/* 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 "smtreeitem.h" #include "archivemodel.h" ArchiveModel::ArchiveModel(const QStringList &headers, QObject *parent) : SmTreeModel(headers, parent), mOrder(NoOrder){ mDb = QSqlDatabase::database("treedb"); mAvailableOrders.insert("Series Name", SeriesName); mAvailableOrders.insert("Actor", Actor); mAvailableOrders.insert("Genre", Genre); mCollector = new ArchiveCollector(NumFields, this); connect(mCollector, SIGNAL(finished()), this, SLOT(collectorFinished())); } const QStringList ArchiveModel::availableOrders() const { QStringList retval = mAvailableOrders.keys(); qSort(retval); return retval; } QVariant ArchiveModel::data(const QModelIndex &index, int role) const{ SmTreeItem *item = itemAt(index); if(role == Qt::DisplayRole && index.column() == 0){ QString retval; int part = item->data(SeriesPart).toInt(); int childCount = item->data(Count).toInt(); int nodeType = item->data(Type).toInt(); if(nodeType == SeriesNode || nodeType == GenreNode || nodeType == ActorNode){ retval = QString("%1 (%2)").arg(item->data(Name).toString()).arg(QString::number(childCount)); }else if(nodeType == SeriesPartNode){ if(part > 0){ retval = QString("%1 %2").arg(item->data(Name).toString()).arg(QString::number(part)); }else{ QString subtitle = item->data(Subtitle).toString(); if(!subtitle.isEmpty()){ retval = QString("%1 - %2").arg(item->data(Name).toString()).arg(item->data(Subtitle).toString()); } } }else{ retval = item->data(Name).toString(); } return retval; } if(role == Qt::ForegroundRole){ bool favorite = item->data(Favorite).toBool(); if(favorite){ return QColor(Qt::darkGreen); } } return SmTreeModel::data(index, role); } QStringList ArchiveModel::indexToPath(const QModelIndex &idx) const { QStringList retval; SmTreeItem *item = itemAt(idx); while (item) { retval << item->data(Name).toString(); item = item->parent(); } std::reverse(retval.begin(), retval.end()); return retval; } QModelIndexList ArchiveModel::pathToIndex(const QStringList &path) const { QModelIndexList retval; QModelIndex parentIdx = QModelIndex(); for(int i = 0; i < path.count(); ++i){ QString curItem = path.at(i); QModelIndex found = find(curItem, Name, parentIdx); if(found.isValid()){ retval << found; parentIdx = found; } } return retval; } void ArchiveModel::setOrder(int order) { mOrder = order; SmTreeItem *rootItem = new SmTreeItem(NumFields); mCollector->populate(mOrder, rootItem); if(!mCollector->isRunning()){ mCollector->start(); } } void ArchiveModel::setOrder(const QString &order){ int orderNum = mAvailableOrders.value(order); setOrder(orderNum); } void ArchiveModel::collectorFinished(){ SmTreeItem *item = mCollector->rootItem(); setRoot(item); } ArchiveCollector::ArchiveCollector(int numFields, QObject *parent) : QThread(parent), mNumFields(numFields) { mDb = QSqlDatabase::cloneDatabase(QSqlDatabase::database("treedb"), "archivedb"); mDb.open(); } void ArchiveCollector::populate(int order, SmTreeItem *rootItem){ mRootItem = rootItem; mSortOrder = order; } void ArchiveCollector::run(){ switch (mSortOrder){ case ArchiveModel::SeriesName: populateBySeriesName(); break; case ArchiveModel::Genre: populateByGenre(); break; case ArchiveModel::Actor: populateByActor(); break; default: return; } } void ArchiveCollector::populateBySeriesName() { fetchSeries(QVariant(), mRootItem); for(int i = 0; i < mRootItem->childCount(); ++i){ QString msg = QString("Processing %1").arg(mRootItem->child(i)->data(ArchiveModel::Name).toString()); emit message(msg); fetchParts(QVariant(), mRootItem->child(i)); } } void ArchiveCollector::populateByGenre(){ QSqlQuery genreIdQuery = QSqlQuery("SELECT igenres_id, tgenrename FROM genres ORDER BY tgenrename", mDb); while(genreIdQuery.next()){ QList genreIdData; genreIdData << genreIdQuery.value(1) << genreIdQuery.value(0) << QVariant() << QVariant() << ArchiveModel::GenreNode << false << QVariant() << QVariant() << QVariant(); SmTreeItem *genreIdItem = new SmTreeItem(genreIdData, mRootItem); mRootItem->appendChild(genreIdItem); } fetchChildren(mRootItem); } void ArchiveCollector::populateByActor(){ QSqlQuery actorIdQuery = QSqlQuery("SELECT iactors_id, tactorname FROM actors ORDER BY tactorname", mDb); while(actorIdQuery.next()){ QList actorIdData; actorIdData << actorIdQuery.value(1) << actorIdQuery.value(0) << QVariant() << QVariant() << ArchiveModel::GenreNode << false << QVariant() << QVariant() << QVariant(); SmTreeItem *actorIdItem = new SmTreeItem(actorIdData, mRootItem); mRootItem->appendChild(actorIdItem); } fetchChildren(mRootItem); } void ArchiveCollector::fetchChildren(SmTreeItem *parent){ for(int i = 0; i < parent->childCount(); ++i){ QString msg = QString("Processing %1").arg(parent->child(i)->data(ArchiveModel::Name).toString()); emit message(msg); fetchSeries(parent->child(i)->data(ArchiveModel::GenericId), parent->child(i)); for(int j = 0; j < parent->child(i)->childCount(); ++j){ SmTreeItem *seriesItem = parent->child(i)->child(j); fetchParts(parent->child(i)->data(ArchiveModel::GenericId), seriesItem); } } } void ArchiveCollector::fetchSeries(const QVariant &id, SmTreeItem *parent){ QSqlQuery seriesIdQuery(mDb); switch (mSortOrder) { case ArchiveModel::SeriesName: seriesIdQuery.prepare("SELECT iseries_id, tseries_name FROM series ORDER BY tseries_name"); break; case ArchiveModel::Genre: seriesIdQuery.prepare("SELECT distinct(series.iseries_id), tseries_name FROM series, seriesparts, seriesparts_genremap WHERE seriesparts_genremap.igenres_id = :genreid AND seriesparts_genremap.iseriesparts_id = seriesparts.iseriesparts_id AND seriesparts.iseries_id = series.iseries_id ORDER BY tseries_name"); seriesIdQuery.bindValue(":genreid", id); break; case ArchiveModel::Actor: seriesIdQuery.prepare("SELECT distinct(series.iseries_id), tseries_name FROM series, seriesparts, seriesparts_actormap WHERE seriesparts_actormap.iactors_id = :actorid AND seriesparts_actormap.iseriesparts_id = seriesparts.iseriesparts_id AND seriesparts.iseries_id = series.iseries_id ORDER BY tseries_name"); seriesIdQuery.bindValue(":actorid", id); break; default: qFatal("ArchiveTreeModel::fetchSeries: invalid order!"); return; } if(!seriesIdQuery.exec()){ qWarning("ArchiveTreeModel::fetchSeries: failed to exectue query!"); return; } while(seriesIdQuery.next()){ QList seriesData; seriesData << seriesIdQuery.value(1) << seriesIdQuery.value(0) << QVariant() << QVariant() << ArchiveModel::SeriesNode << false << QVariant() << QVariant() << QVariant(); SmTreeItem *seriesItem = new SmTreeItem(seriesData, parent); parent->appendChild(seriesItem); } parent->setData(ArchiveModel::Count, parent->childCount()); } void ArchiveCollector::fetchParts(const QVariant &id, SmTreeItem *parent){ QSqlQuery partsQuery(mDb); if(mSortOrder == ArchiveModel::SeriesName){ partsQuery.prepare("SELECT iseriesparts_id, iseriespart, bfavorite, tsubtitle FROM seriesparts WHERE iseries_id = :id ORDER BY iseriespart"); partsQuery.bindValue(":id", parent->data(ArchiveModel::GenericId)); }else if(mSortOrder == ArchiveModel::Genre){ partsQuery.prepare("SELECT seriesparts.iseriesparts_id, iseriespart, bfavorite, tsubtitle FROM seriesparts, seriesparts_genremap WHERE iseries_id = :id AND seriesparts.iseriesparts_id = seriesparts_genremap.iseriesparts_id AND seriesparts_genremap.igenres_id = :genreid ORDER BY iseriespart"); partsQuery.bindValue(":id", parent->data(ArchiveModel::GenericId)); partsQuery.bindValue(":genreid", id); }else if(mSortOrder == ArchiveModel::Actor){ partsQuery.prepare("SELECT seriesparts.iseriesparts_id, iseriespart, bfavorite, tsubtitle FROM seriesparts, seriesparts_actormap WHERE iseries_id = :id AND seriesparts.iseriesparts_id = seriesparts_actormap.iseriesparts_id AND seriesparts_actormap.iactors_id = :actorid ORDER BY iseriespart"); partsQuery.bindValue(":id", parent->data(ArchiveModel::GenericId)); partsQuery.bindValue(":actorid", id); } partsQuery.exec(); while(partsQuery.next()){ QList partData; partData << parent->data(ArchiveModel::Name) << parent->data(ArchiveModel::GenericId) << partsQuery.value(0) << partsQuery.value(1) << ArchiveModel::SeriesPartNode << partsQuery.value(2) << partsQuery.value(3) << QVariant(); SmTreeItem *partItem = new SmTreeItem(partData, parent); parent->appendChild(partItem); } parent->setData(ArchiveModel::Count, parent->childCount()); }