diff options
-rw-r--r-- | dbanalyzer.cpp | 156 | ||||
-rw-r--r-- | dbanalyzer.h | 28 | ||||
-rw-r--r-- | smtreeitem.cpp | 8 | ||||
-rw-r--r-- | smtreeitem.h | 3 | ||||
-rw-r--r-- | smtreemodel.cpp | 5 |
5 files changed, 181 insertions, 19 deletions
diff --git a/dbanalyzer.cpp b/dbanalyzer.cpp index 4de88da..95bf5a9 100644 --- a/dbanalyzer.cpp +++ b/dbanalyzer.cpp @@ -15,12 +15,15 @@ #include <QTableWidget> #include <QModelIndex> #include <QLabel> +#include <QColor> +#include <QMenu> +#include <QAction> #include "dbanalyzer.h" #include "smtreemodel.h" #include "smtreeitem.h" -DbAnalyzerDialog::DbAnalyzerDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f){ +DbAnalyzerDialog::DbAnalyzerDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f), mMarkMode(DbAnalyzer::NOMARKS), mCurrentView(0){ //create tab widget mTab = new QTabWidget; @@ -41,10 +44,12 @@ DbAnalyzerDialog::DbAnalyzerDialog(QWidget *parent, Qt::WindowFlags f) : QDialog mNoActorsV->setColumnHidden(5, true); mNoActorsV->setEditTriggers(QTreeView::NoEditTriggers); mNoActorsV->setSelectionBehavior(QAbstractItemView::SelectRows); - mNoActorsV->setSelectionMode(QAbstractItemView::SingleSelection); + mNoActorsV->setSelectionMode(QAbstractItemView::ExtendedSelection); mNoActorsV->setAlternatingRowColors(true); connect(mNoActorsV, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(noDataDoubleClicked(QModelIndex))); noActorsT->setLayout(noActorsL); + mCurrentView = mNoActorsV; + mMarkMode = DbAnalyzer::MARKS_ACTORS; //no covers QWidget *noCoversT = new QWidget; @@ -60,7 +65,7 @@ DbAnalyzerDialog::DbAnalyzerDialog(QWidget *parent, Qt::WindowFlags f) : QDialog mNoCoversV->setColumnHidden(5, true); mNoCoversV->setEditTriggers(QTreeView::NoEditTriggers); mNoCoversV->setSelectionBehavior(QAbstractItemView::SelectRows); - mNoCoversV->setSelectionMode(QAbstractItemView::SingleSelection); + mNoCoversV->setSelectionMode(QAbstractItemView::ExtendedSelection); mNoCoversV->setAlternatingRowColors(true); connect(mNoCoversV, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(noDataDoubleClicked(QModelIndex))); noCoversT->setLayout(noCoversL); @@ -102,9 +107,17 @@ DbAnalyzerDialog::DbAnalyzerDialog(QWidget *parent, Qt::WindowFlags f) : QDialog connect(mRefresh, SIGNAL(clicked()), this, SLOT(refresh())); mClose = new QPushButton(tr("Close")); connect(mClose, SIGNAL(clicked()), this, SLOT(accept())); - mDelete = new QPushButton(tr("Delete...")); - mDelete->setEnabled(false); - connect(mDelete, SIGNAL(clicked()), this, SLOT(deleteItems())); + mMark = new QPushButton(tr("Mark")); + + //button menu + QMenu *markMenu = new QMenu(mMark); + QAction *markOkA = new QAction(tr("Set OK"), this); + QAction *deleteMarkA = new QAction(tr("Delete mark"), this); + markMenu->addAction(markOkA); + markMenu->addAction(deleteMarkA); + mMark->setMenu(markMenu); + connect(markOkA, SIGNAL(triggered()), this, SLOT(setMarks())); + connect(deleteMarkA, SIGNAL(triggered()), this, SLOT(deleteMarks())); //setup dialog mTab->addTab(noActorsT, tr("No Actors")); @@ -112,13 +125,12 @@ DbAnalyzerDialog::DbAnalyzerDialog(QWidget *parent, Qt::WindowFlags f) : QDialog mTab->addTab(strayActorsT, tr("Stray actors")); mTab->addTab(strayGenresT, tr("Stray genres")); - //buttons QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->addWidget(mCancel); buttonLayout->addWidget(mRefresh); buttonLayout->addStretch(); - buttonLayout->addWidget(mDelete); + buttonLayout->addWidget(mMark); buttonLayout->addWidget(mClose); //totals @@ -165,8 +177,8 @@ void DbAnalyzerDialog::analyzerFinished(){ mCancel->setEnabled(false); mRefresh->setEnabled(true); mClose->setEnabled(true); - populate(mNoActorsV, mNoActorsM, mAnalyzer->noActors()); - populate(mNoCoversV, mNoCoversM, mAnalyzer->noCovers()); + populate(mNoActorsV, mNoActorsM, mAnalyzer->noActors(), mAnalyzer->actorMarks()); + populate(mNoCoversV, mNoCoversM, mAnalyzer->noCovers(), mAnalyzer->coverMarks()); populate(mStrayActorsV, mStrayActorsM, mAnalyzer->strayActors()); populate(mStrayGenresV, mStrayGenresM, mAnalyzer->strayGenres()); QString totalString = QString(tr("<b>Total items: %1</b>")); @@ -220,11 +232,48 @@ void DbAnalyzerDialog::deleteItems(){ } void DbAnalyzerDialog::tabChanged(int index){ - mDelete->setEnabled(index > 1); + switch(index){ + case 0: + mMarkMode = DbAnalyzer::MARKS_ACTORS; + mCurrentView = mNoActorsV; + break; + case 1: + mMarkMode = DbAnalyzer::MARKS_COVERS; + mCurrentView = mNoCoversV; + break; + case 2: + mMarkMode = DbAnalyzer::NOMARKS; + mCurrentView = mStrayActorsV; + break; + case 3: + mMarkMode = DbAnalyzer::NOMARKS; + mCurrentView = mStrayGenresV; + break; + default: + mMarkMode = DbAnalyzer::NOMARKS; + mCurrentView = 0; + break; + } mTotal->setText(mTotals.at(index)); } -void DbAnalyzerDialog::populate(QTreeView *view, SmTreeModel *model, const QList<QList<QVariant> > &data){ +void DbAnalyzerDialog::setMarks(){ + if(mMarkMode != DbAnalyzer::NOMARKS){ + const QList<int> curIds = currentIds(); + mAnalyzer->setMarks(curIds, mMarkMode, 1); + refresh(); + } +} + +void DbAnalyzerDialog::deleteMarks(){ + if(mMarkMode != DbAnalyzer::NOMARKS){ + const QList<int> curIds = currentIds(); + mAnalyzer->deleteMarks(curIds, mMarkMode); + refresh(); + } +} + +void DbAnalyzerDialog::populate(QTreeView *view, SmTreeModel *model, const QList<QList<QVariant> > &data, const QHash<int, QVariant> &marks){ const int columns = data.first().count(); if(columns == 0){ return; @@ -232,12 +281,31 @@ void DbAnalyzerDialog::populate(QTreeView *view, SmTreeModel *model, const QList SmTreeItem *root = new SmTreeItem(columns); foreach(QList<QVariant> l, data){ SmTreeItem *child = new SmTreeItem(l, root); + if(!marks.isEmpty()){ + int seriesId = l.at(4).toInt(); + QColor fgColor = Qt::red; + if(marks.contains(seriesId) && marks.value(seriesId).toInt() > 0){ + fgColor = Qt::green; + } + child->setForegroundColor(fgColor); + } root->appendChild(child); } model->setRoot(root); view->resizeColumnToContents(0); } +const QList<int> DbAnalyzerDialog::currentIds() const { + QTreeView *curView = qobject_cast<QTreeView*>(mCurrentView); + Q_ASSERT(curView); + QModelIndexList curIdxs = curView->selectionModel()->selectedRows(4); + QList<int> retval; + foreach(QModelIndex i, curIdxs){ + retval << i.data().toInt(); + } + return retval; +} + DbAnalyzer::DbAnalyzer(QObject *parent) : QThread(parent), mCanceled(false), mStatus(Fail) { mDb = QSqlDatabase::cloneDatabase(QSqlDatabase::database("treedb"), "analyzerDb"); mDb.open(); @@ -250,6 +318,12 @@ DbAnalyzer::DbAnalyzer(QObject *parent) : QThread(parent), mCanceled(false), mSt mStrayGenresQuery->prepare("SELECT genres.tgenrename, genres.igenres_id, COUNT(seriesparts_genremap.igenres_id) FROM genres LEFT JOIN seriesparts_genremap ON genres.igenres_id = seriesparts_genremap.igenres_id WHERE seriesparts_genremap.igenres_id IS NULL GROUP BY genres.igenres_id, genres.tgenrename ORDER BY genres.tgenrename"); mNoCoverQuery = new QSqlQuery(mDb); mNoCoverQuery->prepare("SELECT series.tseries_name, seriesparts.iseriespart, seriesparts.tsubtitle, series.iseries_id, seriesparts.iseriesparts_id FROM files, series, seriesparts WHERE files.iseriespart_id = seriesparts.iseriesparts_id AND seriesparts.iseries_id = series.iseries_id GROUP BY files.iseriespart_id, series.tseries_name,seriesparts.iseriespart, seriesparts.tsubtitle, seriesparts.iseriesparts_id, series.iseries_id HAVING COUNT(iseriespart_id) = 1 ORDER BY series.tseries_name"); + mMarksQuery = new QSqlQuery(mDb); + mMarksQuery->prepare("SELECT id, mark_id FROM marks where mark_reason = :reason"); + mSetMarksQuery = new QSqlQuery(mDb); + mSetMarksQuery->prepare("INSERT INTO marks (id, mark_reason, mark_id) VALUES(:seriesid, :reason, :mark_id)"); + mDeleteMarksQuery = new QSqlQuery(mDb); + mDeleteMarksQuery->prepare("DELETE FROM marks WHERE id = :id AND mark_reason = :reason"); } DbAnalyzer::~DbAnalyzer(){ @@ -257,6 +331,9 @@ DbAnalyzer::~DbAnalyzer(){ delete mNoCoverQuery; delete mStrayActorsQuery; delete mStrayGenresQuery; + delete mMarksQuery; + delete mSetMarksQuery; + delete mDeleteMarksQuery; mDb.close(); mDb = QSqlDatabase(); QSqlDatabase::removeDatabase("analyzerDb"); @@ -267,19 +344,49 @@ void DbAnalyzer::setCancel(bool canceled){ mCanceled = canceled; } +void DbAnalyzer::setMarks(const QList<int> &ids, int reason, int mark_id){ + mDb.transaction(); + mSetMarksQuery->bindValue(":reason", reason); + mSetMarksQuery->bindValue(":mark_id", mark_id); + foreach(int id, ids){ + mSetMarksQuery->bindValue(":seriesid", id); + if(!mSetMarksQuery->exec()){ + mDb.rollback(); + return; + } + } + mDb.commit(); +} + +void DbAnalyzer::deleteMarks(const QList<int> &ids, int reason){ + mDb.transaction(); + mDeleteMarksQuery->bindValue(":reason", reason); + foreach(int id, ids){ + mDeleteMarksQuery->bindValue(":id", id); + if(!mDeleteMarksQuery->exec()){ + mDb.rollback(); + return; + } + } + mDb.commit(); +} + void DbAnalyzer::run(){ mNoActorR = noDataCheck(mNoActorQuery); + mActorMarks = marks(MARKS_ACTORS); mNoCoverR = noDataCheck(mNoCoverQuery); + mCoverMarks = marks(MARKS_COVERS); mStrayActorR = strayCheck(mStrayActorsQuery); mStrayGenresR = strayCheck(mStrayGenresQuery); } const QList<QList<QVariant> > DbAnalyzer::noDataCheck(QSqlQuery *query){ if(!query->exec()){ - QMutexLocker m(&mStatusMutex); - mStatus = Fail; + setStatus(Fail); return QList<QList<QVariant> >(); } + + //read data QList<QList<QVariant> > retval; while(query->next()){ if(mCanceled){ @@ -315,3 +422,24 @@ const QList<QList<QVariant> > DbAnalyzer::strayCheck(QSqlQuery *query){ } return retval; } + +QHash<int, QVariant> DbAnalyzer::marks(int markType){ + QHash<int, QVariant> retval; + if(markType == NOMARKS){ + return retval; + } + mMarksQuery->bindValue(":reason", markType); + if(!mMarksQuery->exec()){ + setStatus(Fail); + return retval; + } + while(mMarksQuery->next()){ + retval.insert(mMarksQuery->value(0).toInt(), mMarksQuery->value(1)); + } + return retval; +} + +void DbAnalyzer::setStatus(int status){ + QMutexLocker m(&mStatusMutex); + mStatus = status; +} diff --git a/dbanalyzer.h b/dbanalyzer.h index 653aa70..25b0bfb 100644 --- a/dbanalyzer.h +++ b/dbanalyzer.h @@ -11,6 +11,7 @@ #include <QThread> #include <QVariant> #include <QList> +#include <QHash> #include <QDialog> #include <QSqlDatabase> #include <QMutex> @@ -27,7 +28,7 @@ class QLabel; class DbAnalyzerDialog : public QDialog { Q_OBJECT public: - enum DeleteMode { Actors, Genres }; + enum Mode { Actors, Genres }; explicit DbAnalyzerDialog(QWidget *parent = 0, Qt::WindowFlags f = 0); public slots: @@ -44,9 +45,12 @@ class DbAnalyzerDialog : public QDialog { void noDataDoubleClicked(const QModelIndex &); void deleteItems(); void tabChanged(int index); + void setMarks(); + void deleteMarks(); private: - void populate(QTreeView *view ,SmTreeModel *model, const QList<QList<QVariant> > &data); + void populate(QTreeView *view ,SmTreeModel *model, const QList<QList<QVariant> > &data, const QHash<int, QVariant> &marks = QHash<int, QVariant>()); + const QList<int> currentIds() const; QTabWidget *mTab; QTreeView *mNoActorsV; QTreeView *mNoCoversV; @@ -58,27 +62,34 @@ class DbAnalyzerDialog : public QDialog { SmTreeModel *mStrayGenresM; QPushButton *mClose; QPushButton *mCancel; - QPushButton *mDelete; + QPushButton *mMark; QPushButton *mRefresh; QLabel *mTotal; QList<QString> mTotals; DbAnalyzer *mAnalyzer; + int mMarkMode; + QTreeView *mCurrentView; }; class DbAnalyzer : public QThread { Q_OBJECT public: enum Status { Ok, Fail }; + enum Marks { NOMARKS = 0, MARKS_ACTORS = 1, MARKS_COVERS = 2 }; explicit DbAnalyzer(QObject *parent = 0); ~DbAnalyzer(); int status() { return mStatus; } - const QList<QList<QVariant> > noActors() { return mNoActorR; } - const QList<QList<QVariant> > noCovers() { return mNoCoverR; } + const QList<QList<QVariant> > noActors() const { return mNoActorR; } + const QHash<int, QVariant> actorMarks() const { return mActorMarks; } + const QList<QList<QVariant> > noCovers() const { return mNoCoverR; } + const QHash<int, QVariant> coverMarks() const { return mCoverMarks; } const QList<QList<QVariant> > strayActors() { return mStrayActorR; } const QList<QList<QVariant> > strayGenres() { return mStrayGenresR; } public slots: void setCancel(bool canceled); + void setMarks(const QList<int> &ids, int reason, int mark_id); + void deleteMarks(const QList<int> &ids, int reason); signals: void message(const QString &); @@ -89,15 +100,22 @@ class DbAnalyzer : public QThread { private: const QList<QList<QVariant> > noDataCheck(QSqlQuery *query); const QList<QList<QVariant> > strayCheck(QSqlQuery *query); + QHash<int, QVariant> marks(int markType); + void setStatus(int status); QSqlDatabase mDb; QSqlQuery *mNoActorQuery; QSqlQuery *mNoCoverQuery; QSqlQuery *mStrayActorsQuery; QSqlQuery *mStrayGenresQuery; + QSqlQuery *mMarksQuery; + QSqlQuery *mSetMarksQuery; + QSqlQuery *mDeleteMarksQuery; QList<QList<QVariant> > mNoActorR; QList<QList<QVariant> > mNoCoverR; QList<QList<QVariant> > mStrayActorR; QList<QList<QVariant> > mStrayGenresR; + QHash<int, QVariant> mActorMarks; + QHash<int, QVariant> mCoverMarks; QMutex mCancelMutex; QMutex mStatusMutex; bool mCanceled; diff --git a/smtreeitem.cpp b/smtreeitem.cpp index 5584319..56d9b6e 100644 --- a/smtreeitem.cpp +++ b/smtreeitem.cpp @@ -73,6 +73,14 @@ void SmTreeItem::setData(int column, const QVariant &data){ mData[column] = data; } +QVariant SmTreeItem::foregroundColor() const{ + return mForegroundColor; +} + +void SmTreeItem::setForegroundColor(const QVariant &data){ + mForegroundColor = data; +} + bool SmTreeItem::insertChild(int where, SmTreeItem *child){ if((where < 0) || (where > mChildren.count())){ return false; diff --git a/smtreeitem.h b/smtreeitem.h index 591f2a4..28ab77a 100644 --- a/smtreeitem.h +++ b/smtreeitem.h @@ -26,6 +26,8 @@ class SmTreeItem { void setParent(SmTreeItem *parent); QVariant data(int column) const; void setData(int column, const QVariant &data); + QVariant foregroundColor() const; + void setForegroundColor(const QVariant &data); bool insertChild(int where, SmTreeItem *child); bool removeChild(int where, bool deleteChild = true); @@ -33,6 +35,7 @@ class SmTreeItem { private: QList<SmTreeItem*> mChildren; QList<QVariant> mData; + QVariant mForegroundColor; SmTreeItem *mParent; }; diff --git a/smtreemodel.cpp b/smtreemodel.cpp index 50a55d0..86d2b77 100644 --- a/smtreemodel.cpp +++ b/smtreemodel.cpp @@ -7,6 +7,7 @@ #include <QIcon> #include <QSettings> +#include <QBrush> #include "smtreemodel.h" #include "smtreeitem.h" @@ -107,6 +108,10 @@ QVariant SmTreeModel::data(const QModelIndex &index, int role) const{ return mDecorationIcon; } } + if(role == Qt::ForegroundRole){ + QColor fgCol = item->foregroundColor().value<QColor>(); + return QBrush(fgCol); + } return QVariant(); } |