/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ #include #include #include #include #include #include #include #include #include #include "smdirwatcher.h" #include "smtreeitem.h" #include "helper.h" extern int errno; SmDirWatcher::SmDirWatcher(QObject *parent) : QThread(parent), mFd(0), mDescr(0) { mFd = inotify_init1(IN_NONBLOCK); } SmDirWatcher::~SmDirWatcher(){ if(mFd && mDescr){ inotify_rm_watch(mFd, mDescr); } } void SmDirWatcher::setDir(const QString &dir){ QMutexLocker lock(&mWatchMx); if(mDescr){ inotify_rm_watch(mFd, mDescr); //generates IN_IGNORE ??? } /* mask rationale: * IN_DELETE_SELF cannot happen since we're only * watching one directory at all time. * We don't care about the other events */ mDescr = inotify_add_watch(mFd, qPrintable(dir), IN_CLOSE_WRITE | IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVED_FROM | IN_MOVED_TO); mCurrent = dir; } void SmDirWatcher::run(){ QMutexLocker lock(&mWatchMx); QVarLengthArray data(4096); int r = read(mFd, data.data(), data.size()); int err = errno; if(r < 0){ if(err != EAGAIN){ return; } r = read(mFd, data.data(), data.size()); } // inspect data char *at = data.data(); inotify_event *e = reinterpret_cast(at); if(!e->len){ return; } char *end = at + data.size(); while(at < end){ if(e->mask & IN_IGNORED){ at += sizeof(inotify_event) + e->len; continue; } quint32 mask = e->mask; QString name = QString("%1/%2").arg(mCurrent).arg(e->name); at += sizeof(inotify_event) + e->len; if(mask & IN_CREATE){ emit dwEvent(name, Added); return; } if(mask & IN_DELETE){ emit dwEvent(name, Deleted); return; } if(mask & IN_CLOSE_WRITE || e->mask & IN_MODIFY){ emit dwEvent(name, Modified); return; } if(mask & IN_MOVED_FROM || e->mask & IN_MOVED_TO){ emit needRefresh(); return; } } } SmDataGatherer::SmDataGatherer(const int numFields, QObject *parent) : QThread(parent), mNumFields(numFields) {} void SmDataGatherer::setCurrent(const QString ¤t, int mode){ QMutexLocker lock(&mSetMx); mCurrent = current; mMode = mode; } void SmDataGatherer::run(){ QMutexLocker lock(&mRunMx); QFileInfo fi(mCurrent); if(fi.isDir()){ SmTreeItem *rv = populate(); emit population(rv); return; } if(fi.isFile()){ QList fd = fileData(fi); emit newData(fd, mMode); } } SmTreeItem * SmDataGatherer::populate(){ SmTreeItem *retval = new SmTreeItem(mNumFields); QDir d = QDir(mCurrent); foreach(QFileInfo fi, d.entryInfoList()){ if(fi.fileName() == "."){ continue; } QList data = fileData(fi); SmTreeItem *newItem = new SmTreeItem(data, retval); retval->appendChild(newItem); } return retval; } const QList SmDataGatherer::fileData(const QFileInfo &fi) const{ QList data; data << fi.fileName() << fi.size(); QString mime = Helper::mimeType(fi.absoluteFilePath()); data << mime; data << fi.lastModified(); QList si = QList() << QVariant() << QVariant(); if(mime.startsWith("video")){ si = Helper::duration(fi.absoluteFilePath()); } data << Helper::md5Sum(fi.absoluteFilePath()); data << si << fi.absoluteFilePath(); return data; }