Source Code (Use browser search to find items of interest.)
Class Index
kdelibs'KDirWatch (./kdelibs/kio/kdirwatch.h:53)
class KDirWatch : public QObject
{
Q_OBJECT
public:
/**
* Constructor. Does not begin with scanning until @ref startScan
* is called. Default frequency is 500 ms. The created list of
* directories has deep copies.
*/
KDirWatch ( int freq = 500 );
/**
* Destructor. Stops scanning and cleans up.
*/
~KDirWatch();
/**
* Adds directory to list of directories to be watched. (The list
* makes deep copies).
*/
void addDir(const QString& path);
/**
* Returns the time the directory was last changed.
*/
time_t ctime(const QString& path);
/**
* Removes directory from list of scanned directories. If specified
* path is not in the list, does nothing.
*/
void removeDir(const QString& path);
/**
* Stops scanning for specified path. Does not delete dir from list,
* just skips it. Call this function when you make an huge operation
* on this directory (copy/move big files or lot of files). When finished,
* call @ref #restartDirScan (path).
* Returns 'false' if specified path is not in list, 'true' otherwise.
*/
bool stopDirScan(const QString& path);
/**
* Restarts scanning for specified path. Resets ctime. It doesn't notify
* the change, since ctime value is reset. Call it when you are finished
* with big operations on that path, *and* when *you* have refreshed that
* path.
* Returns 'false' if specified path is not in list, 'true' otherwise.
*/
bool restartDirScan(const QString& path);
/**
* Starts scanning of all dirs in list. If notify is true, all changed
* dirs (since @ref #stopScan call) will be notified for refresh. If
* notify is false, all ctimes will be reset (except those who are stopped,
* but only if skippedToo is false) and changed dirs won't be
* notified. You can start scanning even if the list is empty. First call
* should be called with 'false' or else all dirs in list will be notified.
* Note that direcories that were.
* If 'skippedToo' is true, the skipped dirs, (scanning of which was
* stopped with @ref #stopDirScan ) will be reset and notified for change.
* Otherwise, stopped dirs will continue to be unnotified.
*/
void startScan( bool notify=false, bool skippedToo=false );
/**
* Stops scanning of all dirs in list. List is not cleared, just the
* timer is stopped.
*/
void stopScan();
bool contains( const QString& path ) const;
/** @see signal fileDirty */
void setFileDirty( const QString & _file );
static KDirWatch* self();
signals:
/**
* This signal is emited when directory is changed. The new ctime is set
* before the signal is emited.
*/
void dirty (const QString& dir);
/**
* This signal is emited when KDirWatch learns that the file
* _file has changed. This happens for instance when a .desktop file
* gets a new icon - but this isn't automatic, one has to call
* setFileDirty() for this signal to be emitted.
*/
void fileDirty (const QString& _file);
/**
* This signal is emited when directory is deleted. When you receive
* this signal, directory is not yet deleted from the list. You will
* receive this signal only once, because one directory cannot be
* deleted more than once. Please, forget the last^H^H^H^Hprevious
* sentence.
*/
void deleted (const QString& dir);
protected:
void resetList (bool reallyall);
protected slots:
void slotRescan();
void famEventReceived();
private:
struct Entry
{
time_t m_ctime;
int m_clients;
#ifdef USE_FAM
FAMRequest fr;
#endif
};
QTimer *timer;
QMap<QString,Entry> m_mapDirs;
int freq;
struct stat statbuff;
static KDirWatch* s_pSelf;
#ifdef USE_FAM
QSocketNotifier *sn;
FAMConnection fc;
FAMEvent fe;
int use_fam;
bool emitEvents;
#endif
};
kdelibs'KDirWatch::self() (./kdelibs/kio/kdirwatch.cpp:45)
KDirWatch* KDirWatch::self()
{
if ( !s_pSelf )
s_pSelf = new KDirWatch;
return s_pSelf;
}
kdelibs'KDirWatch::KDirWatch() (./kdelibs/kio/kdirwatch.cpp:52)
KDirWatch::KDirWatch (int _freq)
{
timer = new QTimer(this);
connect (timer, SIGNAL(timeout()), this, SLOT(slotRescan()));
freq = _freq;
#ifdef USE_FAM
// It's possible that FAM server can't be started
if (FAMOpen(&fc) ==0) {
qDebug("KDirWatch: Using FAM");
use_fam=1;
emitEvents = true;
sn = new QSocketNotifier( FAMCONNECTION_GETFD(&fc),
QSocketNotifier::Read, this);
connect( sn, SIGNAL(activated(int)),
this, SLOT(famEventReceived()) );
}
else {
qDebug("KDirWatch: Can't use FAM");
use_fam=0;
}
#endif
}
kdelibs'KDirWatch::~KDirWatch() (./kdelibs/kio/kdirwatch.cpp:77)
KDirWatch::~KDirWatch()
{
timer->stop();
// delete timer; timer was created with 'this' as parent!
#ifdef USE_FAM
if (use_fam) {
FAMClose(&fc);
qDebug("KDirWatch deleted (FAM closed)");
}
#endif
}
kdelibs'KDirWatch::addDir() (./kdelibs/kio/kdirwatch.cpp:90)
void KDirWatch::addDir( const QString& _path )
{
QString path = _path;
if ( path.right(1) == "/" )
path.truncate( path.length() - 1 );
QMap<QString,Entry>::Iterator it = m_mapDirs.find( path );
if ( it != m_mapDirs.end() )
{
(*it).m_clients++;
return;
}
stat( QFile::encodeName(path), &statbuff );
Entry e;
e.m_clients = 1;
e.m_ctime = statbuff.st_ctime;
#ifdef USE_FAM
if (use_fam) {
FAMMonitorDirectory(&fc, QFile::encodeName(path), &(e.fr), 0);
// qDebug("KDirWatch added %s -> FAMReq %d",
// QFile::encodeName(path), FAMREQUEST_GETREQNUM(&(e.fr)) );
}
#endif
m_mapDirs.insert( path, e );
#ifdef USE_FAM
// if FAM server can't be used, fall back to good old timer...
if (!use_fam)
#endif
if ( m_mapDirs.count() == 1 ) // if this was first entry (=timer was stopped)
timer->start(freq); // then start the timer
}
kdelibs'KDirWatch::ctime() (./kdelibs/kio/kdirwatch.cpp:129)
time_t KDirWatch::ctime( const QString &_path )
{
if ( m_mapDirs.isEmpty() )
return 0;
QString path = _path;
if ( path.right(1) == "/" )
path.truncate( path.length() - 1 );
QMap<QString,Entry>::Iterator it = m_mapDirs.find( path );
if ( it == m_mapDirs.end() )
return 0;
return (*it).m_ctime;
}
kdelibs'KDirWatch::removeDir() (./kdelibs/kio/kdirwatch.cpp:146)
void KDirWatch::removeDir( const QString& _path )
{
if ( m_mapDirs.isEmpty() )
return;
QString path = _path;
if ( path.right(1) == "/" )
path.truncate( path.length() - 1 );
QMap<QString,Entry>::Iterator it = m_mapDirs.find( path );
if ( it == m_mapDirs.end() )
return;
(*it).m_clients--;
if ( (*it).m_clients > 0 )
return;
#ifdef USE_FAM
if (use_fam) {
FAMCancelMonitor(&fc, &((*it).fr) );
// qDebug("KDirWatch deleted: %s (FAMReq %d)",
// QFile::encodeName(path), FAMREQUEST_GETREQNUM(&((*it).fr)) );
}
#endif
m_mapDirs.remove( it );
#ifdef USE_FAM
if (!use_fam)
#endif
if( m_mapDirs.isEmpty() )
timer->stop(); // stop timer if list empty
}
kdelibs'KDirWatch::stopDirScan() (./kdelibs/kio/kdirwatch.cpp:181)
bool KDirWatch::stopDirScan( const QString& _path )
{
if ( m_mapDirs.isEmpty() )
return false;
QString path = _path;
if ( path.right(1) == "/" )
path.truncate( path.length() - 1 );
QMap<QString,Entry>::Iterator it = m_mapDirs.find( path );
if ( it == m_mapDirs.end() )
return false;
(*it).m_ctime = NO_NOTIFY;
#ifdef USE_FAM
if (use_fam) {
FAMSuspendMonitor(&fc, &((*it).fr) );
}
#endif
return true;
}
kdelibs'KDirWatch::restartDirScan() (./kdelibs/kio/kdirwatch.cpp:205)
bool KDirWatch::restartDirScan( const QString& _path )
{
if ( m_mapDirs.isEmpty() )
return false;
QString path = _path;
if ( path.right(1) == "/" )
path.truncate( path.length() - 1 );
QMap<QString,Entry>::Iterator it = m_mapDirs.find( path );
if ( it == m_mapDirs.end() )
return false;
stat( QFile::encodeName(path), &statbuff );
(*it).m_ctime = statbuff.st_ctime;
#ifdef USE_FAM
if (use_fam) {
FAMResumeMonitor(&fc, &((*it).fr) );
}
#endif
return true;
}
kdelibs'KDirWatch::stopScan() (./kdelibs/kio/kdirwatch.cpp:230)
void KDirWatch::stopScan()
{
#ifdef USE_FAM
if (use_fam)
emitEvents = false;
else
#endif
timer->stop();
}
kdelibs'KDirWatch::startScan() (./kdelibs/kio/kdirwatch.cpp:240)
void KDirWatch::startScan( bool notify, bool skippedToo )
{
if (!notify)
resetList(skippedToo);
#ifdef USE_FAM
if (use_fam)
emitEvents = true;
else
#endif
timer->start(freq);
}
// Protected:
kdelibs'KDirWatch::resetList() (./kdelibs/kio/kdirwatch.cpp:254)
void KDirWatch::resetList( bool skippedToo )
{
if ( m_mapDirs.isEmpty() )
return;
QMap<QString,Entry>::Iterator it = m_mapDirs.begin();
for( ; it != m_mapDirs.end(); ++it )
{
if ( (*it).m_ctime != NO_NOTIFY || skippedToo )
{
stat( QFile::encodeName(it.key()), &statbuff );
(*it).m_ctime = statbuff.st_ctime;
}
}
}
kdelibs'KDirWatch::slotRescan() (./kdelibs/kio/kdirwatch.cpp:270)
void KDirWatch::slotRescan()
{
QStringList del;
QMap<QString,Entry>::Iterator it = m_mapDirs.begin();
for( ; it != m_mapDirs.end(); ++it )
{
if ( stat( QFile::encodeName(it.key()), &statbuff ) == -1 )
{
kdDebug(7001) << "Deleting " << it.key() << endl;
emit deleted( it.key() );
del.append( it.key() );
continue; // iterator incremented
}
if ( statbuff.st_ctime != (*it).m_ctime &&
(*it).m_ctime != NO_NOTIFY)
{
(*it).m_ctime = statbuff.st_ctime;
qDebug("KDirWatch emitting dirty");
emit dirty( it.key() );
}
}
QStringList::Iterator it2 = del.begin();
for( ; it2 != del.end(); ++it2 )
m_mapDirs.remove( *it2 );
}
kdelibs'KDirWatch::contains() (./kdelibs/kio/kdirwatch.cpp:298)
bool KDirWatch::contains( const QString& _path ) const
{
QString path = _path;
if ( path.right(1) == "/" )
path.truncate( path.length() - 1 );
return m_mapDirs.contains( path );
}
kdelibs'KDirWatch::setFileDirty() (./kdelibs/kio/kdirwatch.cpp:307)
void KDirWatch::setFileDirty( const QString & _file )
{
emit fileDirty( _file );
}
kdelibs'KDirWatch::famEventReceived() (./kdelibs/kio/kdirwatch.cpp:313)
void KDirWatch::famEventReceived()
{
if (!use_fam || !emitEvents) return;
FAMNextEvent(&fc, &fe);
int reqNum = FAMREQUEST_GETREQNUM(&(fe.fr));
// Don't be too verbose ;-)
if (fe.code == FAMExists || fe.code == FAMEndExist) return;
qDebug("KDirWatch processing FAM event (%s, %s, Req %d)",
(fe.code == FAMChanged) ? "FAMChanged" :
(fe.code == FAMDeleted) ? "FAMDeleted" :
(fe.code == FAMStartExecuting) ? "FAMStartExecuting" :
(fe.code == FAMStopExecuting) ? "FAMStopExecuting" :
(fe.code == FAMCreated) ? "FAMCreated" :
(fe.code == FAMMoved) ? "FAMMoved" :
(fe.code == FAMAcknowledge) ? "FAMAcknowledge" :
(fe.code == FAMExists) ? "FAMExists" :
(fe.code == FAMEndExist) ? "FAMEndExist" : "Unkown Code",
&(fe.filename[0]), reqNum );
if (fe.code == FAMDeleted) {
QMap<QString,Entry>::Iterator it = m_mapDirs.begin();
for( ; it != m_mapDirs.end(); ++it )
if ( FAMREQUEST_GETREQNUM( &((*it).fr) ) == reqNum ) {
if (fe.filename[0] == '/') {
qDebug("KDirWatch emitting deleted");
emit deleted ( it.key() );
m_mapDirs.remove( it.key() );
}
else {
qDebug("KDirWatch emitting dirty");
emit dirty( it.key() );
}
return;
}
}
else if (fe.code == FAMChanged || fe.code == FAMCreated) {
QMap<QString,Entry>::Iterator it = m_mapDirs.begin();
for( ; it != m_mapDirs.end(); ++it )
if ( FAMREQUEST_GETREQNUM( &((*it).fr) ) == reqNum ) {
qDebug("KDirWatch emitting dirty");
emit dirty( it.key() );
return;
}
}
}
kdelibs'KDirWatch::famEventReceived() (./kdelibs/kio/kdirwatch.cpp:363)
void KDirWatch::famEventReceived() {}
#endif
#include "kdirwatch.moc"
//sven