diff options
author | Arno <am@disconnect.de> | 2013-03-20 21:27:35 +0100 |
---|---|---|
committer | Arno <am@disconnect.de> | 2013-03-20 21:27:35 +0100 |
commit | 03831d3669ea49a99a15aaf5d17724be8c533b85 (patch) | |
tree | 618e3fe63b0430a4dbe604153ab588eb811fd183 | |
parent | 457e5328c8fbbf236fb163e90d732a35a583fd2d (diff) | |
download | SheMov-03831d3669ea49a99a15aaf5d17724be8c533b85.tar.gz SheMov-03831d3669ea49a99a15aaf5d17724be8c533b85.tar.bz2 SheMov-03831d3669ea49a99a15aaf5d17724be8c533b85.zip |
Use a Thread for collecting file data
blocking the GUI isn't nice, so use a separate Thread to gather all the
data for SmDirModel. Populating and changing directory works, but
modifying a file is most likely broken.
-rw-r--r-- | filesystemwidget.cpp | 16 | ||||
-rw-r--r-- | shemov.cpp | 2 | ||||
-rw-r--r-- | smdirmodel.cpp | 32 | ||||
-rw-r--r-- | smdirmodel.h | 9 | ||||
-rw-r--r-- | smdirwatcher.cpp | 96 | ||||
-rw-r--r-- | smdirwatcher.h | 32 |
6 files changed, 135 insertions, 52 deletions
diff --git a/filesystemwidget.cpp b/filesystemwidget.cpp index 4b7a9c7..b842541 100644 --- a/filesystemwidget.cpp +++ b/filesystemwidget.cpp @@ -8,7 +8,6 @@ #include <QtWidgets/QFileSystemModel> #include <QtWidgets/QTreeView> #include <QSettings> -#include <QDir> #include <QtWidgets/QSplitter> #include <QtWidgets/QVBoxLayout> #include <QtWidgets/QHBoxLayout> @@ -18,16 +17,12 @@ #include <QProcess> #include <QtWidgets/QApplication> #include <QtWidgets/QMessageBox> -#include <QFile> #include <QtWidgets/QAction> -#include <QRegExp> -#include <QFile> #include <QTextStream> #include <QSqlQuery> #include <QClipboard> #include <QMimeData> #include <QUrl> -#include <QList> #include "filesystemwidget.h" #include "filesystemdirproxy.h" @@ -40,13 +35,17 @@ #include "smdirmodel.h" FilesystemWidget::FilesystemWidget(QWidget *parent) : QWidget(parent), mClipboardMode(None) { - mModel = new FileSystemModel(this); + mModel = new FileSystemModel(this); mModel->setRootPath("/"); mModel->setFilter(QDir::AllEntries | QDir::NoDot); mModel->setReadOnly(false); mIconProvider = new SheMovIconProvider; mModel->setIconProvider(mIconProvider); + QStringList fHeaders = QStringList() << tr("Name") << tr("Size") << tr("Type") << tr("Created") << tr("Md5Sum") << tr("Duration") << tr("Bitrate") << tr("Full Path"); + mFileModel = new SmDirModel(fHeaders, this); + connect(mFileModel, SIGNAL(needResize()), this, SLOT(resizeFileView())); + mDirProxy = new FilesystemDirProxy; mDirProxy->setSourceModel(mModel); mDirView = new QTreeView; @@ -64,9 +63,7 @@ FilesystemWidget::FilesystemWidget(QWidget *parent) : QWidget(parent), mClipboar mFileView = new FileView; mFileProxy = new FilesystemFileProxy; - QStringList fHeaders = QStringList() << tr("Name") << tr("Size") << tr("Type") << tr("Created") << tr("Md5Sum") << tr("Duration") << tr("Bitrate") << tr("Full Path"); - mFileModel = new SmDirModel(fHeaders, this); - connect(mFileModel, SIGNAL(needResize()), this, SLOT(resizeFileView())); + mFileProxy->setSourceModel(mFileModel); mFileView->setModel(mFileProxy); mFileView->setSortingEnabled(true); @@ -114,7 +111,6 @@ FilesystemWidget::FilesystemWidget(QWidget *parent) : QWidget(parent), mClipboar splitter->setStretchFactor(0, 1); splitter->setStretchFactor(1, 2); mainLayout->addWidget(splitter); - setLayout(mainLayout); } @@ -147,7 +147,7 @@ SheMov::SheMov(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, fla splash.finish(this); mATree->seriesWidget()->readSettings(); mATree->filesWidget()->filesTree()->readSettings(); - mFSWidget->readSettings(); + mFSWidget->readSettings(); readSettings(); mFSWidget->fileView()->setFocus(Qt::ActiveWindowFocusReason); mATree->filesWidget()->filesTree()->header()->resizeSections(QHeaderView::ResizeToContents); diff --git a/smdirmodel.cpp b/smdirmodel.cpp index cf2197a..914acff 100644 --- a/smdirmodel.cpp +++ b/smdirmodel.cpp @@ -21,14 +21,18 @@ #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(populate())); + connect(mWatch, SIGNAL(needRefresh()), this, SLOT(refresh())); mRunTimer = new QTimer(this); mRunTimer->setInterval(2000); connect(mRunTimer, SIGNAL(timeout()), mWatch, SLOT(start())); mRunTimer->start(); readSettings(); + + connect(mCollector, SIGNAL(population(SmTreeItem*)), this, SLOT(populate(SmTreeItem*))); } SmDirModel::~SmDirModel(){ @@ -112,13 +116,10 @@ QFileInfo SmDirModel::fileInfo(const QModelIndex &idx) const { } void SmDirModel::setDir(const QString &dir){ - QFileInfo fi(dir); - if(!fi.isDir()){ - return; - } - mCur = dir; - populate(); - mWatch->setDir(dir); + mCurrentDir = dir; + mCollector->setCurrent(mCurrentDir); + mCollector->start(); + mWatch->setDir(mCurrentDir); } void SmDirModel::dirEvent(const QString &file, int e){ @@ -154,20 +155,11 @@ void SmDirModel::readSettings(){ } void SmDirModel::refresh(){ - populate(); + mCollector->setCurrent(mCurrentDir); + mCollector->start(); } -void SmDirModel::populate(){ - SmTreeItem *root = new SmTreeItem(mHeaders.size()); - QDir d = QDir(mCur); - foreach(QFileInfo fi, d.entryInfoList()){ - if(fi.fileName() == "."){ - continue; - } - QList<QVariant> data = fileData(fi); - SmTreeItem *n = new SmTreeItem(data, root); - root->appendChild(n); - } +void SmDirModel::populate(SmTreeItem *root){ setRoot(root); emit needResize(); } diff --git a/smdirmodel.h b/smdirmodel.h index 3712cba..c8cc69c 100644 --- a/smdirmodel.h +++ b/smdirmodel.h @@ -23,12 +23,15 @@ class SmDirWatcher; class QTimer; class SmTreeItem; +class QMutex; +class SmDataGatherer; class SmDirModel : public SmTreeModel { Q_OBJECT public: enum CustomRoles { NameRole = Qt::UserRole + 1, SizeRole = Qt::UserRole + 2, TypeRole = Qt::UserRole + 3, CreatedRole = Qt::UserRole + 4, Md5sumRole = Qt::UserRole + 5, DurationRole = Qt::UserRole + 6, BitrateRole = Qt::UserRole + 7, FullPathRole = Qt::UserRole + 8 }; enum Fields { Name = 0, Size = 1, Type = 2, Created = 3, Md5sum = 4, Duration = 5, Bitrate = 6, FullPath = 7 }; + enum { NumFields = 8 }; enum FileDate { Access, Modified, Status }; explicit SmDirModel(const QStringList &headers, QObject *parent = 0); ~SmDirModel(); @@ -36,7 +39,6 @@ class SmDirModel : public SmTreeModel { virtual bool setData(const QModelIndex &index, const QVariant &value, int role); bool isDir(const QModelIndex &idx) const; QFileInfo fileInfo(const QModelIndex &idx) const; - QDir dir() const { return QDir(mCur); }; public slots: void setDir(const QString &dir); @@ -45,7 +47,7 @@ class SmDirModel : public SmTreeModel { void refresh(); private slots: - void populate(); + void populate(SmTreeItem *root); signals: void needResize(); @@ -54,9 +56,12 @@ class SmDirModel : public SmTreeModel { const QList<QVariant> fileData(const QFileInfo &fi) const; SmDirWatcher *mWatch; QStringList mHeaders; + QString mCurrentDir; QString mCur; QTimer *mRunTimer; QMap<QString, QIcon> mIcons; + QMutex *mCollectorMx; + SmDataGatherer *mCollector; }; #endif // SMDIRMODEL_H diff --git a/smdirwatcher.cpp b/smdirwatcher.cpp index 78dae2a..8650d3b 100644 --- a/smdirwatcher.cpp +++ b/smdirwatcher.cpp @@ -7,6 +7,8 @@ #include <QVarLengthArray> #include <QMutexLocker> +#include <QDateTime> +#include <QDir> #include <sys/inotify.h> #include <stropts.h> @@ -15,6 +17,8 @@ #include <errno.h> #include "smdirwatcher.h" +#include "smtreeitem.h" +#include "helper.h" extern int errno; @@ -34,11 +38,11 @@ void SmDirWatcher::setDir(const QString &dir){ inotify_rm_watch(mFd, mDescr); //generates IN_IGNORE ??? } /* mask rationale: - * IN_DELETE_SELF, IN_MOVE_TO and IN_MOVE_FROM cannot happen, - * since we're only watching one directory at all times - * don't care about the other events + * 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); + mDescr = inotify_add_watch(mFd, qPrintable(dir), IN_CLOSE_WRITE | IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVED_FROM | IN_MOVED_TO); mCurrent = dir; } @@ -46,40 +50,94 @@ void SmDirWatcher::run(){ QMutexLocker lock(&mWatchMx); QVarLengthArray<char, 4096> data(4096); int r = read(mFd, data.data(), data.size()); - while(r < 0){ - int err = errno; - // buffer too small - if(err == EINVAL){ - data.resize(data.size() * 2); - r = read(mFd, data.data(), data.size()); - continue; - // dunno - }else{ + 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){ + return; + } char *end = at + data.size(); while(at < end){ - inotify_event *e = reinterpret_cast<inotify_event*>(at); 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); - if(e->mask & IN_CREATE){ + at += sizeof(inotify_event) + e->len; + if(mask & IN_CREATE){ emit dwEvent(name, Added); + return; } - if(e->mask & IN_DELETE){ + if(mask & IN_DELETE){ emit dwEvent(name, Deleted); + return; } - if(e->mask & IN_CLOSE_WRITE || e->mask & IN_MODIFY){ + if(mask & IN_CLOSE_WRITE || e->mask & IN_MODIFY){ emit dwEvent(name, Modified); + return; } - if(e->mask & IN_MOVED_FROM){ + if(mask & IN_MOVED_FROM || e->mask & IN_MOVED_TO){ emit needRefresh(); + return; } - at += sizeof(inotify_event) + e->len; } } + +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<QVariant> 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<QVariant> data = fileData(fi); + SmTreeItem *newItem = new SmTreeItem(data, retval); + retval->appendChild(newItem); + } + return retval; +} + +const QList<QVariant> SmDataGatherer::fileData(const QFileInfo &fi) const{ + QList<QVariant> data; + data << fi.fileName() << fi.size(); + QString mime = Helper::mimeType(fi.absoluteFilePath()); + data << mime; + data << fi.lastModified(); + QList<QVariant> si = QList<QVariant>() << QVariant() << QVariant(); + if(mime.startsWith("video")){ + si = Helper::duration(fi.absoluteFilePath()); + } + data << Helper::md5Sum(fi.absoluteFilePath()); + data << si << fi.absoluteFilePath(); + return data; +} diff --git a/smdirwatcher.h b/smdirwatcher.h index 0da5b4b..3167aeb 100644 --- a/smdirwatcher.h +++ b/smdirwatcher.h @@ -10,6 +10,11 @@ #include <QThread> #include <QMutex> +#include <QList> +#include <QVariant> +#include <QFileInfo> + +class SmTreeItem; class SmDirWatcher : public QThread { Q_OBJECT @@ -33,4 +38,31 @@ class SmDirWatcher : public QThread { QString mCurrent; }; +class SmDataGatherer : public QThread { + Q_OBJECT + public: + explicit SmDataGatherer(const int numFields, QObject *parent = 0); + void setCurrent(const QString ¤t, int mode = -1); + + public slots: + void run(); + //void setFile(const QString &fullPath, int event); + //void populate(const QString &dir); + + signals: + void newData(const QList<QVariant>,int); + void population(SmTreeItem*); + void needRefresh(); + + private: + //QList<QList<QVariant> > populate(); + SmTreeItem *populate(); + const QList<QVariant> fileData(const QFileInfo &fi) const; + QString mCurrent; + QMutex mRunMx; + QMutex mSetMx; + int mMode; + const int mNumFields; +}; + #endif // SMDIRWATCHER_H |