/* 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 "archivebrowsermodel.h" #include "smtreeitem.h" #include "smglobals.h" #include "helper.h" ArchiveBrowserModel::ArchiveBrowserModel(const QStringList &headers, QObject *parent) : SmTreeModel(headers, parent), mNumFields(10) { mDb = QSqlDatabase::database("treedb"); readConfig(); populate(); } QVariant ArchiveBrowserModel::data(const QModelIndex &index, int role) const { SmTreeItem *item = itemAt(index); int col = index.column(); if(role == Qt::DisplayRole && index.column() == 1){ return item->data(Name); } if(role == ExpansionRole){ return item->data(Expansion); } if(role == NameRole){ return item->data(Name); } if(role == GenericIdRole){ return item->data(GenericId); } if(role == NodeTypeRole){ return item->data(NodeType); } if(role == TotalSizeRole){ return item->data(TotalSize); } if(role == QualityRole){ return item->data(Quality); } if(role == FileTypeRole){ return item->data(FileType); } if(role == FullPathRole){ return item->data(FullPath); } if(role == SelectedRole){ return item->data(Selected); } if(role == GenreRole){ return item->data(Genres); } if(role == Qt::ForegroundRole){ if(col == TotalSize){ qint64 s = item->data(TotalSize).toLongLong(); QColor retval = Qt::green; if(s > DVDSIZE){ retval = Qt::cyan; } if(s > DVDSIZE){ retval = Qt::red; } return retval; } if(col == Quality){ int q = item->data(Quality).toInt(); QColor retval = Qt::green; if(q < 8){ retval = Qt::red; } return retval; } } if(role == Qt::TextAlignmentRole){ if(col == TotalSize || col == Quality){ int retval = Qt::AlignRight | Qt::AlignVCenter; return retval; } } if(role == Qt::DecorationRole){ if(index.column() == 0){ if(item->parent() == root()){ return QVariant(); }else{ return decorationIcon(); } } return QVariant(); } return SmTreeModel::data(index, role); } bool ArchiveBrowserModel::setData(const QModelIndex &index, const QVariant &value, int role){ if(role == SelectedRole){ SmTreeItem *item = itemAt(index); item->setData(Selected, value); emit dataChanged(index, index); return true; } return SmTreeModel::setData(index, value, role); } void ArchiveBrowserModel::updateDVDNo(const QList fileNos) { if(fileNos.isEmpty()){ return; } int maxdvd = 0; QSqlQuery maxDvdQ = QSqlQuery("SELECT max(idvd) FROM files", mDb); while(maxDvdQ.next()){ maxdvd = maxDvdQ.value(0).toInt(); } ++maxdvd; QSqlQuery updateFile(mDb); updateFile.prepare("UPDATE files SET idvd = :dvd WHERE ifiles_id = :id"); for(int i : fileNos){ updateFile.bindValue(":id", i); updateFile.bindValue(":dvd", maxdvd); updateFile.exec(); } } int ArchiveBrowserModel::nextDVDNo() const { int maxdvd = 0; QSqlQuery maxDvdQ = QSqlQuery("SELECT max(idvd) FROM files", mDb); while(maxDvdQ.next()){ maxdvd = maxDvdQ.value(0).toInt(); } ++maxdvd; return maxdvd; } QModelIndexList ArchiveBrowserModel::children(const QModelIndex &idx){ if(!idx.isValid()){ return QModelIndexList(); } QModelIndexList retval; SmTreeItem *item = itemAt(idx); for(int i = 0; i < item->childCount(); ++i){ QModelIndex retIdx = createIndex(i, 0, item->child(i)); retval << retIdx; } return retval; } void ArchiveBrowserModel::refresh() { populate(); } Qt::ItemFlags ArchiveBrowserModel::flags(const QModelIndex &index) const{ SmTreeItem *item = itemAt(index); int nt = item->data(NodeType).toInt(); if(nt == FileNode){ return Qt::ItemIsEnabled; } return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } void ArchiveBrowserModel::populate(){ SmTreeItem *rootItem = new SmTreeItem(mNumFields); mAvailableQualities.clear(); QSqlQuery localFilesQ(mDb); localFilesQ.prepare("SELECT tfilename, bisize, sifiletype, siquality, ifiles_id, cmd5sum FROM files WHERE iseriespart_id = :sid ORDER BY sifiletype"); QSqlQuery localGenresQ(mDb); localGenresQ.prepare("SELECT seriesparts_genremap.igenres_id, genres.tgenrename FROM seriesparts_genremap, genres WHERE iseriesparts_id = :sid AND seriesparts_genremap.igenres_id = genres.igenres_id ORDER BY genres.tgenrename ASC"); QSqlQuery localQ = QSqlQuery("SELECT DISTINCT(series.iseries_id), tseries_name, seriesparts.iseriespart, seriesparts.tsubtitle, seriesparts.iseriesparts_id FROM series LEFT JOIN seriesparts ON series.iseries_id = seriesparts.iseries_id LEFT JOIN files ON seriesparts.iseriesparts_id = files.iseriespart_id WHERE files.sifiletype = 1 AND files.idvd < 1 AND seriesparts.bfavorite = false ORDER BY tseries_name ASC", mDb); while(localQ.next()){ QList serPartData; QString name; if(localQ.value(2).toInt() > 0){ name = QString("%1 %2").arg(localQ.value(1).toString(), QString::number(localQ.value(2).toInt())); }else{ name = QString("%1 - %2").arg(localQ.value(1).toString(), localQ.value(3).toString()); } serPartData << QChar(0x26A4) << name << localQ.value(4) << SeriesPartNode << QVariant() << QVariant() << QVariant() << QString() << false << QVariant(); SmTreeItem *seriesItem = new SmTreeItem(serPartData, rootItem); rootItem->appendChild(seriesItem); localFilesQ.bindValue(":sid", localQ.value(4)); localFilesQ.exec(); qint64 totalSize = 0; int quality = -1; QStringList genres; while(localFilesQ.next()){ QList fileData; fileData << QVariant() << localFilesQ.value(0) << localFilesQ.value(4) << FileNode << localFilesQ.value(1) << localFilesQ.value(3) << localFilesQ.value(2) << Helper::createArchivePath(localFilesQ.value(0).toString(), localFilesQ.value(5).toString()) << false << QVariant(); totalSize += localFilesQ.value(1).toDouble(); if(localFilesQ.value(2) == FT_MOVIE){ int q = localFilesQ.value(3).toInt(); quality = q; if(!mAvailableQualities.contains(q)){ mAvailableQualities << q; } } SmTreeItem *fileItem = new SmTreeItem(fileData, seriesItem); seriesItem->appendChild(fileItem); } localGenresQ.bindValue(":sid", localQ.value(4)); localGenresQ.exec(); while(localGenresQ.next()){ QString genre = localGenresQ.value(1).toString(); genres << genre; if(!mAvailableGenres.contains(genre)){ mAvailableGenres << genre; } } seriesItem->setData(Quality, quality); seriesItem->setData(TotalSize, totalSize); seriesItem->setData(Genres, QVariant(genres)); } setRoot(rootItem); emit populated(); } void ArchiveBrowserModel::readConfig() { setDecorationIcon(SmGlobals::instance()->iconFor("file")); } //ArchiveBrowserModelProxy ArchiveBrowserModelProxy::ArchiveBrowserModelProxy(QObject *parent) : QSortFilterProxyModel(parent), mQuality(-1), mSizeFilter(false) {} void ArchiveBrowserModelProxy::setQualityFilter(QString quality){ if(quality == tr("(none)")){ mQuality = -1; }else{ mQuality = quality.toInt(); } invalidateFilter(); } void ArchiveBrowserModelProxy::readSettings(){ QSettings s; mGenreFilters = s.value("archivebrowser/includedgenres").toStringList(); mExcludedGenreFilters = s.value("archivebrowser/archivebrowser/excludedgenres").toStringList(); } void ArchiveBrowserModelProxy::writeSettings(){ QSettings s; s.setValue("archivebrowser/includedgenres", mGenreFilters); s.setValue("archivebrowser/archivebrowser/excludedgenres", mExcludedGenreFilters); } void ArchiveBrowserModelProxy::toggleGenre(QAction *a){ QString text = a->text(); if(a->isChecked()){ mGenreFilters << text; }else{ mGenreFilters.removeAll(text); } invalidateFilter(); } void ArchiveBrowserModelProxy::toggleExcludedGenre(QAction *a){ QString text = a->text(); if(a->isChecked()){ mExcludedGenreFilters << text; }else{ mExcludedGenreFilters.removeAll(text); } invalidateFilter(); } void ArchiveBrowserModelProxy::setSizeFilter(int activate){ mSizeFilter = activate; invalidateFilter(); } void ArchiveBrowserModelProxy::setBytesRemaining(qint64 bytes){ mBytesRemaining = bytes; invalidateFilter(); } bool ArchiveBrowserModelProxy::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { if(mQuality == -1 && !mSizeFilter && mGenreFilters.isEmpty() && mExcludedGenreFilters.isEmpty()){ return true; } QModelIndex selIdx = sourceModel()->index(sourceRow, ArchiveBrowserModel::Selected, sourceParent); if(selIdx.data().toBool()){ return true; } QModelIndex nodeIdx = sourceModel()->index(sourceRow, ArchiveBrowserModel::NodeType, sourceParent); int nodeType = nodeIdx.data().toInt(); if(nodeType == ArchiveBrowserModel::FileNode){ return true; } QModelIndex genreIdx = sourceModel()->index(sourceRow, ArchiveBrowserModel::Genres, sourceParent); QStringList genres = genreIdx.data().toStringList(); if(!mExcludedGenreFilters.isEmpty()){ for(const QString &exg : std::as_const(mExcludedGenreFilters)){ if(genres.contains(exg)){ return false; } } } bool retval = true; if(!mGenreFilters.isEmpty()){ for(const QString &fg : std::as_const(mGenreFilters)){ if(!genres.contains(fg)){ retval = false; } } } QModelIndex qualIdx = sourceModel()->index(sourceRow, ArchiveBrowserModel::Quality, sourceParent); int quality = qualIdx.data().toInt(); QModelIndex sizeIdx = sourceModel()->index(sourceRow, ArchiveBrowserModel::TotalSize, sourceParent); qint64 size = sizeIdx.data().toLongLong(); if(retval){ if(quality < mQuality){ retval = false; } if(mSizeFilter){ if(size > mBytesRemaining){ retval = false; } } } return retval; }