/* 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 #include #include #include #include #include #include #include #include #include "dbanalyzer.h" #include "smtreemodel.h" #include "smtreeitem.h" DbAnalyzerDialog::DbAnalyzerDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f){ //create tab widget mTab = new QTabWidget; //setup analyzer mAnalyzer = new DbAnalyzer(this); // no actors QWidget *noActorsT = new QWidget; QStringList noActorsHeaders = QStringList() << tr("Series") << tr("Part/Subtitle") << tr("Series Part") << tr("Seriespart Id") << tr("Series Id") << tr("Seriespart"); mNoActorsV = new QTreeView; mNoActorsM = new SmTreeModel(noActorsHeaders, this); mNoActorsV->setModel(mNoActorsM); QVBoxLayout *noActorsL = new QVBoxLayout; noActorsL->addWidget(mNoActorsV); mNoActorsV->setColumnHidden(2, true); mNoActorsV->setColumnHidden(3, true); mNoActorsV->setColumnHidden(4, true); mNoActorsV->setColumnHidden(5, true); mNoActorsV->setEditTriggers(QTreeView::NoEditTriggers); mNoActorsV->setSelectionBehavior(QAbstractItemView::SelectRows); mNoActorsV->setSelectionMode(QAbstractItemView::SingleSelection); mNoActorsV->setAlternatingRowColors(true); connect(mNoActorsV, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(noActorsDoubleClicked(QModelIndex))); noActorsT->setLayout(noActorsL); //stray actors QWidget *strayActorsT = new QWidget; QStringList strayActorsHeaders = QStringList() << tr("Actor") << tr("Actor Id") << tr("Count"); mStrayActorsV = new QTreeView; mStrayActorsM = new SmTreeModel(strayActorsHeaders, this); mStrayActorsV->setModel(mStrayActorsM); QVBoxLayout *strayActorsL = new QVBoxLayout; strayActorsL->addWidget(mStrayActorsV); mStrayActorsV->setColumnHidden(1, true); mStrayActorsV->setEditTriggers(QTreeView::NoEditTriggers); mStrayActorsV->setSelectionBehavior(QAbstractItemView::SelectRows); mStrayActorsV->setSelectionMode(QAbstractItemView::ExtendedSelection); mStrayActorsV->setAlternatingRowColors(true); strayActorsT->setLayout(strayActorsL); //strac genres QWidget *strayGenresT = new QWidget; QStringList strayGenresHeaders = QStringList() << tr("Genre") << tr("Genre Id") << tr("Count"); mStrayGenresV = new QTreeView; mStrayGenresM = new SmTreeModel(strayGenresHeaders, this); mStrayGenresV->setModel(mStrayGenresM); QVBoxLayout *strayGenresL = new QVBoxLayout; strayGenresL->addWidget(mStrayGenresV); mStrayGenresV->setColumnHidden(1, true); mStrayGenresV->setEditTriggers(QTreeView::NoEditTriggers); mStrayGenresV->setSelectionBehavior(QAbstractItemView::SelectRows); mStrayGenresV->setSelectionMode(QAbstractItemView::ExtendedSelection); mStrayGenresV->setAlternatingRowColors(true); strayGenresT->setLayout(strayGenresL); //buttons mCancel = new QPushButton(tr("Cancel")); connect(mCancel, SIGNAL(clicked()), this, SLOT(cancelAnalyzer())); mRefresh = new QPushButton(tr("Refresh")); 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())); //setup dialog mTab->addTab(noActorsT, tr("No Actors")); mTab->addTab(strayActorsT, tr("Stray actors")); mTab->addTab(strayGenresT, tr("Stray genres")); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(mTab); QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->addWidget(mCancel); buttonLayout->addWidget(mRefresh); buttonLayout->addStretch(); buttonLayout->addWidget(mDelete); buttonLayout->addWidget(mClose); mainLayout->addLayout(buttonLayout); setLayout(mainLayout); setMinimumWidth(500); //get things going connect(mTab, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); connect(mAnalyzer, SIGNAL(started()), this, SLOT(analyzerStarted())); connect(mAnalyzer, SIGNAL(finished()), this, SLOT(analyzerFinished())); mAnalyzer->start(); } void DbAnalyzerDialog::refresh(){ if(!mAnalyzer->isRunning()){ mAnalyzer->start(); } } void DbAnalyzerDialog::cancelAnalyzer(){ mAnalyzer->setCancel(true); } void DbAnalyzerDialog::analyzerStarted(){ mCancel->setEnabled(true); mRefresh->setEnabled(false); mClose->setEnabled(false); } void DbAnalyzerDialog::analyzerFinished(){ mCancel->setEnabled(false); mRefresh->setEnabled(true); mClose->setEnabled(true); populate(mNoActorsV, mNoActorsM, mAnalyzer->noActors()); populate(mStrayActorsV, mStrayActorsM, mAnalyzer->strayActors()); populate(mStrayGenresV, mStrayGenresM, mAnalyzer->strayGenres()); } void DbAnalyzerDialog::noActorsDoubleClicked(const QModelIndex &idx){ if(!idx.isValid()){ return; } QModelIndex seriesPartIdx = mNoActorsM->index(idx.row(), 5, idx.parent()); QModelIndex seriesIdx = mNoActorsM->index(idx.row(), 4, idx.parent()); emit partClicked(seriesPartIdx.data().toInt(), seriesIdx.data().toInt()); } void DbAnalyzerDialog::deleteItems(){ QTreeView *view = 0; int deleteMode; switch(mTab->currentIndex()){ case 0: return; break; case 1: view = mStrayActorsV; deleteMode = Actors; break; case 2: view = mStrayGenresV; deleteMode = Genres; break; default: view = 0; break; } Q_ASSERT(view); QModelIndexList selected = view->selectionModel()->selectedRows(1); QList ids; foreach(QModelIndex i, selected){ ids << i.data().toInt(); } emit delItems(deleteMode, ids); } void DbAnalyzerDialog::tabChanged(int index){ mDelete->setEnabled(index != 0); } void DbAnalyzerDialog::populate(QTreeView *view, SmTreeModel *model, const QList > &data){ const int columns = data.first().count(); if(columns == 0){ return; } SmTreeItem *root = new SmTreeItem(columns); foreach(QList l, data){ SmTreeItem *child = new SmTreeItem(l, root); root->appendChild(child); } model->setRoot(root); view->resizeColumnToContents(0); } DbAnalyzer::DbAnalyzer(QObject *parent) : QThread(parent), mCanceled(false), mStatus(Fail) { mDb = QSqlDatabase::cloneDatabase(QSqlDatabase::database("treedb"), "analyzerDb"); mDb.open(); mStatus = mDb.isOpen() ? Ok : Fail; mNoActorQuery = new QSqlQuery(mDb); mNoActorQuery->prepare("SELECT series.tseries_name, seriesparts.iseriespart, seriesparts.tsubtitle, series.iseries_id, seriesparts.iseriesparts_id FROM series, seriesparts LEFT JOIN seriesparts_actormap ON seriesparts.iseriesparts_id = seriesparts_actormap.iseriesparts_id WHERE iactors_id IS NULL AND seriesparts.iseries_id = series.iseries_id ORDER BY tseries_name"); mStrayActorsQuery = new QSqlQuery(mDb); mStrayActorsQuery->prepare("SELECT actors.tactorname, actors.iactors_id, COUNT(seriesparts_actormap.iactors_id) FROM actors LEFT JOIN seriesparts_actormap ON actors.iactors_id = seriesparts_actormap.iactors_id WHERE seriesparts_actormap.iactors_id IS NULL GROUP BY actors.iactors_id, actors.tactorname ORDER BY actors.tactorname"); mStrayGenresQuery = new QSqlQuery(mDb); 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"); } DbAnalyzer::~DbAnalyzer(){ delete mNoActorQuery; delete mStrayActorsQuery; delete mStrayGenresQuery; mDb.close(); mDb = QSqlDatabase(); QSqlDatabase::removeDatabase("analyzerDb"); } void DbAnalyzer::setCancel(bool canceled){ QMutexLocker m(&mCancelMutex); mCanceled = canceled; } void DbAnalyzer::run(){ noActorsCheck(); mStrayActorR = strayCheck(mStrayActorsQuery); mStrayGenresR = strayCheck(mStrayGenresQuery); } void DbAnalyzer::noActorsCheck(){ if(!mNoActorQuery->exec()){ mStatus = Fail; return; } emit message(tr("Fetching movies without actors")); while(mNoActorQuery->next()){ if(mCanceled){ break; } QList res; res << mNoActorQuery->value(0); if(!mNoActorQuery->value(2).isNull()){ res << mNoActorQuery->value(2); }else{ res << mNoActorQuery->value(1); } res << mNoActorQuery->value(1) << mNoActorQuery->value(2) << mNoActorQuery->value(3) << mNoActorQuery->value(4); mNoActorR << res; } emit message(tr("Done fetching movies")); } const QList > DbAnalyzer::strayCheck(QSqlQuery *query){ if(!query->exec()){ QMutexLocker m(&mStatusMutex); mStatus = Fail; return QList >(); } QList > retval; while(query->next()){ if(mCanceled){ break; } QList res; res << query->value(0) << query->value(1) << query->value(2); retval << res; } return retval; } /*void DbAnalyzer::strayActorsCheck(){ if(!mStrayActorsQuery->exec()){ QMutexLocker m(&mStatusMutex); mStatus = Fail; return; } emit message(tr("Fetching stray actors")); while(mStrayActorsQuery->next()){ if(mCanceled){ break; } QList res; res << mStrayActorsQuery->value(0) << mStrayActorsQuery->value(1) << mStrayActorsQuery->value(2); mStrayActorR << res; } emit message(tr("Done fetching stray actors")); }*/