diff options
-rw-r--r-- | filesystemfileproxy.cpp | 7 | ||||
-rw-r--r-- | filesystemwidget.cpp | 2 | ||||
-rw-r--r-- | helper.cpp | 10 | ||||
-rw-r--r-- | smdirmodel.cpp | 51 | ||||
-rw-r--r-- | smdirmodel.h | 16 | ||||
-rw-r--r-- | smdirwatcher.cpp | 107 | ||||
-rw-r--r-- | smdirwatcher.h | 30 | ||||
-rw-r--r-- | smtreemodel.cpp | 6 |
8 files changed, 127 insertions, 102 deletions
diff --git a/filesystemfileproxy.cpp b/filesystemfileproxy.cpp index b45b740..249eeb4 100644 --- a/filesystemfileproxy.cpp +++ b/filesystemfileproxy.cpp @@ -11,8 +11,7 @@ #include <QFileInfo> #include <QDateTime> #include <QFont> - -#include <QDebug> +#include <QLocale> #include "filesystemfileproxy.h" #include "smdirmodel.h" @@ -21,9 +20,9 @@ FilesystemFileProxy::FilesystemFileProxy(QObject *parent) : QSortFilterProxyModel(parent) {} QVariant FilesystemFileProxy::data(const QModelIndex &index, int role) const{ - if(!index.isValid()){ + if(!index.isValid()){ return QVariant(); - } + } SmDirModel *source = qobject_cast<SmDirModel*>(sourceModel()); if(role == Qt::DisplayRole){ QModelIndex real = mapToSource(index); diff --git a/filesystemwidget.cpp b/filesystemwidget.cpp index b842541..5f462e8 100644 --- a/filesystemwidget.cpp +++ b/filesystemwidget.cpp @@ -65,7 +65,7 @@ FilesystemWidget::FilesystemWidget(QWidget *parent) : QWidget(parent), mClipboar mFileProxy = new FilesystemFileProxy; mFileProxy->setSourceModel(mFileModel); - mFileView->setModel(mFileProxy); + mFileView->setModel(mFileProxy); mFileView->setSortingEnabled(true); mFileView->sortByColumn(0, Qt::AscendingOrder); mFileView->setItemsExpandable(false); @@ -68,7 +68,9 @@ namespace Helper { QByteArray data(4096, '\0'); do { read = file.read(data.data(), 4096); - h.addData(data.data(), read); + if(read > 0){ + h.addData(data.data(), read); + } } while (read == 4096); QByteArray res = h.result(); retval = res.toHex().toLower(); @@ -214,7 +216,7 @@ namespace Helper { QSettings s; QString ffProbe = s.value("paths/ffprobe").toString(); QStringList args; - QList<QVariant> retval; + QList<QVariant> retval = QList<QVariant>() << QVariant() << QVariant(); args << "-show_streams" << path; QProcess ffproc; ffproc.start(ffProbe, args); @@ -229,9 +231,9 @@ namespace Helper { QString llc = l.toLower(); if(llc.contains("duration")){ int idx = llc.indexOf("duration:"); - retval << llc.mid(idx + 10, 8); + retval[0] = llc.mid(idx + 10, 8); idx = llc.indexOf("bitrate:"); - retval << llc.mid(idx + 9); + retval[1] = llc.mid(idx + 9); break; } } diff --git a/smdirmodel.cpp b/smdirmodel.cpp index 914acff..d24fdef 100644 --- a/smdirmodel.cpp +++ b/smdirmodel.cpp @@ -5,14 +5,9 @@ 2 of the License, or (at your option) any later version. */ -#include <QDir> #include <QDateTime> -#include <QFile> #include <QTimer> #include <QSettings> -#include <QHash> - -#include <sys/stat.h> #include "smdirmodel.h" #include "smdirwatcher.h" @@ -21,10 +16,7 @@ #include "helper.h" SmDirModel::SmDirModel(const QStringList &headers, QObject *parent) : SmTreeModel(headers, parent), mHeaders(headers){ - mCollector = new SmDataGatherer(NumFields, this); - mWatch = new SmDirWatcher(this); - connect(mWatch, SIGNAL(dwEvent(QString,int)), this, SLOT(dirEvent(QString,int))); connect(mWatch, SIGNAL(needRefresh()), this, SLOT(refresh())); mRunTimer = new QTimer(this); mRunTimer->setInterval(2000); @@ -32,7 +24,9 @@ SmDirModel::SmDirModel(const QStringList &headers, QObject *parent) : SmTreeMode mRunTimer->start(); readSettings(); + mCollector = mWatch->collector(); connect(mCollector, SIGNAL(population(SmTreeItem*)), this, SLOT(populate(SmTreeItem*))); + connect(mCollector, SIGNAL(newData(QList<QVariant>,int)), this, SLOT(dirEvent(QList<QVariant>,int)), Qt::BlockingQueuedConnection); } SmDirModel::~SmDirModel(){ @@ -84,6 +78,7 @@ bool SmDirModel::setData(const QModelIndex &index, const QVariant &value, int ro return false; } if(role == Qt::EditRole && index.column() == Name){ + //this is a rename QString newName = value.toString(); if(newName.contains(QDir::separator())){ return false; @@ -94,6 +89,8 @@ bool SmDirModel::setData(const QModelIndex &index, const QVariant &value, int ro QString newPath = QString("%1/%2").arg(dir).arg(newName); QFile::rename(old, newPath); emit needResize(); + // watcher->collector will do the rest + return true; } return SmTreeModel::setData(index, value, role); } @@ -107,6 +104,10 @@ bool SmDirModel::isDir(const QModelIndex &idx) const { return fi.isDir(); } +QDir SmDirModel::dir() const{ + return QDir(mCurrentDir); +} + QFileInfo SmDirModel::fileInfo(const QModelIndex &idx) const { if(!idx.isValid()){ return QFileInfo(); @@ -117,25 +118,26 @@ QFileInfo SmDirModel::fileInfo(const QModelIndex &idx) const { void SmDirModel::setDir(const QString &dir){ mCurrentDir = dir; - mCollector->setCurrent(mCurrentDir); mCollector->start(); mWatch->setDir(mCurrentDir); } -void SmDirModel::dirEvent(const QString &file, int e){ - QFileInfo fi(file); - const QList<QVariant> fData = fileData(fi); +void SmDirModel::dirEvent(const QList<QVariant> &data, int e){ if(e == SmDirWatcher::Added){ - addRow(fData, rootIndex(), true); + /* for some reason SmTreeModel::addRow() doesn't work, + * couldn't figure it out in 5 hours, so customize it + * and reset the model + */ + addFile(data); } - QModelIndex idx = find(fData.at(Name), Name, rootIndex()); + QModelIndex idx = find(data.at(Name), Name, rootIndex()); if(e == SmDirWatcher::Deleted){ removeRow(idx.row()); } if(e == SmDirWatcher::Modified){ for(int i = 0; i < mHeaders.count(); ++i){ QModelIndex c = index(idx.row(), i, QModelIndex()); - setData(c, fData.at(i), Qt::EditRole); + setData(c, data.at(i), Qt::EditRole); } } emit needResize(); @@ -155,8 +157,6 @@ void SmDirModel::readSettings(){ } void SmDirModel::refresh(){ - mCollector->setCurrent(mCurrentDir); - mCollector->start(); } void SmDirModel::populate(SmTreeItem *root){ @@ -164,6 +164,23 @@ void SmDirModel::populate(SmTreeItem *root){ emit needResize(); } +void SmDirModel::addFile(const QList<QVariant> &data){ + SmTreeItem *newItem = new SmTreeItem(data, root()); + int w = root()->childCount(); + int i = 0; + while(i < root()->childCount()){ + if(newItem->data(Name).toString().toLower() < root()->child(i)->data(Name).toString().toLower()){ + w = i; + break; + } + ++i; + } + beginResetModel(); + root()->insertChild(w, newItem); + endResetModel(); + return; +} + const QList<QVariant> SmDirModel::fileData(const QFileInfo &fi) const{ QList<QVariant> data; data << fi.fileName() << fi.size(); diff --git a/smdirmodel.h b/smdirmodel.h index c8cc69c..2db790b 100644 --- a/smdirmodel.h +++ b/smdirmodel.h @@ -8,13 +8,6 @@ #ifndef SMDIRMODEL_H #define SMDIRMODEL_H -#include <QStringList> -#include <QVariant> -#include <QModelIndex> -#include <QList> -#include <QFileInfo> -#include <QMap> -#include <QIcon> #include <QDir> #include <smtreemodel.h> @@ -24,7 +17,7 @@ class SmDirWatcher; class QTimer; class SmTreeItem; class QMutex; -class SmDataGatherer; +class SmDataColletor; class SmDirModel : public SmTreeModel { Q_OBJECT @@ -38,16 +31,19 @@ class SmDirModel : public SmTreeModel { virtual QVariant data(const QModelIndex &index, int role) const; virtual bool setData(const QModelIndex &index, const QVariant &value, int role); bool isDir(const QModelIndex &idx) const; + QDir dir() const; QFileInfo fileInfo(const QModelIndex &idx) const; + public slots: void setDir(const QString &dir); - void dirEvent(const QString &file, int e); + void dirEvent(const QList<QVariant> &data, int e); void readSettings(); void refresh(); private slots: void populate(SmTreeItem *root); + void addFile(const QList<QVariant> &data); signals: void needResize(); @@ -61,7 +57,7 @@ class SmDirModel : public SmTreeModel { QTimer *mRunTimer; QMap<QString, QIcon> mIcons; QMutex *mCollectorMx; - SmDataGatherer *mCollector; + SmDataColletor *mCollector; }; #endif // SMDIRMODEL_H diff --git a/smdirwatcher.cpp b/smdirwatcher.cpp index 8650d3b..8b72aab 100644 --- a/smdirwatcher.cpp +++ b/smdirwatcher.cpp @@ -9,6 +9,7 @@ #include <QMutexLocker> #include <QDateTime> #include <QDir> +#include <QSemaphore> #include <sys/inotify.h> #include <stropts.h> @@ -23,17 +24,26 @@ extern int errno; SmDirWatcher::SmDirWatcher(QObject *parent) : QThread(parent), mFd(0), mDescr(0) { - mFd = inotify_init1(IN_NONBLOCK); + mBufLen = 1024 * (sizeof(struct inotify_event) + 16); + mINdata = new char[mBufLen]; + mFd = inotify_init(); + + mCollector = new SmDataColletor(8, this); + mSemFree = new QSemaphore(1024); + mSemUsed = new QSemaphore; + mDataQueue = new QQueue<QPair<QString, DWEvent> >(); + mCollector->init(mSemFree, mSemUsed, mDataQueue); + mCollector->start(); } SmDirWatcher::~SmDirWatcher(){ if(mFd && mDescr){ inotify_rm_watch(mFd, mDescr); } + delete mINdata; } void SmDirWatcher::setDir(const QString &dir){ - QMutexLocker lock(&mWatchMx); if(mDescr){ inotify_rm_watch(mFd, mDescr); //generates IN_IGNORE ??? } @@ -44,78 +54,73 @@ void SmDirWatcher::setDir(const QString &dir){ */ mDescr = inotify_add_watch(mFd, qPrintable(dir), IN_CLOSE_WRITE | IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVED_FROM | IN_MOVED_TO); mCurrent = dir; + mSemFree->acquire(); + QPair<QString, DWEvent> c = qMakePair(dir, Populate); + mDataQueue->enqueue(c); + mSemUsed->release(); } void SmDirWatcher::run(){ - QMutexLocker lock(&mWatchMx); - QVarLengthArray<char, 4096> 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<inotify_event*>(at); - if(!e->len){ + int r = read(mFd, mINdata, mBufLen); + if(r <= 0){ return; } - char *end = at + data.size(); - while(at < end){ - if(e->mask & IN_IGNORED){ - at += sizeof(inotify_event) + e->len; + int i = 0; + while(i < r){ + inotify_event *e = reinterpret_cast<inotify_event*>(&mINdata[i]); + if((!e->len) || (e->mask & IN_IGNORED)){ + i += sizeof(inotify_event) + e->len; continue; } + mSemFree->acquire(); 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; + DWEvent curEvent = None; + if(mask & IN_CREATE || mask & IN_MOVED_TO){ + curEvent = Added; } - if(mask & IN_DELETE){ - emit dwEvent(name, Deleted); - return; + if(mask & IN_DELETE || mask & IN_MOVED_FROM){ + curEvent = Deleted; } 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; + curEvent = Modified; } + QPair<QString, DWEvent> c = qMakePair(name, curEvent); + mDataQueue->enqueue(c); + mSemUsed->release(); + i += sizeof(inotify_event) + e->len; } } -SmDataGatherer::SmDataGatherer(const int numFields, QObject *parent) : QThread(parent), mNumFields(numFields) {} +SmDataColletor::SmDataColletor(const int numFields, QObject *parent) : QThread(parent), mSemFree(0), mSemUsed(0), mDataQueue(0), mNumFields(numFields) {} -void SmDataGatherer::setCurrent(const QString ¤t, int mode){ - QMutexLocker lock(&mSetMx); - mCurrent = current; - mMode = mode; +void SmDataColletor::init(QSemaphore *set, QSemaphore *get, QQueue<QPair<QString, SmDirWatcher::DWEvent> > *data){ + mSemFree = set; + mSemUsed = get; + mDataQueue = data; } -void SmDataGatherer::run(){ - QMutexLocker lock(&mRunMx); - QFileInfo fi(mCurrent); - if(fi.isDir()){ - SmTreeItem *rv = populate(); - emit population(rv); - return; - } - if(fi.isFile()){ +void SmDataColletor::run(){ + forever { + mSemUsed->acquire(); + QPair<QString, SmDirWatcher::DWEvent> cur = mDataQueue->dequeue(); + if(cur.second == SmDirWatcher::Populate){ + SmTreeItem *i = populate(cur.first); + emit population(i); + mSemFree->release(); + continue; + + } + QFileInfo fi(cur.first); QList<QVariant> fd = fileData(fi); - emit newData(fd, mMode); + emit newData(fd, cur.second); + mSemFree->release(); } } -SmTreeItem * SmDataGatherer::populate(){ +SmTreeItem * SmDataColletor::populate(const QString &dir){ SmTreeItem *retval = new SmTreeItem(mNumFields); - QDir d = QDir(mCurrent); + QDir d = QDir(dir); foreach(QFileInfo fi, d.entryInfoList()){ if(fi.fileName() == "."){ continue; @@ -127,7 +132,7 @@ SmTreeItem * SmDataGatherer::populate(){ return retval; } -const QList<QVariant> SmDataGatherer::fileData(const QFileInfo &fi) const{ +const QList<QVariant> SmDataColletor::fileData(const QFileInfo &fi) const{ QList<QVariant> data; data << fi.fileName() << fi.size(); QString mime = Helper::mimeType(fi.absoluteFilePath()); diff --git a/smdirwatcher.h b/smdirwatcher.h index 3167aeb..19cd746 100644 --- a/smdirwatcher.h +++ b/smdirwatcher.h @@ -9,18 +9,21 @@ #define SMDIRWATCHER_H #include <QThread> -#include <QMutex> #include <QList> #include <QVariant> #include <QFileInfo> +#include <QQueue> class SmTreeItem; +class QSemaphore; +class SmDataColletor; class SmDirWatcher : public QThread { Q_OBJECT public: - enum DWEvent { Added, Deleted, Modified }; + enum DWEvent { None, Added, Deleted, Modified, Populate }; explicit SmDirWatcher(QObject *parent = 0); + SmDataColletor *collector() { return mCollector; } ~SmDirWatcher(); signals: @@ -34,20 +37,23 @@ class SmDirWatcher : public QThread { private: int mFd; int mDescr; - QMutex mWatchMx; QString mCurrent; + SmDataColletor *mCollector; + QSemaphore *mSemFree; + QSemaphore *mSemUsed; + QQueue<QPair<QString, DWEvent> > *mDataQueue; + char *mINdata; + int mBufLen; }; -class SmDataGatherer : public QThread { +class SmDataColletor : public QThread { Q_OBJECT public: - explicit SmDataGatherer(const int numFields, QObject *parent = 0); - void setCurrent(const QString ¤t, int mode = -1); + explicit SmDataColletor(const int numFields, QObject *parent = 0); + void init(QSemaphore *set, QSemaphore *get, QQueue<QPair<QString, SmDirWatcher::DWEvent> > *data); public slots: void run(); - //void setFile(const QString &fullPath, int event); - //void populate(const QString &dir); signals: void newData(const QList<QVariant>,int); @@ -55,12 +61,12 @@ class SmDataGatherer : public QThread { void needRefresh(); private: - //QList<QList<QVariant> > populate(); - SmTreeItem *populate(); + SmTreeItem *populate(const QString &dir); const QList<QVariant> fileData(const QFileInfo &fi) const; QString mCurrent; - QMutex mRunMx; - QMutex mSetMx; + QSemaphore *mSemFree; + QSemaphore *mSemUsed; + QQueue<QPair<QString, SmDirWatcher::DWEvent> > *mDataQueue; int mMode; const int mNumFields; }; diff --git a/smtreemodel.cpp b/smtreemodel.cpp index c8a0452..4f8ffdc 100644 --- a/smtreemodel.cpp +++ b/smtreemodel.cpp @@ -266,10 +266,10 @@ bool SmTreeModel::addRow(const QList<QVariant> &data, const QModelIndex &parent, } QModelIndex start = index(parentItem->childCount() - 1, 0, parent); QModelIndex end = index(parentItem->childCount() - 1, parentItem->columnCount() - 1, parent); - emit dataChanged(start, end); + emit dataChanged(start, end); return true; - } - return false; + } + return false; } SmTreeItem *SmTreeModel::itemAt(const QModelIndex &index) const{ |