summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--filesystemfileproxy.cpp59
-rw-r--r--filesystemfileproxy.h3
-rw-r--r--filesystemwidget.cpp72
-rw-r--r--filesystemwidget.h2
-rw-r--r--fileview.cpp5
-rw-r--r--helper.cpp29
-rw-r--r--helper.h2
-rw-r--r--shemov.pro8
-rw-r--r--smdirmodel.cpp127
-rw-r--r--smdirmodel.h48
-rw-r--r--smdirwatcher.cpp84
-rw-r--r--smdirwatcher.h35
12 files changed, 400 insertions, 74 deletions
diff --git a/filesystemfileproxy.cpp b/filesystemfileproxy.cpp
index ddf5d86..b45b740 100644
--- a/filesystemfileproxy.cpp
+++ b/filesystemfileproxy.cpp
@@ -10,10 +10,12 @@
#include <QtWidgets/QFileSystemModel>
#include <QFileInfo>
#include <QDateTime>
+#include <QFont>
#include <QDebug>
#include "filesystemfileproxy.h"
+#include "smdirmodel.h"
#include "helper.h"
FilesystemFileProxy::FilesystemFileProxy(QObject *parent) : QSortFilterProxyModel(parent) {}
@@ -22,39 +24,38 @@ QVariant FilesystemFileProxy::data(const QModelIndex &index, int role) const{
if(!index.isValid()){
return QVariant();
}
-
+ SmDirModel *source = qobject_cast<SmDirModel*>(sourceModel());
if(role == Qt::DisplayRole){
- if(index.column() == 2){
- QString filePath = index.data(QFileSystemModel::FilePathRole).toString();
- QString mimeType = Helper::mimeType(filePath);
- if(mimeType.contains('/')){
- mimeType = mimeType.split('/').at(1);
- mimeType = mimeType.remove(QRegExp("^x-"));
- return mimeType;
- }
- }
- if(index.column() == 3){
- QString filePath = index.data(QFileSystemModel::FilePathRole).toString();
- QFileInfo fi(filePath);
- return fi.lastModified().toString("MM-dd-yyyy hh:mm");
+ QModelIndex real = mapToSource(index);
+ QLocale l;
+ if(index.column() == SmDirModel::Created){
+ return real.data().toDateTime().toString("MM-dd-yyyy hh:mm");
}
+ if(index.column() == SmDirModel::Size){
+ if(source->isDir(real)){
+ return QVariant();
+ }
+ return l.toString(real.data().toLongLong());
+ }
+ if(index.column() == SmDirModel::Type){
+ if(source->isDir(real)){
+ return QVariant();
+ }
+ }
}
+ if(role == Qt::TextAlignmentRole){
+ if(index.column() == SmDirModel::Size || index.column() == SmDirModel::Duration || index.column() == SmDirModel::Bitrate){
+ return Qt::AlignRight;
+ }
+ }
+ if(role == Qt::FontRole){
+ if(index.column() == SmDirModel::Md5sum || index.column() == SmDirModel::Duration || index.column() == SmDirModel::Bitrate){
+ return QFont("courier");
+ }
+ }
return QSortFilterProxyModel::data(index, role);
}
-bool FilesystemFileProxy::filterAcceptsRow(int sourcerow, const QModelIndex &sourceparent) const{
- QFileSystemModel *m = static_cast<QFileSystemModel*>(sourceModel());
- QModelIndex idx = m->index(sourcerow, 0, sourceparent);
- if(!idx.isValid()){
- return false;
- }
- QString fName = idx.data().toString();
- if(fName == "." ){
- return false;
- }
- return QSortFilterProxyModel::filterAcceptsRow(sourcerow, sourceparent);
-}
-
bool FilesystemFileProxy::lessThan(const QModelIndex &left, const QModelIndex &right) const {
if(left.model()->headerData(left.column(), Qt::Horizontal).toString() == tr("Name")){
if(left.data().toString() == ".."){
@@ -64,7 +65,7 @@ bool FilesystemFileProxy::lessThan(const QModelIndex &left, const QModelIndex &r
return false;
}
}
- QFileSystemModel *source = static_cast<QFileSystemModel*>(sourceModel());
+ SmDirModel *source = qobject_cast<SmDirModel*>(sourceModel());
if(source->isDir(left) && source->isDir(right)){
return left.data().toString().toLower() < right.data().toString().toLower();
}
@@ -77,7 +78,7 @@ bool FilesystemFileProxy::lessThan(const QModelIndex &left, const QModelIndex &r
return left.data().toString().toLower() < right.data().toString().toLower();
}
if(left.model()->headerData(left.column(), Qt::Horizontal).toString() == tr("Size")){
- QFileSystemModel *source = static_cast<QFileSystemModel*>(sourceModel());
+ SmDirModel *source = qobject_cast<SmDirModel*>(sourceModel());
QFileInfo lInfo = source->fileInfo(left);
QFileInfo rInfo = source->fileInfo(right);
if(lInfo.isDir() && rInfo.isDir()){
diff --git a/filesystemfileproxy.h b/filesystemfileproxy.h
index 739305d..e829158 100644
--- a/filesystemfileproxy.h
+++ b/filesystemfileproxy.h
@@ -18,8 +18,7 @@ class FilesystemFileProxy : public QSortFilterProxyModel {
public:
FilesystemFileProxy(QObject *parent = 0);
~FilesystemFileProxy() {};
- virtual QVariant data(const QModelIndex &index, int role) const;
- virtual bool filterAcceptsRow(int sourcerow, const QModelIndex &source_parent) const;
+ virtual QVariant data(const QModelIndex &index, int role) const;
protected:
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
diff --git a/filesystemwidget.cpp b/filesystemwidget.cpp
index b3ab4e1..e4363f0 100644
--- a/filesystemwidget.cpp
+++ b/filesystemwidget.cpp
@@ -37,6 +37,7 @@
#include "helper.h"
#include "pictureviewer2.h"
#include "smglobals.h"
+#include "smdirmodel.h"
FilesystemWidget::FilesystemWidget(QWidget *parent) : QWidget(parent), mClipboardMode(None) {
mModel = new FileSystemModel(this);
@@ -62,7 +63,9 @@ FilesystemWidget::FilesystemWidget(QWidget *parent) : QWidget(parent), mClipboar
mFileView = new FileView;
mFileProxy = new FilesystemFileProxy;
- mFileProxy->setSourceModel(mModel);
+ 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);
+ mFileProxy->setSourceModel(mFileModel);
mFileView->setModel(mFileProxy);
mFileView->setSortingEnabled(true);
mFileView->sortByColumn(0, Qt::AscendingOrder);
@@ -70,6 +73,7 @@ FilesystemWidget::FilesystemWidget(QWidget *parent) : QWidget(parent), mClipboar
mFileView->setSelectionMode(QAbstractItemView::ExtendedSelection);
mFileView->setEditTriggers(QAbstractItemView::NoEditTriggers);
mFileView->setAlternatingRowColors(true);
+ mFileView->setColumnHidden(static_cast<int>(SmDirModel::FullPath), true);
connect(mFileView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), mFileView, SLOT(selectedFilesChanged()));
mPicViewer = SmGlobals::instance()->pictureViewer();
@@ -100,8 +104,6 @@ FilesystemWidget::FilesystemWidget(QWidget *parent) : QWidget(parent), mClipboar
connect(mFileView, SIGNAL(delFiles()), this, SLOT(deleteFiles()));
connect(mFileView, SIGNAL(editorClosed(QModelIndex)), this, SLOT(fileEditorClosed(QModelIndex)));
- mFileView->resizeColumnToContents(0);
-
QVBoxLayout *mainLayout = new QVBoxLayout;
QSplitter *splitter = new QSplitter;
splitter->addWidget(mDirView);
@@ -147,7 +149,12 @@ void FilesystemWidget::directoryChanged(const QModelIndex &selected, const QMode
mDirEdit->setText(mModel->filePath(real));
setWindowTitle(mModel->filePath(real));
mFileView->selectionModel()->clear();
- mFileView->setRootIndex(mFileProxy->mapFromSource(real));
+ mFileModel->setDir(mModel->filePath(real));
+ mFileView->resizeColumnToContents(0);
+ mFileView->resizeColumnToContents(1);
+ mFileView->resizeColumnToContents(2);
+ mFileView->resizeColumnToContents(3);
+ mFileView->resizeColumnToContents(4);
}
void FilesystemWidget::directoryEdited(){
@@ -164,16 +171,17 @@ void FilesystemWidget::directoryEdited(){
void FilesystemWidget::fileViewActivated(const QModelIndex &idx){
QModelIndex real = mFileProxy->mapToSource(idx);
- if(mModel->isDir(real)){
+ if(mFileModel->isDir(real)){
if(idx.data().toString() == ".."){
parentDir();
return;
}
fileView()->selectionModel()->select(idx, QItemSelectionModel::Deselect);
- mDirView->setCurrentIndex(mDirProxy->mapFromSource(real));
+ QModelIndex curDir = mModel->index(real.data(SmDirModel::FullPathRole).toString());
+ mDirView->setCurrentIndex(mDirProxy->mapFromSource(curDir));
return;
}
- QString path = mModel->filePath(real);
+ QString path = real.data(SmDirModel::FullPathRole).toString();
QString mt = Helper::mimeType(path);
QStringList programArgs;
QString program;
@@ -215,32 +223,20 @@ void FilesystemWidget::goBack(){
}
void FilesystemWidget::deleteFiles(){
- QSortFilterProxyModel *proxy = static_cast<QSortFilterProxyModel*>(mFileView->model());
+ QSortFilterProxyModel *proxy = qobject_cast<QSortFilterProxyModel*>(mFileView->model());
QModelIndexList selected = mFileView->selectionModel()->selectedRows();
- int count(0);
- if(!selected.isEmpty()){
- count = selected.count();
- QString message = QString(tr("Really delete %1 files?")).arg(QString::number(selected.count()));
- int retval = QMessageBox::question(this, tr("Question"), message, QMessageBox::Yes | QMessageBox::No);
- if(retval == QMessageBox::Yes){
- foreach(QModelIndex idx, selected){
- QModelIndex real = proxy->mapToSource(idx);
- deleteRecursive(mModel->fileInfo(real));
- }
- }
- mFileView->selectionModel()->clearSelection();
- }else{
- count = 1;
- QModelIndex cur = mFileView->currentIndex();
- QModelIndex real = proxy->mapToSource(cur);
- QString message = QString(tr("Really delete %1?")).arg(mModel->fileName(real));
- int retval = QMessageBox::question(this, tr("Question"), message, QMessageBox::Yes | QMessageBox::No);
- if(retval == QMessageBox::Yes){
- deleteRecursive(mModel->fileInfo(real));
- }
- }
- QString message = QString(tr("Deleted %1 file(s)")).arg(count);
- emit statusbarMessage(message);
+ if(selected.isEmpty()){
+ return;
+ }
+
+ QString message = QString(tr("Really delete %1 files?")).arg(QString::number(selected.count()));
+ int retval = QMessageBox::question(this, tr("Question"), message, QMessageBox::Yes | QMessageBox::No);
+ if(retval == QMessageBox::Yes){
+ foreach(QModelIndex idx, selected){
+ QModelIndex real = proxy->mapToSource(idx);
+ deleteRecursive(mFileModel->fileInfo(real));
+ }
+ }
}
void FilesystemWidget::toClipboard(int clipmode){
@@ -254,10 +250,10 @@ void FilesystemWidget::toClipboard(int clipmode){
}
QList<QUrl> files;
foreach(QModelIndex idx, selected){
- if(idx.data(QFileSystemModel::FileNameRole).toString() == ".."){
+ if(idx.data(SmDirModel::NameRole).toString() == ".."){
continue;
}
- files << QUrl::fromLocalFile(idx.data(QFileSystemModel::FilePathRole).toString());
+ files << QUrl::fromLocalFile(idx.data(SmDirModel::FullPathRole).toString());
mModel->markForClipboard(mFileProxy->mapToSource(idx));
}
QMimeData *mimeData = new QMimeData;
@@ -540,9 +536,9 @@ void FilesystemWidget::dirCollapsed(const QModelIndex &idx){
}
void FilesystemWidget::fileEditorClosed(const QModelIndex &idx){
- QModelIndex real = mDirProxy->mapFromSource(idx);
+ QModelIndex real = mFileProxy->mapFromSource(idx);
if(real.isValid()){
- mDirView->update(real);
+ mFileView->update(real);
}
}
@@ -552,10 +548,8 @@ QStringList FilesystemWidget::selectedFiles(){
if(selected.isEmpty()){
return QStringList();
}
- QSortFilterProxyModel *proxy = static_cast<QSortFilterProxyModel*>(fileView()->model());
foreach(QModelIndex idx, selected){
- QModelIndex src = proxy->mapToSource(idx);
- retval << mModel->filePath(src);
+ retval << idx.data(SmDirModel::FullPathRole).toString();
}
return retval;
}
diff --git a/filesystemwidget.h b/filesystemwidget.h
index 744a3d3..1f83e5a 100644
--- a/filesystemwidget.h
+++ b/filesystemwidget.h
@@ -29,6 +29,7 @@ class QStringList;
class FileSystemModel;
class QSqlQuery;
class SheMovIconProvider;
+class SmDirModel;
class FilesystemWidget : public QWidget {
Q_OBJECT
@@ -83,6 +84,7 @@ class FilesystemWidget : public QWidget {
QStringList selectedFiles();
QStringList mExpandedDirs;
FileSystemModel *mModel;
+ SmDirModel *mFileModel;
QTreeView *mDirView;
FileView *mFileView;
FilesystemDirProxy *mDirProxy;
diff --git a/fileview.cpp b/fileview.cpp
index dba2948..07e64be 100644
--- a/fileview.cpp
+++ b/fileview.cpp
@@ -28,6 +28,7 @@
#include "fileview.h"
#include "hoverwindow.h"
#include "smglobals.h"
+#include "smdirmodel.h"
#include "helper.h"
FileView::FileView(QWidget *parent) : QTreeView(parent), mDeleteA(0) {
@@ -53,10 +54,10 @@ void FileView::markFiles(){
QRegExp re(glob);
for(int i = 0; i < rowCount; ++i){
QModelIndex cur = rootIndex().child(i, 0);
- if(cur.data(QFileSystemModel::FileNameRole).toString() == ".."){
+ if(cur.data(SmDirModel::NameRole).toString() == ".."){
continue;
}
- if(re.indexIn(cur.data(QFileSystemModel::FileNameRole).toString()) != -1){
+ if(re.indexIn(cur.data(SmDirModel::NameRole).toString()) != -1){
selectionModel()->select(cur, QItemSelectionModel::Select | QItemSelectionModel::Rows);
}
}
diff --git a/helper.cpp b/helper.cpp
index b3f2fc6..cfb1711 100644
--- a/helper.cpp
+++ b/helper.cpp
@@ -18,6 +18,7 @@
#include <QTemporaryFile>
#include <QProcess>
#include <QRect>
+#include <QTime>
#include <QtWidgets/QWidget>
#include <QtWidgets/QDesktopWidget>
#include <QtWidgets/QApplication>
@@ -208,5 +209,33 @@ namespace Helper {
widgetRect.moveCenter(qApp->desktop()->screenGeometry(widget).center());
widget->move(widgetRect.topLeft());
}
+
+ QList<QVariant> duration(const QString &path){
+ QSettings s;
+ QString ffProbe = s.value("paths/ffprobe").toString();
+ QStringList args;
+ QList<QVariant> retval;
+ args << "-show_streams" << path;
+ QProcess ffproc;
+ ffproc.start(ffProbe, args);
+ if(!ffproc.waitForStarted()){
+ return retval;
+ }
+ ffproc.waitForFinished();
+ QByteArray ffData = ffproc.readAllStandardError();
+ QList<QByteArray> lines = ffData.split('\n');
+
+ foreach(QString l, lines){
+ QString llc = l.toLower();
+ if(llc.contains("duration")){
+ int idx = llc.indexOf("duration:");
+ retval << llc.mid(idx + 10, 8);
+ idx = llc.indexOf("bitrate:");
+ retval << llc.mid(idx + 9);
+ break;
+ }
+ }
+ return retval;
+ }
}
diff --git a/helper.h b/helper.h
index b000026..a93406a 100644
--- a/helper.h
+++ b/helper.h
@@ -11,6 +11,7 @@
#include <QPair>
#include <QStringList>
#include <QVariant>
+#include <QList>
#include <magic.h>
@@ -30,6 +31,7 @@ namespace Helper {
const QStringList toStringList(const QList<QVariant> &list);
const QString colorToHtml(const QColor &color);
void centerWidget(QWidget *widget);
+ QList<QVariant> duration(const QString &path);
}
#endif
diff --git a/shemov.pro b/shemov.pro
index a8a12a2..d98d469 100644
--- a/shemov.pro
+++ b/shemov.pro
@@ -39,7 +39,9 @@ SOURCES = main.cpp \
newpicsdialog.cpp \
pictureswidget.cpp \
pictureviewer2.cpp \
- picfilesmodel.cpp
+ picfilesmodel.cpp \
+ smdirwatcher.cpp \
+ smdirmodel.cpp
HEADERS = \
filesystemdirproxy.h \
filesystemwidget.h \
@@ -74,6 +76,8 @@ HEADERS = \
newpicsdialog.h \
pictureswidget.h \
pictureviewer2.h \
- picfilesmodel.h
+ picfilesmodel.h \
+ smdirwatcher.h \
+ smdirmodel.h
LIBS += -lmagic -lXfixes -lX11
RESOURCES = shemov.qrc
diff --git a/smdirmodel.cpp b/smdirmodel.cpp
new file mode 100644
index 0000000..0a0578b
--- /dev/null
+++ b/smdirmodel.cpp
@@ -0,0 +1,127 @@
+/*
+ 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 <QDir>
+#include <QDateTime>
+#include <QFile>
+
+#include <sys/stat.h>
+
+#include "smdirmodel.h"
+#include "smdirwatcher.h"
+#include "smtreeitem.h"
+#include "helper.h"
+
+SmDirModel::SmDirModel(const QStringList &headers, QObject *parent) : SmTreeModel(headers, parent), mHeaders(headers){
+ mWatch = new SmDirWatcher(this);
+}
+
+SmDirModel::~SmDirModel(){
+ delete mWatch;
+}
+
+QVariant SmDirModel::data(const QModelIndex &index, int role) const{
+ if(!index.isValid()){
+ return QVariant();
+ }
+ SmTreeItem *i = itemAt(index);
+ switch (role){
+ case NameRole:
+ return i->data(Name);
+ case SizeRole:
+ return i->data(Size);
+ case TypeRole:
+ return i->data(Type);
+ case CreatedRole:
+ return i->data(Created);
+ case Md5sumRole:
+ return i->data(Md5sum);
+ case DurationRole:
+ return i->data(Duration);
+ case BitrateRole:
+ return i->data(Bitrate);
+ case FullPathRole:
+ return i->data(FullPath);
+ default:
+ return SmTreeModel::data(index, role);
+ }
+}
+
+bool SmDirModel::setData(const QModelIndex &index, const QVariant &value, int role){
+ if(!index.isValid()){
+ return false;
+ }
+ if(role == Qt::EditRole && index.column() == Name){
+ QString newName = value.toString();
+ if(newName.contains(QDir::separator())){
+ return false;
+ }
+ SmTreeItem *i = itemAt(index);
+ QString old = i->data(FullPath).toString();
+ QString dir = fileInfo(index).absolutePath();
+ QString newPath = QString("%1/%2").arg(dir).arg(newName);
+ QFile::rename(old, newPath);
+ return true;
+ }
+ return false;
+}
+
+bool SmDirModel::isDir(const QModelIndex &idx) const {
+ if(!idx.isValid()){
+ return false;
+ }
+ SmTreeItem *i = itemAt(idx);
+ QFileInfo fi(i->data(FullPath).toString());
+ return fi.isDir();
+}
+
+QFileInfo SmDirModel::fileInfo(const QModelIndex &idx) const {
+ if(!idx.isValid()){
+ return QFileInfo();
+ }
+ SmTreeItem *i = itemAt(idx);
+ return QFileInfo(i->data(FullPath).toString());
+}
+
+void SmDirModel::setDir(const QString &dir){
+ QFileInfo fi(dir);
+ if(!fi.isDir()){
+ return;
+ }
+ mCur = dir;
+ populate();
+ mWatch->setDir(dir);
+}
+
+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);
+ }
+ setRoot(root);
+}
+
+const QList<QVariant> SmDirModel::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/smdirmodel.h b/smdirmodel.h
new file mode 100644
index 0000000..5e1dceb
--- /dev/null
+++ b/smdirmodel.h
@@ -0,0 +1,48 @@
+/*
+ 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.
+*/
+
+#ifndef SMDIRMODEL_H
+#define SMDIRMODEL_H
+
+#include <QStringList>
+#include <QVariant>
+#include <QModelIndex>
+#include <QList>
+#include <QFileInfo>
+
+#include <smtreemodel.h>
+#include <smdirwatcher.h>
+
+class SmDirWatcher;
+
+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 FileDate { Access, Modified, Status };
+ explicit SmDirModel(const QStringList &headers, QObject *parent = 0);
+ ~SmDirModel();
+ 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;
+ QFileInfo fileInfo(const QModelIndex &idx) const;
+
+ public slots:
+ void setDir(const QString &dir);
+
+ private:
+ void populate();
+ const QList<QVariant> fileData(const QFileInfo &fi) const;
+ SmDirWatcher *mWatch;
+ QStringList mHeaders;
+ QString mCur;
+
+
+};
+
+#endif // SMDIRMODEL_H
diff --git a/smdirwatcher.cpp b/smdirwatcher.cpp
new file mode 100644
index 0000000..a216af5
--- /dev/null
+++ b/smdirwatcher.cpp
@@ -0,0 +1,84 @@
+/*
+ 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 <QVarLengthArray>
+#include <QMutexLocker>
+
+#include <sys/inotify.h>
+#include <stropts.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "smdirwatcher.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, 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
+ */
+ mDescr = inotify_add_watch(mFd, qPrintable(dir), IN_CLOSE_WRITE | IN_CREATE | IN_DELETE | IN_MODIFY);
+ mCurrent = dir;
+}
+
+#include <QDebug>
+
+void SmDirWatcher::run(){
+ QMutexLocker lock(&mWatchMx);
+ QVarLengthArray<char, 4096> data(ioctl(mFd, FIONREAD) + 1);
+ 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{
+ return;
+ }
+ }
+ // inspect data
+ char *at = data.data();
+ char *end = at + data.size();
+ while(at < end){
+ inotify_event *e = reinterpret_cast<inotify_event*>(at);
+ qDebug() << "inotify:" << e->name;
+ if(e->mask & IN_IGNORED){
+ at += sizeof(inotify_event) + e->len;
+ continue;
+ }
+ if(e->mask & IN_CREATE){
+ emit dwEvent(e->name, Added);
+ }
+ if(e->mask & IN_DELETE){
+ emit dwEvent(e->name, Deleted);
+ }
+ if((e->mask & IN_CLOSE_WRITE) || (e->mask & IN_MODIFY)){
+ emit dwEvent(e->name, Modified);
+ }
+ at += sizeof(inotify_event) + e->len;
+ }
+}
diff --git a/smdirwatcher.h b/smdirwatcher.h
new file mode 100644
index 0000000..656d677
--- /dev/null
+++ b/smdirwatcher.h
@@ -0,0 +1,35 @@
+/*
+ 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.
+*/
+
+#ifndef SMDIRWATCHER_H
+#define SMDIRWATCHER_H
+
+#include <QThread>
+#include <QMutex>
+
+class SmDirWatcher : public QThread {
+ Q_OBJECT
+ public:
+ enum DWEvent { Added, Deleted, Modified };
+ explicit SmDirWatcher(QObject *parent = 0);
+ ~SmDirWatcher();
+
+ signals:
+ void dwEvent(const QString& file, int event);
+
+ public slots:
+ void run();
+ void setDir(const QString &dir);
+
+ private:
+ int mFd;
+ int mDescr;
+ QMutex mWatchMx;
+ QString mCurrent;
+};
+
+#endif // SMDIRWATCHER_H