summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArno Moeller <arno.moeller@bit.bremerhaven.de>2013-07-18 16:23:22 +0200
committerArno Moeller <arno.moeller@bit.bremerhaven.de>2013-07-19 13:02:51 +0200
commit536643c36b61ddbce1a1b3efb70488ad83f7ae7b (patch)
tree69756bfa3cd37a5edc782db87e13829c3cf0c3ef
parent057da448ad06de20b8054ae1ba5ed7f6fb656c1b (diff)
downloadSheMov-536643c36b61ddbce1a1b3efb70488ad83f7ae7b.tar.gz
SheMov-536643c36b61ddbce1a1b3efb70488ad83f7ae7b.tar.bz2
SheMov-536643c36b61ddbce1a1b3efb70488ad83f7ae7b.zip
Clean up the db analyzer mess
I guess I was quite drunk when I designed this overengineered, multithreaded monstrosity. Replace it with 4 nifty dialogs.
-rw-r--r--archivetreeview.cpp13
-rw-r--r--archivetreeview.h1
-rw-r--r--dbanalyzer.cpp506
-rw-r--r--dbanalyzer.h135
-rw-r--r--main.cpp2
-rw-r--r--shemov.cpp65
-rw-r--r--shemov.h18
7 files changed, 238 insertions, 502 deletions
diff --git a/archivetreeview.cpp b/archivetreeview.cpp
index 2eb0b14..d6dc7b0 100644
--- a/archivetreeview.cpp
+++ b/archivetreeview.cpp
@@ -156,17 +156,6 @@ void ArchiveTreeView::cleanDatabase(const QString &table){
}
}
-void ArchiveTreeView::selectMoviePart(int seriespartId, int seriesId){
- QModelIndex seriesIdx = mSeriesModel->findValue(seriesId, QModelIndex(), SeriesTreeModel::SeriesId);
- QModelIndex partIdx = mSeriesModel->findValue(seriespartId, seriesIdx, SeriesTreeModel::SeriesPartId);
- if(partIdx.isValid()){
- QModelIndex viewSelect = mSeriesWidget->seriesProxy()->mapFromSource(partIdx);
- mSeriesWidget->seriesTree()->expand(viewSelect.parent());
- mSeriesWidget->seriesTree()->selectionModel()->select(viewSelect, QItemSelectionModel::Clear | QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
- mSeriesWidget->seriesTree()->scrollTo(viewSelect.parent(), QAbstractItemView::PositionAtTop);
- }
-}
-
void ArchiveTreeView::copyPath(int type){
QModelIndexList selected = mFilesWidget->filesTree()->selectionModel()->selectedRows();
if(selected.isEmpty()){
@@ -254,7 +243,7 @@ void ArchiveTreeView::currentChanged(const QItemSelection &selected, const QItem
mFilesWidget->filesTree()->header()->resizeSections(QHeaderView::ResizeToContents);
setMappingItems(selectedPartIds, mActorsModel, mActorsWidget);
setMappingItems(selectedPartIds, mGenresModel, mGenresWidget);
- mMetaData->setSeriesPartId(selectedPartIds.at(0));
+ mMetaData->setSeriesPartId(selectedPartIds.at(0));
}
void ArchiveTreeView::setMappingItems(QList<int>seriesPartIds, MappingTableModel *model, MappingTableWidget *widget){
diff --git a/archivetreeview.h b/archivetreeview.h
index b62d323..ad23bc1 100644
--- a/archivetreeview.h
+++ b/archivetreeview.h
@@ -39,7 +39,6 @@ class ArchiveTreeView : public QWidget {
void showAllFiles(bool toggled);
void showForBurn(bool toggled);
void cleanDatabase(const QString &table);
- void selectMoviePart(int seriespartId, int seriesId);
void copyPath(int type);
void readSettings();
diff --git a/dbanalyzer.cpp b/dbanalyzer.cpp
index f9e3830..c0b47ff 100644
--- a/dbanalyzer.cpp
+++ b/dbanalyzer.cpp
@@ -11,441 +11,187 @@
#include <QtWidgets/QMenu>
#include <QtWidgets/QStackedLayout>
+#include <QStandardItemModel>
+#include <QItemSelectionModel>
+
#include "dbanalyzer.h"
#include "smtreemodel.h"
#include "smtreeitem.h"
#include "smglobals.h"
#include "smtreeview.h"
-DbAnalyzerDialog::DbAnalyzerDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f), mMarkMode(DbAnalyzer::NOMARKS), mCurrentView(0){
- //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 SmTreeView;
- 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::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;
- QStringList noCoversHeaders = QStringList() << tr("Series") << tr("Part/Subtitle") << tr("Series Part") << tr("Seriespart Id") << tr("Series Id") << tr("Seriespart");
- mNoCoversV = new SmTreeView;
- mNoCoversM = new SmTreeModel(noCoversHeaders, this);
- mNoCoversV->setModel(mNoCoversM);
- QVBoxLayout *noCoversL = new QVBoxLayout;
- noCoversL->addWidget(mNoCoversV);
- mNoCoversV->setColumnHidden(2, true);
- mNoCoversV->setColumnHidden(3, true);
- mNoCoversV->setColumnHidden(4, true);
- mNoCoversV->setColumnHidden(5, true);
- mNoCoversV->setEditTriggers(QTreeView::NoEditTriggers);
- mNoCoversV->setSelectionBehavior(QAbstractItemView::SelectRows);
- mNoCoversV->setSelectionMode(QAbstractItemView::ExtendedSelection);
- mNoCoversV->setAlternatingRowColors(true);
- connect(mNoCoversV, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(noDataDoubleClicked(QModelIndex)));
- noCoversT->setLayout(noCoversL);
-
- //stray actors
- QWidget *strayActorsT = new QWidget;
- QStringList strayActorsHeaders = QStringList() << tr("Actor") << tr("Actor Id") << tr("Count");
- mStrayActorsV = new SmTreeView;
- 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);
-
- //stray genres
- QWidget *strayGenresT = new QWidget;
- QStringList strayGenresHeaders = QStringList() << tr("Genre") << tr("Genre Id") << tr("Count");
- mStrayGenresV = new SmTreeView;
- 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()));
+DbEmptyDialog::DbEmptyDialog(const QString &caption, QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f){
+ mDb = QSqlDatabase::database("treedb");
+ mDb.open();
+ QString c = QString(tr("<b>Unused %1</b>")).arg(caption);
+ QLabel *l = new QLabel(c);
+ mView = new SmTreeView(this);
+ mModel = new QStandardItemModel;
+ mView->setModel(mModel);
+
+ mDelete = new QPushButton(tr("Delete"));
+ connect(mDelete, SIGNAL(clicked()), this, SLOT(deleteItem()));
mClose = new QPushButton(tr("Close"));
connect(mClose, SIGNAL(clicked()), this, SLOT(accept()));
- 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()));
- mDelete = new QPushButton(tr("Delete..."));
- connect(mDelete, SIGNAL(clicked()), this, SLOT(deleteItems()));
- mButtonStack = new QStackedLayout;
- mButtonStack->addWidget(mMark);
- mButtonStack->addWidget(mDelete);
-
- //setup dialog
- mTab->addTab(noActorsT, tr("No Actors"));
- mTab->addTab(noCoversT, tr("No Covers"));
- mTab->addTab(strayActorsT, tr("Stray actors"));
- mTab->addTab(strayGenresT, tr("Stray genres"));
- //buttons
QHBoxLayout *buttonLayout = new QHBoxLayout;
- buttonLayout->addWidget(mCancel);
- buttonLayout->addWidget(mRefresh);
+ buttonLayout->addWidget(mDelete);
buttonLayout->addStretch();
- buttonLayout->addLayout(mButtonStack);
buttonLayout->addWidget(mClose);
- //totals
- mTotal = new QLabel(tr("<b>Total items: 0</b>"));
- mTotal->setAlignment(Qt::AlignCenter);
- QHBoxLayout *totalLayout = new QHBoxLayout;
- totalLayout->addWidget(mTotal);
-
- //setup dialog
QVBoxLayout *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(mTab);
- mainLayout->addLayout(totalLayout);
+ mainLayout->addWidget(l);
+ mainLayout->addWidget(mView);
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()));
- for(int i = 0; i < mTab->count(); ++i){
- mTotals << QString();
- }
- mAnalyzer->start();
}
-void DbAnalyzerDialog::refresh(){
- if(!mAnalyzer->isRunning()){
- mAnalyzer->start();
- }
+QItemSelectionModel *DbEmptyDialog::selectionModel(){
+ return mView->selectionModel();
}
-void DbAnalyzerDialog::cancelAnalyzer(){
- mAnalyzer->setCancel(true);
+void DbEmptyDialog::populate(){
+ return;
}
-void DbAnalyzerDialog::analyzerStarted(){
- mCancel->setEnabled(true);
- mRefresh->setEnabled(false);
- mClose->setEnabled(false);
+void DbEmptyDialog::deleteItem(){
+ return;
}
-void DbAnalyzerDialog::analyzerFinished(){
- mCancel->setEnabled(false);
- mRefresh->setEnabled(true);
- mClose->setEnabled(true);
- 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>"));
- mTotals[0] = totalString.arg(QString::number(mAnalyzer->noActors().count()));
- mTotals[1] = totalString.arg(QString::number(mAnalyzer->noCovers().count()));
- mTotals[2] = totalString.arg(QString::number(mAnalyzer->strayActors().count()));
- mTotals[3] = totalString.arg(QString::number(mAnalyzer->strayGenres().count()));
- mTotal->setText(mTotals.at(mTab->currentIndex()));
-}
+EmptyActorsDialog::EmptyActorsDialog(const QString &caption, QWidget *parent, Qt::WindowFlags f) : DbEmptyDialog(caption, parent, f){}
-void DbAnalyzerDialog::noDataDoubleClicked(const QModelIndex &idx){
- if(mTab->currentIndex() > 1){
- return;
- }
- if(!idx.isValid()){
- return;
+void EmptyActorsDialog::populate(){
+ model()->clear();
+ model()->setHorizontalHeaderLabels(QStringList() << tr("Name") << tr("Count") << tr("Id"));
+ QSqlQuery q("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", db());
+ while(q.next()){
+ QStandardItem *nameItem = new QStandardItem(q.value(0).toString());
+ nameItem->setIcon(QIcon(":/chastity_belt.png"));
+ QStandardItem *idItem = new QStandardItem(QString::number(q.value(1).toInt()));
+ idItem->setData(q.value(1));
+ QStandardItem *countItem = new QStandardItem(QString::number(q.value(2).toInt()));
+ countItem->setData(q.value(2));
+
+ model()->appendRow(QList<QStandardItem*>() << nameItem << countItem << idItem);
}
- const QAbstractItemModel *model = idx.model();
- QModelIndex seriesPartIdx = model->index(idx.row(), 5, idx.parent());
- QModelIndex seriesIdx = model->index(idx.row(), 4, idx.parent());
- emit partClicked(seriesPartIdx.data().toInt(), seriesIdx.data().toInt());
}
-void DbAnalyzerDialog::deleteItems(){
- SmTreeView *view = 0;
- int deleteMode;
- switch(mTab->currentIndex()){
- case 0:
- case 1:
- return;
- break;
- case 2:
- view = mStrayActorsV;
- deleteMode = Actors;
- break;
- case 3:
- view = mStrayGenresV;
- deleteMode = Genres;
- break;
- default:
- view = 0;
- break;
+void EmptyActorsDialog::deleteItem(){
+ QModelIndexList sel = selectionModel()->selectedRows(2);
+ if(sel.isEmpty()){
+ return;
}
- Q_ASSERT(view);
- QModelIndexList selected = view->selectionModel()->selectedRows(1);
- QList<int> ids;
- foreach(QModelIndex i, selected){
- ids << i.data().toInt();
+ QSqlQuery deleteQ(db());
+ deleteQ.prepare("DELETE FROM actors WHERE iactors_id = :id");
+ foreach(QModelIndex i, sel){
+ QStandardItem *item = model()->itemFromIndex(i);
+ deleteQ.bindValue(":id", item->data());
+ deleteQ.exec();
}
- emit delItems(deleteMode, ids);
+ populate();
}
-void DbAnalyzerDialog::tabChanged(int index){
- switch(index){
- case 0:
- mMarkMode = DbAnalyzer::MARKS_ACTORS;
- mCurrentView = mNoActorsV;
- mButtonStack->setCurrentWidget(mMark);
- break;
- case 1:
- mMarkMode = DbAnalyzer::MARKS_COVERS;
- mCurrentView = mNoCoversV;
- mButtonStack->setCurrentWidget(mMark);
- break;
- case 2:
- mMarkMode = DbAnalyzer::NOMARKS;
- mCurrentView = mStrayActorsV;
- mButtonStack->setCurrentWidget(mDelete);
- break;
- case 3:
- mMarkMode = DbAnalyzer::NOMARKS;
- mCurrentView = mStrayGenresV;
- mButtonStack->setCurrentWidget(mDelete);
- break;
- default:
- mMarkMode = DbAnalyzer::NOMARKS;
- mCurrentView = 0;
- break;
- }
- mTotal->setText(mTotals.at(index));
-}
+EmptyGenresDialog::EmptyGenresDialog(const QString &caption, QWidget *parent, Qt::WindowFlags f) : DbEmptyDialog(caption, parent, f){}
-void DbAnalyzerDialog::setMarks(){
- if(mMarkMode != DbAnalyzer::NOMARKS){
- const QList<int> curIds = currentIds();
- mAnalyzer->setMarks(curIds, mMarkMode, 1);
- refresh();
- }
-}
+void EmptyGenresDialog::populate(){
+ model()->clear();
+ model()->setHorizontalHeaderLabels(QStringList() << tr("Name") << tr("Count") << tr("Id"));
+ QSqlQuery q("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", db());
+ while(q.next()){
+ QStandardItem *nameItem = new QStandardItem(q.value(0).toString());
+ nameItem->setIcon(QIcon(":/chastity_belt.png"));
+ QStandardItem *idItem = new QStandardItem(QString::number(q.value(1).toInt()));
+ idItem->setData(q.value(1));
+ QStandardItem *countItem = new QStandardItem(QString::number(q.value(2).toInt()));
+ countItem->setData(q.value(2));
-void DbAnalyzerDialog::deleteMarks(){
- if(mMarkMode != DbAnalyzer::NOMARKS){
- const QList<int> curIds = currentIds();
- mAnalyzer->deleteMarks(curIds, mMarkMode);
- refresh();
+ model()->appendRow(QList<QStandardItem*>() << nameItem << countItem << idItem);
}
}
-void DbAnalyzerDialog::populate(SmTreeView *view, SmTreeModel *model, const QList<QList<QVariant> > &data, const QHash<int, QVariant> &marks){
- if(data.isEmpty()){
- return;
- }
- const int columns = data.first().count();
- if(columns == 0){
+void EmptyGenresDialog::deleteItem(){
+ QModelIndexList sel = selectionModel()->selectedRows(2);
+ if(sel.isEmpty()){
return;
}
- 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);
+ QSqlQuery deleteQ(db());
+ deleteQ.prepare("DELETE FROM genres WHERE igenres_id = :id");
+ foreach(QModelIndex i, sel){
+ QStandardItem *item = model()->itemFromIndex(i);
+ deleteQ.bindValue(":id", item->data());
+ deleteQ.exec();
}
- model->setRoot(root);
- view->resizeColumnToContents(0);
+ populate();
}
-const QList<int> DbAnalyzerDialog::currentIds() const {
- SmTreeView *curView = qobject_cast<SmTreeView*>(mCurrentView);
- Q_ASSERT(curView);
- QModelIndexList curIdxs = curView->selectionModel()->selectedRows(4);
- QList<int> retval;
- foreach(QModelIndex i, curIdxs){
- retval << i.data().toInt();
- }
- return retval;
-}
+EmptySeriesDialog::EmptySeriesDialog(const QString &caption, QWidget *parent, Qt::WindowFlags f) : DbEmptyDialog(caption, parent, f){}
-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");
- 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(){
- delete mNoActorQuery;
- delete mNoCoverQuery;
- delete mStrayActorsQuery;
- delete mStrayGenresQuery;
- delete mMarksQuery;
- delete mSetMarksQuery;
- delete mDeleteMarksQuery;
- mDb.close();
- mDb = QSqlDatabase();
- QSqlDatabase::removeDatabase("analyzerDb");
-}
-
-void DbAnalyzer::setCancel(bool canceled){
- QMutexLocker m(&mCancelMutex);
- 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;
- }
+void EmptySeriesDialog::populate(){
+ model()->clear();
+ model()->setHorizontalHeaderLabels(QStringList() << tr("Name") << tr("Count") << tr("Id"));
+ QSqlQuery q("SELECT series.tseries_name, COUNT(seriesparts.iseries_id), series.iseries_id FROM series LEFT JOIN seriesparts ON series.iseries_id = seriesparts.iseries_id GROUP BY 1,3 HAVING COUNT(seriesparts.iseries_id) = 0 ORDER BY series.tseries_name ASC", db());
+ while(q.next()){
+ QStandardItem *nameItem = new QStandardItem(q.value(0).toString());
+ nameItem->setIcon(QIcon(":/chastity_belt.png"));
+ QStandardItem *countItem = new QStandardItem(QString::number(q.value(1).toInt()));
+ countItem->setData(q.value(1));
+ QStandardItem *idItem = new QStandardItem(QString::number(q.value(2).toInt()));
+ idItem->setData(q.value(2));
+ model()->appendRow(QList<QStandardItem*>() << nameItem << countItem << idItem);
}
- 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;
- }
+void EmptySeriesDialog::deleteItem(){
+ QModelIndexList sel = selectionModel()->selectedRows(2);
+ if(sel.isEmpty()){
+ 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);
+ QSqlQuery deleteQ(db());
+ deleteQ.prepare("DELETE FROM series WHERE iseries_id = :id");
+ foreach(QModelIndex i, sel){
+ QStandardItem *item = model()->itemFromIndex(i);
+ deleteQ.bindValue(":id", item->data());
+ deleteQ.exec();
+ }
+ populate();
}
-const QList<QList<QVariant> > DbAnalyzer::noDataCheck(QSqlQuery *query){
- if(!query->exec()){
- setStatus(Fail);
- return QList<QList<QVariant> >();
- }
+EmptyPartsDialog::EmptyPartsDialog(const QString &caption, QWidget *parent, Qt::WindowFlags f) : DbEmptyDialog(caption, parent, f){}
- //read data
- QList<QList<QVariant> > retval;
- while(query->next()){
- if(mCanceled){
- break;
+void EmptyPartsDialog::populate(){
+ model()->clear();
+ model()->setHorizontalHeaderLabels(QStringList() << tr("Name") << tr("Count") << tr("Id"));
+ QSqlQuery q("SELECT seriesparts.iseriesparts_id, series.tseries_name, seriesparts.iseriespart, seriesparts.tsubtitle, COUNT(files.ifiles_id) FROM seriesparts LEFT JOIN files ON files.iseriespart_id = seriesparts.iseriesparts_id INNER JOIN series ON series.iseries_id = seriesparts.iseries_id GROUP BY 1,2,3,4 HAVING COUNT(files.ifiles_id) = 0 ORDER BY series.tseries_name ASC", db());
+ while(q.next()){
+ QString sName = q.value(1).toString();
+ int part = q.value(2).toInt();
+ if(part > 0){
+ sName.append(QString(" %1").arg(QString::number(part)));
}
- QList<QVariant> res;
- res << query->value(0);
- if(!query->value(2).isNull()){
- res << query->value(2);
- }else{
- res << query->value(1);
+ if(!q.value(3).toString().isEmpty()){
+ sName.append(QString(" - %1").arg(q.value(3).toString()));
}
- res << query->value(1) << query->value(2) << query->value(3) << query->value(4);
- retval << res;
+ QStandardItem *nameItem = new QStandardItem(sName);
+ nameItem->setIcon(QIcon(":/chastity_belt.png"));
+ QStandardItem *countItem = new QStandardItem(QString::number(q.value(4).toInt()));
+ countItem->setData(q.value(4));
+ QStandardItem *idItem = new QStandardItem(QString::number(q.value(0).toInt()));
+ idItem->setData(q.value(0));
+ model()->appendRow(QList<QStandardItem*>() << nameItem << countItem << idItem);
}
- return retval;
}
-const QList<QList<QVariant> > DbAnalyzer::strayCheck(QSqlQuery *query){
- if(!query->exec()){
- QMutexLocker m(&mStatusMutex);
- mStatus = Fail;
- return QList<QList<QVariant> >();
- }
- QList<QList<QVariant> > retval;
- while(query->next()){
- if(mCanceled){
- break;
- }
- QList<QVariant> res;
- res << query->value(0) << query->value(1) << query->value(2);
- retval << res;
- }
- 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;
+void EmptyPartsDialog::deleteItem(){
+ QModelIndexList sel = selectionModel()->selectedRows(2);
+ if(sel.isEmpty()){
+ return;
}
- while(mMarksQuery->next()){
- retval.insert(mMarksQuery->value(0).toInt(), mMarksQuery->value(1));
+ QSqlQuery deleteQ(db());
+ deleteQ.prepare("DELETE FROM seriesparts WHERE iseriesparts_id = :id");
+ foreach(QModelIndex i, sel){
+ QStandardItem *item = model()->itemFromIndex(i);
+ deleteQ.bindValue(":id", item->data());
+ deleteQ.exec();
}
- return retval;
-}
-
-void DbAnalyzer::setStatus(int status){
- QMutexLocker m(&mStatusMutex);
- mStatus = status;
+ populate();
}
diff --git a/dbanalyzer.h b/dbanalyzer.h
index cc88bbc..9fc2ef2 100644
--- a/dbanalyzer.h
+++ b/dbanalyzer.h
@@ -8,116 +8,75 @@
#ifndef DBANALYZER_H
#define DBANALYZER_H
-#include <QThread>
-#include <QtWidgets/QDialog>
+#include <QDialog>
#include <QSqlDatabase>
-#include <QMutex>
#include <QModelIndex>
-class QTabWidget;
class SmTreeView;
-class SmTreeModel;
-class DbAnalyzer;
class QLabel;
class QStackedLayout;
-class DbAnalyzerDialog : public QDialog {
+class QStandardItemModel;
+class QItemSelectionModel;
+
+class DbEmptyDialog : public QDialog {
Q_OBJECT
public:
- enum Mode { Actors, Genres };
- explicit DbAnalyzerDialog(QWidget *parent = 0, Qt::WindowFlags f = 0);
-
- public slots:
- void refresh();
-
- signals:
- void partClicked(int seriesPartId, int seriesId);
- void delItems(int mode, QList<int> &ids);
-
- private slots:
- void cancelAnalyzer();
- void analyzerStarted();
- void analyzerFinished();
- void noDataDoubleClicked(const QModelIndex &);
- void deleteItems();
- void tabChanged(int index);
- void setMarks();
- void deleteMarks();
+ DbEmptyDialog(const QString &caption, QWidget *parent = 0, Qt::WindowFlags f = 0);
+ QStandardItemModel *model() { return mModel; }
+ QSqlDatabase db() { return mDb; }
+ QItemSelectionModel *selectionModel();
+
+ public slots:
+ virtual void populate();
+ virtual void deleteItem();
private:
- void populate(SmTreeView *view ,SmTreeModel *model, const QList<QList<QVariant> > &data, const QHash<int, QVariant> &marks = QHash<int, QVariant>());
- const QList<int> currentIds() const;
- QTabWidget *mTab;
- SmTreeView *mNoActorsV;
- SmTreeView *mNoCoversV;
- SmTreeView *mStrayActorsV;
- SmTreeView *mStrayGenresV;
- SmTreeModel *mNoActorsM;
- SmTreeModel *mNoCoversM;
- SmTreeModel *mStrayActorsM;
- SmTreeModel *mStrayGenresM;
+ SmTreeView *mView;
QPushButton *mClose;
- QPushButton *mCancel;
- QPushButton *mMark;
- QPushButton *mRefresh;
QPushButton *mDelete;
- QLabel *mTotal;
- QList<QString> mTotals;
- DbAnalyzer *mAnalyzer;
- int mMarkMode;
- SmTreeView *mCurrentView;
- QStackedLayout *mButtonStack;
+ QStandardItemModel *mModel;
+ QSqlDatabase mDb;
};
-class DbAnalyzer : public QThread {
+class EmptyActorsDialog : public DbEmptyDialog {
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() 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; }
+ explicit EmptyActorsDialog(const QString &caption, QWidget *parent = 0, Qt::WindowFlags f = 0);
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);
+ virtual void populate();
+ virtual void deleteItem();
+};
- signals:
- void message(const QString &);
+class EmptyGenresDialog : public DbEmptyDialog{
+ Q_OBJECT
+ public:
+ explicit EmptyGenresDialog(const QString &caption, QWidget *parent = 0, Qt::WindowFlags f = 0);
- protected:
- void run();
+ public slots:
+ virtual void populate();
+ virtual void deleteItem();
+};
- 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;
- int mStatus;
+class EmptySeriesDialog : public DbEmptyDialog{
+ Q_OBJECT
+ public:
+ explicit EmptySeriesDialog(const QString &caption, QWidget *parent, Qt::WindowFlags f = 0);
+
+ public slots:
+ virtual void populate();
+ virtual void deleteItem();
+};
+
+class EmptyPartsDialog : public DbEmptyDialog{
+ Q_OBJECT
+ public:
+ explicit EmptyPartsDialog(const QString &caption, QWidget *parent, Qt::WindowFlags f = 0);
+
+ public slots:
+ virtual void populate();
+ virtual void deleteItem();
};
#endif // DBANALYZER_H
diff --git a/main.cpp b/main.cpp
index 444b6c1..6f615bb 100644
--- a/main.cpp
+++ b/main.cpp
@@ -5,7 +5,7 @@
2 of the License, or (at your option) any later version.
*/
-#include <QtWidgets/QApplication>
+#include <QApplication>
#include "shemov.h"
diff --git a/shemov.cpp b/shemov.cpp
index c8f61d3..c7ba5db 100644
--- a/shemov.cpp
+++ b/shemov.cpp
@@ -100,9 +100,6 @@ SheMov::SheMov(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, fla
mNewMovieWizard->setMinimumWidth(1024);
ArchiveController *c = SmGlobals::instance()->archiveController();
connect(mNewMovieWizard, SIGNAL(accepted()), c->archiveTreeModel(), SLOT(refresh()));
- mDbAnalyzerDialog = new DbAnalyzerDialog(this);
- connect(mDbAnalyzerDialog, SIGNAL(partClicked(int, int)), mATree, SLOT(selectMoviePart(int, int)));
- connect(mDbAnalyzerDialog, SIGNAL(delItems(int,QList<int>&)), this, SLOT(analyzeDelete(int,QList<int>&)));
mNewPicsDialog = new NewPicsDialog(this);
QVBoxLayout *mainLayout = new QVBoxLayout;
@@ -392,8 +389,6 @@ void SheMov::createActions(){
connect(mArchiveSelectedPicsA, SIGNAL(triggered()), this, SLOT(newPicsDialogWithFiles()));
mConsistencyA = new QAction(tr("Check consisteny..."), this);
connect(mConsistencyA, SIGNAL(triggered()), this, SLOT(checkConsistency()));
- mAnalyzerA = new QAction(QIcon(":/higheels.png"), tr("Analyze Db..."), this);
- connect(mAnalyzerA, SIGNAL(triggered()), this, SLOT(analyzeDb()));
mNewPicsA = new QAction(tr("Archive pics...."), this);
connect(mNewPicsA, SIGNAL(triggered()), this, SLOT(newPicsDialog()));
@@ -768,18 +763,36 @@ void SheMov::createActions(){
mArchiveViewMetadataA->setData(ArchiveModel::SeriesPartNode);
connect(mArchiveViewMetadataA, SIGNAL(triggered()), c->archiveTree(), SLOT(editMetadata()));
- // ArchiveFiles actions
+ // ArchiveFiles actions <- ArchiveView!
+ // play selected
mArchiveFilesPlayA = new QAction(tr("Play selected..."), this);
connect(mArchiveFilesPlayA, SIGNAL(triggered()), c, SLOT(playSelectedFiles()));
+ // set quality
mArchiveFilesQualityA = new QAction(tr("Set Quality..."), this);
connect(mArchiveFilesQualityA, SIGNAL(triggered()), c, SLOT(editQuality()));
+ // set dvd
mArchiveFilesDvdNoA = new QAction(tr("Set Dvd No. ..."), this);
connect(mArchiveFilesDvdNoA, SIGNAL(triggered()), c, SLOT(editDvdNo()));
+ // set file type
mArchiveFilesTypeA = new QAction(tr("Set file type..."), this);
connect(mArchiveFilesTypeA, SIGNAL(triggered()), c, SLOT(editFileType()));
+ // set file no
mArchiveFilesFileNoA = new QAction(tr("Set File No. ..."), this);
connect(mArchiveFilesFileNoA, SIGNAL(triggered()), c, SLOT(editFileNo()));
+ // db analyzer dialogs
+ // analyze actors
+ mAnalyzeActorsA = new QAction(tr("Actors..."), this);
+ connect(mAnalyzeActorsA, SIGNAL(triggered()), this, SLOT(analyzeActors()));
+ // analyze genres
+ mAnalyzeGenresA = new QAction(tr("Genres..."), this);
+ connect(mAnalyzeGenresA, SIGNAL(triggered()), this, SLOT(analyzeGenres()));
+ // analyze series
+ mAnalyzeSeriesA = new QAction(tr("Series..."), this);
+ connect(mAnalyzeSeriesA, SIGNAL(triggered()), this, SLOT(analyzeSeries()));
+ // anaylze series parts
+ mAnalyzePartsA = new QAction(tr("Series Parts..."), this);
+ connect(mAnalyzePartsA, SIGNAL(triggered()), this, SLOT(analyzeParts()));
//don't add actions with checkable(true) unless you know what you're doing!
mPicActionGroup = new QActionGroup(this);
@@ -804,7 +817,12 @@ void SheMov::createMenus(){
fileMenu->addAction(mNewPicsA);
fileMenu->addSeparator();
fileMenu->addAction(mConsistencyA);
- fileMenu->addAction(mAnalyzerA);
+ QMenu *analyzeMenu = new QMenu(tr("Analyze"), this);
+ analyzeMenu->addAction(mAnalyzeActorsA);
+ analyzeMenu->addAction(mAnalyzeGenresA);
+ analyzeMenu->addAction(mAnalyzeSeriesA);
+ analyzeMenu->addAction(mAnalyzePartsA);
+ fileMenu->addMenu(analyzeMenu);
fileMenu->addAction(mRebuildFrameCacheA);
fileMenu->addSeparator();
fileMenu->addAction(mQuitA);
@@ -1095,7 +1113,6 @@ void SheMov::createToolBar(){
toolBar->addAction(mCdupA);
toolBar->addSeparator();
toolBar->addAction(mConfigA);
- toolBar->addAction(mAnalyzerA);
toolBar->addSeparator();
toolBar->addAction(mShowNormalA);
toolBar->addAction(mShowArchivedA);
@@ -1197,16 +1214,36 @@ void SheMov::rebuildFrameCache(){
}
}
+void SheMov::analyzeActors(){
+ EmptyActorsDialog d(tr("Actors"), this);
+ d.populate();
+ d.exec();
+}
+
+void SheMov::analyzeGenres(){
+ EmptyGenresDialog d(tr("Genres"), this);
+ d.populate();
+ d.exec();
+}
+
+void SheMov::analyzeSeries(){
+ EmptySeriesDialog d(tr("Series"), this);
+ d.populate();
+ d.exec();
+}
+
+void SheMov::analyzeParts(){
+ EmptyPartsDialog d(tr("Series Parts"), this);
+ d.populate();
+ d.exec();
+}
+
void SheMov::checkConsistency(){
ConsistencyCheck c;
c.exec();
}
-void SheMov::analyzeDb(){
- mDbAnalyzerDialog->show();
-}
-
-void SheMov::analyzeDelete(int mode, QList<int> &ids){
+/*void SheMov::analyzeDelete(int mode, QList<int> &ids){
QString message = QString(tr("Really delete %1 items?")).arg(QString::number(ids.count()));
int res = QMessageBox::question(this, tr("Delete items"), message, QMessageBox::Yes | QMessageBox::No);
if(res != QMessageBox::Yes){
@@ -1226,7 +1263,7 @@ void SheMov::analyzeDelete(int mode, QList<int> &ids){
Q_ASSERT(model);
model->deleteItems(ids);
mDbAnalyzerDialog->refresh();
-}
+}*/
void SheMov::toggleHover(QObject *object){
QAction *action = qobject_cast<QAction*>(object);
diff --git a/shemov.h b/shemov.h
index 100ae30..efccaa2 100644
--- a/shemov.h
+++ b/shemov.h
@@ -8,7 +8,7 @@
#ifndef SHEMOV_H
#define SHEMOV_H
-#include <QtWidgets/QMainWindow>
+#include <QMainWindow>
#include <QVariant>
class QTabWidget;
@@ -18,7 +18,6 @@ class QSignalMapper;
class QActionGroup;
class ArchiveTreeView;
class NewMovieWizard;
-class DbAnalyzerDialog;
class PicturesWidget;
class SmTreeModel;
class NewPicsDialog;
@@ -48,8 +47,6 @@ class SheMov : public QMainWindow {
void setSize(qint64 size);
void setDuration(const QVariant dur);
void checkConsistency();
- void analyzeDb();
- void analyzeDelete(int mode, QList<int> &ids);
void toggleHover(QObject *object);
void checkMount(bool mounted);
void toggleFilterGroup(bool checked);
@@ -58,6 +55,11 @@ class SheMov : public QMainWindow {
void newPicsDialogWithFiles();
void rebuildFrameCache();
+ void analyzeActors();
+ void analyzeGenres();
+ void analyzeSeries();
+ void analyzeParts();
+
signals:
void configChanged();
@@ -107,7 +109,6 @@ class SheMov : public QMainWindow {
QAction *mArchiveSelectedMovsA;
QAction *mArchiveSelectedPicsA;
QAction *mConsistencyA;
- QAction *mAnalyzerA;
QAction *mNewPicsA;
QAction *mHoverDirectoriesA;
QAction *mRebuildFrameCacheA;
@@ -202,6 +203,12 @@ class SheMov : public QMainWindow {
QAction *mArchiveFilesTypeA;
QAction *mArchiveFilesFileNoA;
+ //DB analyze actions
+ QAction *mAnalyzeActorsA;
+ QAction *mAnalyzeGenresA;
+ QAction *mAnalyzeSeriesA;
+ QAction *mAnalyzePartsA;
+
QSignalMapper *mOpenWithMapperFS;
QSignalMapper *mOpenWithMapperAV;
QSignalMapper *mFilterMapper;
@@ -234,7 +241,6 @@ class SheMov : public QMainWindow {
ArchiveTreeView *mATree;
NewMovieWizard *mNewMovieWizard;
NewPicsDialog *mNewPicsDialog;
- DbAnalyzerDialog *mDbAnalyzerDialog;
PicturesWidget *mPicWidget;
ArchiveView *mArchive;
};