diff options
-rw-r--r-- | archivecontroller.cpp | 54 | ||||
-rw-r--r-- | archivecontroller.h | 46 | ||||
-rw-r--r-- | archivemodel.cpp | 155 | ||||
-rw-r--r-- | archivemodel.h | 20 | ||||
-rw-r--r-- | archiveview.cpp | 20 | ||||
-rw-r--r-- | archiveview.h | 15 | ||||
-rw-r--r-- | shemov.pro | 6 |
7 files changed, 310 insertions, 6 deletions
diff --git a/archivecontroller.cpp b/archivecontroller.cpp new file mode 100644 index 0000000..0c67ef7 --- /dev/null +++ b/archivecontroller.cpp @@ -0,0 +1,54 @@ +/* + 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 "archivecontroller.h" +#include "archivemodel.h" +#include "archiveview.h" + +ArchiveController::ArchiveController(QObject *parent) : QObject(parent) {} + +void ArchiveController::setArchiveView(ArchiveTree *atree, ArchiveProxy *aproxy){ + mArchiveTree = atree; + mArchiveProxy = aproxy; + mArchiveSelection = mArchiveTree->selectionModel(); +} + +void ArchiveController::setArchiveFiles(ArchiveFiles *afiles, ArchiveFilesProxy *afilesproxy){ + mArchiveFiles = afiles; + mArchiveFilesProxy = afilesproxy; +} + +void ArchiveController::setModels(ArchiveModel *amodel, ArchiveFilesModel *afilesmodel){ + mArchiveModel = amodel; + mArchiveFilesModel = afilesmodel; +} + +void ArchiveController::init(){ + connect(mArchiveSelection, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(treeSelectionChanged(QItemSelection,QItemSelection))); +} + +void ArchiveController::treeSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected){ + Q_UNUSED(selected); + Q_UNUSED(deselected); + QModelIndexList sel = mapToSource(mArchiveProxy, mArchiveSelection->selectedRows()); + if(sel.isEmpty()){ + return; + } + QSet<int> ids; + foreach(QModelIndex idx, sel){ + ids.unite(mArchiveModel->seriesPartIds(idx)); + } + mArchiveFilesModel->populate(ids); +} + +QModelIndexList ArchiveController::mapToSource(const QSortFilterProxyModel *proxy, const QModelIndexList idxs) const{ + QModelIndexList retval; + foreach(QModelIndex idx, idxs){ + retval << proxy->mapToSource(idx); + } + return retval; +} diff --git a/archivecontroller.h b/archivecontroller.h new file mode 100644 index 0000000..e956d37 --- /dev/null +++ b/archivecontroller.h @@ -0,0 +1,46 @@ +/* + 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 ARCHIVECONTROLLER_H +#define ARCHIVECONTROLLER_H + +#include <QObject> +#include <QItemSelection> + +class ArchiveTree; +class ArchiveProxy; +class ArchiveFiles; +class ArchiveFilesProxy; +class ArchiveModel; +class ArchiveFilesModel; +class QItemSelectionModel; +class QSortFilterProxyModel; + +class ArchiveController : public QObject { + Q_OBJECT + public: + explicit ArchiveController(QObject *parent = 0); + void setArchiveView(ArchiveTree *atree, ArchiveProxy *aproxy); + void setArchiveFiles(ArchiveFiles *afiles, ArchiveFilesProxy *afilesproxy); + void setModels(ArchiveModel *amodel, ArchiveFilesModel *afilesmodel); + void init(); + + private slots: + void treeSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected); + + private: + QModelIndexList mapToSource(const QSortFilterProxyModel *proxy, const QModelIndexList idxs) const; + ArchiveTree *mArchiveTree; + ArchiveProxy *mArchiveProxy; + QItemSelectionModel *mArchiveSelection; + ArchiveFiles *mArchiveFiles; + ArchiveFilesProxy *mArchiveFilesProxy; + ArchiveModel *mArchiveModel; + ArchiveFilesModel *mArchiveFilesModel; +}; + +#endif // ARCHIVECONTROLLER_H diff --git a/archivemodel.cpp b/archivemodel.cpp index 14757af..3746105 100644 --- a/archivemodel.cpp +++ b/archivemodel.cpp @@ -11,9 +11,11 @@ #include <QSettings> #include <QMutexLocker> #include <QSignalMapper> +#include <QFileInfo> #include "smtreeitem.h" #include "archivemodel.h" +#include "helper.h" ArchiveModel::ArchiveModel(const QStringList &headers, QObject *parent) : SmTreeModel(headers, parent), mOrder(NoOrder){ mDb = QSqlDatabase::database("treedb"); @@ -225,6 +227,32 @@ QModelIndexList ArchiveModel::pathToIndex(const QStringList &path) const { return retval; } +QSet<int> ArchiveModel::seriesPartIds(const QModelIndex &idx) const{ + if(!idx.isValid()){ + return QSet<int>(); + } + SmTreeItem *cur = itemAt(idx); + QVector<SmTreeItem*> remaining; + remaining << cur; + QSet<int> retval; + for(int i = 0; i < cur->childCount(); ++i){ + remaining << cur->child(i); + } + while(cur){ + cur = remaining.last(); + remaining.pop_back(); + for(int i = 0; i < cur->childCount(); ++i){ + remaining << cur->child(i); + } + int curId = cur->data(SeriesPartId).toInt(); + retval << curId; + if(remaining.isEmpty()){ + break; + } + } + return retval; +} + void ArchiveModel::setOrder(int order) { mOrder = order; SmTreeItem *rootItem = readCache(mOrder); @@ -368,6 +396,133 @@ const QString ArchiveModel::cacheFile(int o) const{ return cacheFile; } +/* + * ArchiveFilesModel BEGIN */ + +ArchiveFilesModel::ArchiveFilesModel(const QStringList &headers, QObject *parent) : SmTreeModel(headers, parent) { + mDb = QSqlDatabase::database("treedb"); + mRoleDbColumnMap.insert(FilenameRole, "tfilename"); + mRoleDbColumnMap.insert(DvdNoRole, "idvd"); + mRoleDbColumnMap.insert(FileTypeRole, "sifiletype"); + mRoleDbColumnMap.insert(FileNumberRole, "sifileno"); + mRoleDbColumnMap.insert(QualityRole, "siquality"); +} + +QVariant ArchiveFilesModel::data(const QModelIndex &index, int role) const { + if(!index.isValid()){ + return QVariant(); + } + SmTreeItem *item = itemAt(index); + if(role == SeriesPartIdRole){ + return item->data(SeriesPartId); + } + if(role == FilenameRole){ + return item->data(Filename); + } + if(role == Md5SumRole){ + return item->data(Md5Sum); + } + if(role == SizeRole){ + return item->data(Size); + } + if(role == DvdNoRole){ + return item->data(DvdNo); + } + if(role == FileTypeRole){ + return item->data(FileType); + } + if(role == FileNumberRole){ + return item->data(FileNumber); + } + if(role == QualityRole){ + return item->data(Quality); + } + if(role == FileIdRole){ + return item->data(FileId); + } + if(role == PicSizeRole){ + return item->data(PicSize); + } + if(role == DurationRole){ + return item->data(Duration); + } + if(role == FullPathRole){ + return item->data(FullPath); + } + return SmTreeModel::data(index, role); +} + +bool ArchiveFilesModel::setData(const QModelIndex &idx, const QVariant &value, int role){ + const QString dbColumn = mRoleDbColumnMap.value(role); + if(dbColumn.isEmpty()){ + return SmTreeModel::setData(idx, value, role); + } + QString queryString = QString("UPDATE files SET %1 = :value WHERE ifiles_id = :id").arg(dbColumn); + QSqlQuery q(queryString, mDb); + q.bindValue(":value", value); + q.bindValue(":id", idx.data()); + mDb.transaction(); + bool success = q.exec(); + if(success){ + if(role == FilenameRole){ + QFile f(idx.data(FullPathRole).toString()); + QFileInfo fi(f); + QString dir = fi.absolutePath(); + QString newName = QString("%1/%2").arg(dir).arg(value.toString()); + success = f.rename(newName); + } + // check rename, too! + if(success){ + mDb.commit(); + emit dataChanged(idx, idx); + return true; + } + } + mDb.rollback(); + return false; +} + +void ArchiveFilesModel::populate(const QSet<int> &seriesPartIds){ + if(seriesPartIds.isEmpty()){ + return; + } + SmTreeItem *root = new SmTreeItem(NumFields); + SmTreeItem *movies = new SmTreeItem(NumFields, root); + movies->setData(Filename, tr("Movies")); + root->appendChild(movies); + SmTreeItem *pictures = new SmTreeItem(NumFields, root); + pictures->setData(Filename, tr("Pictures")); + root->appendChild(pictures); + QSettings s; + QString archivePath = s.value("paths/archive").toString(); + + QStringList ids; + foreach(int i, seriesPartIds){ + ids << QString::number(i); + } + QString queryString = QString("SELECT iseriespart_id, tfilename, cmd5sum, bisize, idvd, sifiletype, sifileno, siquality, ifiles_id, cpicsize, iduration FROM files WHERE iseriespart_id IN (%1) ORDER BY tfilename ASC").arg(ids.join(",")); + QSqlQuery q(queryString, mDb); + while(q.next()){ + QList<QVariant> data; + for(int i = 0; i < NumFields - 1; ++i){ + data << q.value(i); + } + QString fullPath = Helper::createArchivePath(archivePath, data.at(Md5Sum).toString()); + data << fullPath; + if(data.at(FileType).toInt() == Movie){ + SmTreeItem *newItem = new SmTreeItem(data, movies); + movies->appendChild(newItem); + }else{ + SmTreeItem *newItem = new SmTreeItem(data, pictures); + pictures->appendChild(newItem); + } + } + setRoot(root); +} + +/* + * ArchiveCollector BEGIN */ + ArchiveCollector::ArchiveCollector(int numFields, int order, QObject *parent) : QThread(parent), mRootItem(0), mNumFields(numFields), mSortOrder(order) { QString dbName = QString("%1").arg((qint64(this))); mDb = QSqlDatabase::cloneDatabase(QSqlDatabase::database("treedb"), dbName); diff --git a/archivemodel.h b/archivemodel.h index 4ef39fa..a9994d0 100644 --- a/archivemodel.h +++ b/archivemodel.h @@ -12,6 +12,7 @@ #include <QThread> #include <QDataStream> #include <QMutex> +#include <QSet> #include "smtreemodel.h" @@ -35,6 +36,7 @@ class ArchiveModel : public SmTreeModel { virtual bool removeNode(const QModelIndex &idx); QStringList indexToPath(const QModelIndex &idx) const; QModelIndexList pathToIndex(const QStringList &path) const; + QSet<int> seriesPartIds(const QModelIndex &idx) const; signals: void needRefresh(); @@ -64,6 +66,24 @@ class ArchiveModel : public SmTreeModel { int mOrder; }; +class ArchiveFilesModel : public SmTreeModel { + Q_OBJECT + public: + enum CustomRoles { SeriesPartIdRole = Qt::UserRole + 1, FilenameRole = Qt::UserRole + 2, Md5SumRole = Qt::UserRole + 3, SizeRole = Qt::UserRole + 4, DvdNoRole = Qt::UserRole + 5, FileTypeRole = Qt::UserRole + 6, FileNumberRole = Qt::UserRole + 7, QualityRole = Qt::UserRole + 8, FileIdRole = Qt::UserRole + 9, PicSizeRole = Qt::UserRole + 10, DurationRole = Qt::UserRole + 11, FullPathRole = Qt::UserRole + 12 }; + enum Fields { SeriesPartId = 0, Filename = 1, Md5Sum = 2, Size = 3, DvdNo = 4, FileType = 5, FileNumber = 6, Quality = 7, FileId = 8, PicSize = 9, Duration = 10, FullPath = 11 }; + enum FileType { Movie = 1, FrontCover = 2, BackCover = 3, GeneralCover = 4 }; + enum { NumFields = 12 }; + explicit ArchiveFilesModel(const QStringList &headers, QObject *parent = 0); + virtual QVariant data(const QModelIndex &index, int role) const; + virtual bool setData(const QModelIndex &idx, const QVariant &value, int role); + void populate(const QSet<int> &seriesPartIds); + + private: + QList<int> mSeriesPartIds; + QHash<int, QString> mRoleDbColumnMap; + QSqlDatabase mDb; +}; + class ArchiveCollector : public QThread { Q_OBJECT public: diff --git a/archiveview.cpp b/archiveview.cpp index 34fd169..f570751 100644 --- a/archiveview.cpp +++ b/archiveview.cpp @@ -18,9 +18,10 @@ #include <QVBoxLayout> #include "archiveview.h" +#include "archivecontroller.h" #include "smglobals.h" -ArchiveView::ArchiveView(QWidget *parent) : QWidget(parent), mConstructing(true) { +ArchiveView::ArchiveView(QWidget *parent) : QWidget(parent) { QSettings s; mArchiveModel = static_cast<ArchiveModel*>(SmGlobals::instance()->model("ArchiveModel")); connect(mArchiveModel, SIGNAL(needRefresh()), this, SLOT(refreshArchive())); @@ -74,7 +75,13 @@ ArchiveView::ArchiveView(QWidget *parent) : QWidget(parent), mConstructing(true) treeLayout->addWidget(mTree); QWidget *treeWidget = new QWidget; treeWidget->setLayout(treeLayout); + mFiles = new ArchiveFiles; + mFilesModel = new ArchiveFilesModel(QStringList() << tr("Seriespartid") << tr("Filename") << tr("Md5Sum") << tr("Size") << tr("Dvd") << tr("Type") << tr("No") << tr("Quality") << tr("Fileid") << tr("Pic size") << tr("Duration") << tr("Full Path"), this); + mFilesProxy = new ArchiveFilesProxy; + mFilesProxy->setSourceModel(mFilesModel); + mFiles->setModel(mFilesProxy); + QSplitter *treeSplitter = new QSplitter(Qt::Horizontal); treeSplitter->addWidget(treeWidget); treeSplitter->addWidget(mFiles); @@ -83,6 +90,7 @@ ArchiveView::ArchiveView(QWidget *parent) : QWidget(parent), mConstructing(true) QHBoxLayout *mainLayout = new QHBoxLayout; mainLayout->addWidget(treeSplitter); setLayout(mainLayout); + initController(); } int ArchiveView::currentSortOrder() const { @@ -165,6 +173,14 @@ void ArchiveView::collapseItem(const QModelIndex &idx){ } } +void ArchiveView::initController(){ + mController = new ArchiveController(this); + mController->setArchiveView(mTree, mProxy); + mController->setArchiveFiles(mFiles, mFilesProxy); + mController->setModels(mArchiveModel, mFilesModel); + mController->init(); +} + ArchiveTree::ArchiveTree(QWidget *parent) : SmTreeView(parent) {} void ArchiveTree::setModel(ArchiveProxy *model){ @@ -224,3 +240,5 @@ bool ArchiveProxy::filterAcceptsRow(int sourceRow, const QModelIndex &sourcePare ArchiveModel *model = qobject_cast<ArchiveModel*>(sourceModel()); return model->matchRecursive(nameIdx, mFilter); } + +ArchiveFilesProxy::ArchiveFilesProxy(QObject *parent) : QSortFilterProxyModel(parent) {} diff --git a/archiveview.h b/archiveview.h index 27bae35..de9875d 100644 --- a/archiveview.h +++ b/archiveview.h @@ -24,7 +24,8 @@ class QSortFilterProxyModel; class ArchiveTree; class ArchiveFiles; class ArchiveProxy; -class ArchiveProgressDialog; +class ArchiveFilesProxy; +class ArchiveController; class ArchiveView : public QWidget { Q_OBJECT @@ -48,15 +49,17 @@ class ArchiveView : public QWidget { void collapseItem(const QModelIndex &idx); private: + void initController(); QComboBox *mSortOrder; QLineEdit *mFilter; ArchiveTree *mTree; ArchiveFiles *mFiles; ArchiveModel *mArchiveModel; + ArchiveFilesModel *mFilesModel; ArchiveProxy *mProxy; - ArchiveProgressDialog *mProgress; + ArchiveFilesProxy *mFilesProxy; QHash<int, QVariantList> mExpandedItems; - bool mConstructing; + ArchiveController *mController; }; class ArchiveTree : public SmTreeView { @@ -96,4 +99,10 @@ class ArchiveProxy : public QSortFilterProxyModel { int mSortOrder; }; +class ArchiveFilesProxy : public QSortFilterProxyModel { + Q_OBJECT + public: + explicit ArchiveFilesProxy(QObject *parent = 0); +}; + #endif // ARCHIVEVIEW_H @@ -45,7 +45,8 @@ SOURCES = main.cpp \ framecache.cpp \ smtreeview.cpp \ archivemodel.cpp \ - archiveview.cpp + archiveview.cpp \ + archivecontroller.cpp HEADERS = \ filesystemdirproxy.h \ filesystemwidget.h \ @@ -86,6 +87,7 @@ HEADERS = \ framecache.h \ smtreeview.h \ archivemodel.h \ - archiveview.h + archiveview.h \ + archivecontroller.h LIBS += -lmagic -lXfixes -lX11 RESOURCES = shemov.qrc |