/* 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 "seriestreemodel.h" #include "smtreeitem.h" #include "helper.h" SeriesTreeModel::SeriesTreeModel(QStringList &headers, QObject *parent) : SmTreeModel(headers, parent), mRowFilter(All) { mDb = QSqlDatabase::database("treedb"); mSeriesPartsQuery = new QSqlQuery(mDb); mSeriesPartsQuery->prepare("SELECT iseriesparts_id, iseriespart, bfavorite, tsubtitle FROM seriesparts WHERE iseries_id = :id ORDER BY iseriespart"); mUpdateSeriesIdQuery = new QSqlQuery(mDb); mUpdateSeriesIdQuery->prepare("UPDATE seriesparts SET iseries_id = :newid WHERE iseries_id = :oldid"); mUpdateSeriesNameQuery = new QSqlQuery(mDb); mUpdateSeriesNameQuery->prepare("UPDATE series SET tseries_name = :newname WHERE iseries_id = :id"); mDeleteSeriesQuery = new QSqlQuery(mDb); mDeleteSeriesQuery->prepare("DELETE FROM series where iseries_id = :id"); mDeleteSeriesPartQuery = new QSqlQuery(mDb); mDeleteSeriesPartQuery->prepare("DELETE FROM seriesparts WHERE iseriesparts_id = :id"); mSeriesInsertQuery = new QSqlQuery(mDb); mSeriesInsertQuery->prepare("INSERT INTO series(tseries_name) VALUES(:name)"); mSeriesFilesQuery = new QSqlQuery(mDb); mSeriesFilesQuery->prepare("SELECT files.tfilename, files.cmd5sum FROM series, seriesparts, files WHERE series.iseries_id = :id AND series.iseries_id = seriesparts.iseries_id AND seriesparts.iseriesparts_id = files.iseriespart_id"); mSeriesPartFilesQuery = new QSqlQuery(mDb); mSeriesPartFilesQuery->prepare("SELECT files.tfilename, files.cmd5sum FROM seriesparts, files WHERE seriesparts.iseriesparts_id = :id AND seriesparts.iseriesparts_id = files.iseriespart_id"); mSeriesPartInsertQuery = new QSqlQuery(mDb); mSeriesPartInsertQuery->prepare("INSERT INTO seriesparts(iseriespart, iseries_id, tsubtitle) VALUES(:part, :id, :subtitle)"); mSortedMovieListQuery = new QSqlQuery(mDb); mSortedMovieListQuery->prepare("SELECT files.tfilename, files.cmd5sum FROM series, seriesparts, files WHERE series.iseries_id = :id AND seriesparts.iseries_id = series.iseries_id AND seriesparts.iseriesparts_id = files.iseriespart_id AND files.sifiletype = 1 ORDER BY seriesparts.iseriespart, files.sifileno"); mNextDvdNoQuery = new QSqlQuery(mDb); mNextDvdNoQuery->prepare("SELECT MAX(idvd) FROM files"); mGenreFilterQuery = new QSqlQuery(mDb); mGenreFilterQuery->prepare("SELECT DISTINCT(series.iseries_id), series.tseries_name FROM series, seriesparts, seriesparts_genremap, genres where tgenrename LIKE :pat AND genres.igenres_id = seriesparts_genremap.igenres_id AND seriesparts_genremap.iseriesparts_id = seriesparts.iseriesparts_id AND seriesparts.iseries_id = series.iseries_id"); mFavoriteSeriesIdQuery = new QSqlQuery(mDb); mFavoriteSeriesIdQuery->prepare("SELECT DISTINCT(series.iseries_id), series.tseries_name FROM series, seriesparts WHERE seriesparts.bfavorite = true and seriesparts.iseries_id = series.iseries_id"); mFavoriteSeriesPartsQuery = new QSqlQuery(mDb); mFavoriteSeriesPartsQuery->prepare("SELECT iseriesparts_id, iseriespart, tsubtitle FROM seriesparts WHERE iseries_id = :id AND bfavorite = true"); mUpdateGenericTemplate = QString("UPDATE seriesparts SET %1 = :value WHERE iseriesparts_id = :id"); mIsLocalQuery = new QSqlQuery(mDb); mIsLocalQuery->prepare("SELECT COUNT(*) FROM files WHERE iseriespart_id = :id AND sifiletype = 1 AND idvd = -1"); mUpdateGenericMap.insert(Favorite, "bfavorite"); mUpdateGenericMap.insert(Subtitle, "tsubtitle"); mUpdateGenericMap.insert(SeriesPart, "iseriespart"); populate(); } SeriesTreeModel::~SeriesTreeModel(){ delete mSeriesPartsQuery; delete mUpdateSeriesIdQuery; delete mUpdateSeriesNameQuery; delete mDeleteSeriesQuery; delete mDeleteSeriesPartQuery; delete mSeriesInsertQuery; delete mSeriesFilesQuery; delete mSeriesPartFilesQuery; delete mSeriesPartInsertQuery; delete mSortedMovieListQuery; delete mNextDvdNoQuery; delete mGenreFilterQuery; delete mFavoriteSeriesIdQuery; delete mFavoriteSeriesPartsQuery; mDb = QSqlDatabase(); } Qt::ItemFlags SeriesTreeModel::flags(const QModelIndex &index) const{ if(!index.isValid()){ return 0; } Qt::ItemFlags retval = Qt::ItemIsEnabled | Qt::ItemIsSelectable; if(index.data(TypeRole).toInt() == Series || index.data(TypeRole).toInt() == NewSeries){ return retval | Qt::ItemIsEditable; } return retval; } QVariant SeriesTreeModel::data(const QModelIndex &index, int role) const{ if(!index.isValid()){ return QVariant(); } SmTreeItem *item = static_cast(index.internalPointer()); if(role == Qt::DisplayRole){ if(index.column() == Name){ int type = index.data(TypeRole).toInt(); if(type == Series || type == NewSeries){ return item->data(Name); }else if(type == Part){ QString retval = item->data(Name).toString(); if(item->data(SeriesPart).toInt() > 0){ retval = QString("%1 %2").arg(retval).arg(item->data(SeriesPart).toInt()); } QString subtitle = item->data(Subtitle).toString(); if(!subtitle.isEmpty()){ retval = QString("%1 - %2").arg(retval).arg(subtitle); } return retval; }else{ return QVariant(); } }else{ return item->data(index.column()); } } if(role == Qt::DecorationRole){ if(index.column() == 0){ return decorationIcon(); } } if(role == Qt::ForegroundRole){ if(item->data(Favorite).toBool()){ return mFavoriteColor; } } if(role == Qt::EditRole){ if(index.data(TypeRole) == Series || index.data(TypeRole) == NewSeries){ if(index.column() == 0){ return item->data(Name); } } } if(role == NameRole){ return item->data(Name); } if(role == SeriesIdRole){ return item->data(SeriesId); } if(role == SeriesPartIdRole){ return item->data(SeriesPartId); } if(role == SeriesPartRole){ return item->data(SeriesPart); } if(role == TypeRole){ return item->data(Type); } if(role == FavoriteRole){ return item->data(Favorite); } if(role == SubtitleRole){ return item->data(Subtitle); } if(role == IsLocalRole){ return item->data(IsLocal); } return QVariant(); } bool SeriesTreeModel::setData(const QModelIndex &index, const QVariant &value, int role){ if(!index.isValid()){ return false; } if(role == Qt::EditRole){ if(index.column() == Name){ if(index.data(TypeRole).toInt() == Series){ //change of series name if(index.column() == Name){ QModelIndex newSeries = findValue(value, index.parent(), index.column()); if(newSeries == index){ //no change made, exit gracefully return false; } if(newSeries != QModelIndex()){ //series already exists, merge return mergeSeries(index, newSeries); }else{ //rename series return renameSeries(index, value); } } } }else if(index.column() == IsLocal){ setLocal(index, value); }else if(index.data(TypeRole).toInt() == NewSeries){ return setNewSeries(index, value); }else{ return updateGeneric(index, value); } } return false; } QList SeriesTreeModel::childrenColumnList(const QModelIndex &parent, int column) const{ if(!parent.isValid()){ return QList(); } SmTreeItem *item = static_cast(parent.internalPointer()); QList retval; for(int i = 0; i < item->childCount(); ++i){ SmTreeItem *child = item->child(i); retval << child->data(column); } return retval; } QModelIndex SeriesTreeModel::findValue(const QVariant &value, const QModelIndex &parent, int searchColumn, int indexColumn) const{ SmTreeItem *parentItem = root(); if(parent != QModelIndex()){ parentItem = static_cast(parent.internalPointer()); } for(int i = 0; i < parentItem->childCount(); ++i){ SmTreeItem *childItem = parentItem->child(i); if(value == childItem->data(searchColumn)){ if(indexColumn == -1){ return createIndex(i, searchColumn, childItem); }else{ return createIndex(i, indexColumn, childItem); } } } return QModelIndex(); } QFileInfoList SeriesTreeModel::findFiles(const QModelIndex &where) const{ int type = where.data(TypeRole).toInt(); QFileInfoList retval; QSqlQuery *query = 0; if(type == Series){ query = mSeriesFilesQuery; query->bindValue(":id", where.data(SeriesIdRole)); }else if(type == Part){ query = mSeriesPartFilesQuery; query->bindValue(":id", where.data(SeriesPartIdRole)); } if(query){ if(query->exec()){ while(query->next()){ QString path = Helper::createArchivePath(query->value(0).toString(), query->value(1).toString()); retval << QFileInfo(path); } } } return retval; } QFileInfoList SeriesTreeModel::findMovies(const QModelIndexList &from) const{ if(from.isEmpty()){ return QFileInfoList(); } QFileInfoList retval; foreach(QModelIndex idx, from){ QFileInfoList files = findFiles(idx); foreach(QFileInfo fi, files){ QString mime = Helper::mimeType(fi.absoluteFilePath()); if(mime.startsWith("video")){ if(!retval.contains(fi)){ retval << fi; } } } } return retval; } QFileInfoList SeriesTreeModel::findSortedMovies(const QModelIndex &from) const{ if(!from.isValid()){ return QFileInfoList(); } QFileInfoList retval; int seriesId = from.data(SeriesIdRole).toInt(); mSortedMovieListQuery->bindValue(":id", seriesId); if(mSortedMovieListQuery->exec()){ while(mSortedMovieListQuery->next()){ QString path = Helper::createArchivePath(mSortedMovieListQuery->value(0).toString(), mSortedMovieListQuery->value(1).toString()); retval << QFileInfo(path); } } return retval; } bool SeriesTreeModel::hasLocals(int sPartId) const { bool retval = false; mIsLocalQuery->bindValue(":id", sPartId); mIsLocalQuery->exec(); while(mIsLocalQuery->next()){ retval = mIsLocalQuery->value(0).toBool(); } return retval; } int SeriesTreeModel::seriesIdByPartId(int partId){ if(mSeriesPartSeriesMap.contains(partId)){ return mSeriesPartSeriesMap.value(partId); } return -1; } int SeriesTreeModel::findNextDvdNo() const{ int dvdno = 0; mNextDvdNoQuery->exec(); while(mNextDvdNoQuery->next()){ dvdno = mNextDvdNoQuery->value(0).toInt(); } return ++dvdno; } bool SeriesTreeModel::deleteFromSeries(const QModelIndex &what){ int nodeType = what.data(TypeRole).toInt(); QSqlQuery *query = 0; if(nodeType == Series || nodeType == NewSeries){ query = mDeleteSeriesQuery; query->bindValue(":id", what.data(SeriesIdRole)); }else if(nodeType == Part){ query = mDeleteSeriesPartQuery; query->bindValue(":id", what.data(SeriesPartIdRole)); } if(query){ QFileInfoList files = findFiles(what); if(query->exec()){ foreach(QFileInfo fi, files){ QFile::remove(fi.absoluteFilePath()); } removeRows(what.row(), 1, what.parent()); return true; } } return false; } bool SeriesTreeModel::addSeries(const QVariant &seriesName, const QModelIndex &parent){ const QString name = seriesName.toString().toLower().trimmed(); if(name.isEmpty()){ return false; } mDb.transaction(); mSeriesInsertQuery->bindValue(":name", name); if(mSeriesInsertQuery->exec()){ QSqlQuery lastId("SELECT currval('series_iseries_id__seq')", mDb); if(lastId.next()){ int id = lastId.value(0).toInt(); QList seriesData; seriesData << name << id << QVariant() << QVariant() << Series << false << QVariant() << QVariant(); if(addRow(seriesData, parent)){ mDb.commit(); return true; } } } mDb.rollback(); return false; } bool SeriesTreeModel::addSeriesPart(int seriesPart, const QModelIndex &parent, const QString &subTitle){ if(!parent.isValid() || parent.data(TypeRole) != Series){ return false; } int seriesId = parent.data(SeriesIdRole).toInt(); mDb.transaction(); if(seriesPart > 0){ mSeriesPartInsertQuery->bindValue(":part", seriesPart); }else{ QSqlQuery nextNegValQuery("SELECT nextval('seriesparts_iseriespart__seq')", mDb); if(nextNegValQuery.next()){ seriesPart = nextNegValQuery.value(0).toInt(); mSeriesPartInsertQuery->bindValue(":part", seriesPart); } } mSeriesPartInsertQuery->bindValue(":id", seriesId); mSeriesPartInsertQuery->bindValue(":subtitle", subTitle.toLower()); if(mSeriesPartInsertQuery->exec()){ QSqlQuery lastId("SELECT currval('seriesparts_seriesparts_id__seq')", mDb); if(lastId.next()){ int id = lastId.value(0).toInt(); QList partData; partData << parent.data(NameRole) << seriesId << id << seriesPart << Part << false << subTitle << true; if(addRow(partData, parent)){ mDb.commit(); mSeriesPartSeriesMap.insert(id, seriesId); return true; } } } mDb.rollback(); return false; } void SeriesTreeModel::clearFilter(){ populate(); } void SeriesTreeModel::setMappingFilter(const QString &filter, const QString &table){ QString pattern = QString("%%1%").arg(filter); QString tableIdTemplate = QString("SELECT i%1s_id FROM %1s WHERE t%1name LIKE :pat").arg(table); QSqlQuery tableIdQuery(mDb); tableIdQuery.prepare(tableIdTemplate); tableIdQuery.bindValue(":pat", pattern); if(tableIdQuery.exec()){ mSeriesPartSeriesMap.clear(); QStringList ids; SmTreeItem *rootItem = new SmTreeItem(NumFields); while(tableIdQuery.next()){ ids << QString::number(tableIdQuery.value(0).toInt()); } if(ids.isEmpty()){ return; } QString seriesPartsTemplate("SELECT DISTINCT(seriesparts.iseriesparts_id), seriesparts.iseriespart, seriesparts.bfavorite, seriesparts.tsubtitle FROM seriesparts, seriesparts_%1map WHERE seriesparts.iseries_id = :id AND seriesparts_%1map.iseriesparts_id = seriesparts.iseriesparts_id AND seriesparts_%1map.i%1s_id IN (%2) ORDER BY iseriespart"); QString seriesIdTemplate = QString("SELECT DISTINCT(series.iseries_id), series.tseries_name FROM series, seriesparts, seriesparts_%1map, %1s WHERE %1s.i%1s_id IN (%2) AND %1s.i%1s_id = seriesparts_%1map.i%1s_id AND seriesparts_%1map.iseriesparts_id = seriesparts.iseriesparts_id AND seriesparts.iseries_id = series.iseries_id ORDER BY series.tseries_name").arg(table).arg(ids.join(",")); QSqlQuery seriesIdQuery(seriesIdTemplate, mDb); while(seriesIdQuery.next()){ QList seriesData; seriesData << seriesIdQuery.value(1) << seriesIdQuery.value(0) << QVariant() << QVariant() << Series << false << QVariant() << QVariant(); SmTreeItem *seriesItem = new SmTreeItem(seriesData, rootItem); rootItem->appendChild(seriesItem); QString partsQueryString = seriesPartsTemplate.arg(table).arg(ids.join(",")); QSqlQuery partsQuery(mDb); partsQuery.prepare(partsQueryString); partsQuery.bindValue(":id", seriesIdQuery.value(0)); partsQuery.exec(); while(partsQuery.next()){ QList partData; partData << seriesData.at(Name) << seriesData.at(SeriesId) << partsQuery.value(0) << partsQuery.value(1) << Part << partsQuery.value(2) << partsQuery.value(3); partData << hasLocals(partsQuery.value(0).toInt()); SmTreeItem *partItem = new SmTreeItem(partData, seriesItem); seriesItem->appendChild(partItem); mSeriesPartSeriesMap.insert(partsQuery.value(0).toInt(), seriesData.at(1).toInt()); } } setRoot(rootItem); } } void SeriesTreeModel::setFileFilter(const QString &filter, const QString &column, int queryType){ QSqlQuery seriesIdQuery(mDb); QString partsQueryTemplate; QString op("="); QVariant value = filter; if(queryType == TextQuery){ QString idQueryTemplate = QString("SELECT DISTINCT(series.iseries_id), series.tseries_name FROM series, seriesparts, files WHERE files.%1 LIKE :value AND files.iseriespart_id = seriesparts.iseriesparts_id AND seriesparts.iseries_id = series.iseries_id ORDER BY series.tseries_name").arg(column); seriesIdQuery.prepare(idQueryTemplate); value = QString("%%1%").arg(filter); seriesIdQuery.bindValue(":value", value); partsQueryTemplate = QString("SELECT DISTINCT(seriesparts.iseriesparts_id), seriesparts.iseriespart, seriesparts.bfavorite, seriesparts.tsubtitle FROM seriesparts, series, files WHERE series.iseries_id = :id AND series.iseries_id = seriesparts.iseries_id AND seriesparts.iseriesparts_id = files.iseriespart_id AND files.%1 LIKE :value"); }else if(queryType == NumericQuery){ QRegExp valRe("([<>=]?)\\s*(\\d+)\\s*(\\w*)"); (void)valRe.indexIn(value.toString()); QStringList capText = valRe.capturedTexts(); op = capText.at(1).isEmpty() ? op : capText.at(1); value = Helper::bytesFromUnit(capText.at(2), capText.at(3)); QString idQueryTemplate = QString("SELECT DISTINCT(series.iseries_id), series.tseries_name FROM series, seriesparts, files WHERE files.%1 %2 :value AND files.iseriespart_id = seriesparts.iseriesparts_id AND seriesparts.iseries_id = series.iseries_id ORDER BY series.tseries_name").arg(column).arg(op); seriesIdQuery.prepare(idQueryTemplate); seriesIdQuery.bindValue(":value", value); partsQueryTemplate = QString("SELECT DISTINCT(seriesparts.iseriesparts_id), seriesparts.iseriespart, seriesparts.bfavorite, seriesparts.tsubtitle FROM seriesparts, series, files WHERE series.iseries_id = :id AND series.iseries_id = seriesparts.iseries_id AND seriesparts.iseriesparts_id = files.iseriespart_id AND files.%1 %2 :value"); }else{ return; } if(seriesIdQuery.exec()){ mSeriesPartSeriesMap.clear(); SmTreeItem *rootItem = new SmTreeItem(NumFields); while(seriesIdQuery.next()){ QList seriesData; seriesData << seriesIdQuery.value(1) << seriesIdQuery.value(0) << QVariant() << QVariant() << Series << false << QVariant(); SmTreeItem *seriesItem = new SmTreeItem(seriesData, rootItem); rootItem->appendChild(seriesItem); QString partsQueryString; if(queryType == TextQuery){ partsQueryString = partsQueryTemplate.arg(column); value = QString("%%1%").arg(value.toString()); }else{ partsQueryString = partsQueryTemplate.arg(column).arg(op); } QSqlQuery partsQuery(mDb); partsQuery.prepare(partsQueryString); partsQuery.bindValue(":id", seriesIdQuery.value(0)); partsQuery.bindValue(":value", value); if(partsQuery.exec()){ while(partsQuery.next()){ QList partData; partData << seriesData.at(Name) << seriesData.at(SeriesId) << partsQuery.value(0) << partsQuery.value(1) << Part << partsQuery.value(2) << partsQuery.value(3); partData << hasLocals(partsQuery.value(0).toInt()); SmTreeItem *partItem = new SmTreeItem(partData, seriesItem); seriesItem->appendChild(partItem); mSeriesPartSeriesMap.insert(partsQuery.value(0).toInt(), seriesData.at(1).toInt()); } } } setRoot(rootItem); } } void SeriesTreeModel::setFavoriteFilter(){ if(mFavoriteSeriesIdQuery->exec()){ mSeriesPartSeriesMap.clear(); SmTreeItem *rootItem = new SmTreeItem(NumFields); while(mFavoriteSeriesIdQuery->next()){ QList seriesData; seriesData << mFavoriteSeriesIdQuery->value(1) << mFavoriteSeriesIdQuery->value(0) << QVariant() << QVariant() << Series << false << QVariant(); SmTreeItem *seriesItem = new SmTreeItem(seriesData, rootItem); rootItem->appendChild(seriesItem); mFavoriteSeriesPartsQuery->bindValue(":id", seriesData.at(1)); if(mFavoriteSeriesPartsQuery->exec()){ while(mFavoriteSeriesPartsQuery->next()){ QList partData; partData << seriesData.at(Name) << seriesData.at(SeriesId) << mFavoriteSeriesPartsQuery->value(0) << mFavoriteSeriesPartsQuery->value(1) << Part << true << mFavoriteSeriesPartsQuery->value(2); partData << hasLocals(mFavoriteSeriesPartsQuery->value(0).toInt()); SmTreeItem *partItem = new SmTreeItem(partData, seriesItem); seriesItem->appendChild(partItem); mSeriesPartSeriesMap.insert(mFavoriteSeriesPartsQuery->value(0).toInt(), seriesData.at(1).toInt()); } } } setRoot(rootItem); } } void SeriesTreeModel::readSettings(){ QSettings s; QVariant fc = s.value("ui/favoritecolor"); mFavoriteColor = fc.value(); conditionalUpdate(index(0, 0, QModelIndex()), Favorite, true); } void SeriesTreeModel::conditionalUpdate(const QModelIndex &parent, int field, const QVariant &value){ SmTreeItem *item = static_cast(parent.internalPointer()); if(item->childCount() > 0){ //series for(int i = 0; i < item->childCount(); ++i){ QModelIndex newParent = parent.child(i, field); if(newParent.isValid()){ conditionalUpdate(newParent, field, value); } } }else{ //seriespart if(item->data(field) == value){ QModelIndex start = index(parent.row(), 0, parent.parent()); emit dataChanged(start, parent); } } } void SeriesTreeModel::populate(){ QSqlQuery seriesQuery = QSqlQuery("SELECT iseries_id, tseries_name FROM series ORDER BY tseries_name", mDb); mSeriesPartSeriesMap.clear(); SmTreeItem *rootItem = new SmTreeItem(NumFields); while(seriesQuery.next()){ QList seriesData; seriesData << seriesQuery.value(1) << seriesQuery.value(0) << QVariant() << QVariant() << Series << false << QVariant() << QVariant(); SmTreeItem *seriesItem = new SmTreeItem(seriesData, rootItem); rootItem->appendChild(seriesItem); mSeriesPartsQuery->bindValue(":id", seriesData.at(1)); mSeriesPartsQuery->exec(); while(mSeriesPartsQuery->next()){ QList partData; partData << seriesData.at(Name) << seriesData.at(SeriesId) << mSeriesPartsQuery->value(0) << mSeriesPartsQuery->value(1) << Part << mSeriesPartsQuery->value(2) << mSeriesPartsQuery->value(3); partData << hasLocals(mSeriesPartsQuery->value(0).toInt()); SmTreeItem *partItem = new SmTreeItem(partData, seriesItem); seriesItem->appendChild(partItem); mSeriesPartSeriesMap.insert(mSeriesPartsQuery->value(0).toInt(), seriesData.at(1).toInt()); } } setRoot(rootItem); } bool SeriesTreeModel::mergeSeries(const QModelIndex &from, const QModelIndex &to){ //new series name already exists int oldSeriesId = from.data(SeriesIdRole).toInt(); int newSeriesId = to.data(SeriesIdRole).toInt(); mUpdateSeriesIdQuery->bindValue(":oldid", oldSeriesId); mUpdateSeriesIdQuery->bindValue(":newid", newSeriesId); if(mUpdateSeriesIdQuery->exec()){ SmTreeItem *oldParent = static_cast(from.internalPointer()); SmTreeItem *newParent = static_cast(to.internalPointer()); //reparent items to new series for(int i = oldParent->childCount() - 1; i > -1; --i){ SmTreeItem *curItem = oldParent->child(i); curItem->setParent(newParent); curItem->setData(Name, to.data(NameRole)); newParent->appendChild(curItem); oldParent->removeChild(i, false); } mDeleteSeriesQuery->bindValue(":id", oldSeriesId); if(mDeleteSeriesQuery->exec()){ //series has to be empty root()->removeChild(from.row()); } //update seriespartmap QList seriesPartIds = mSeriesPartSeriesMap.keys(oldSeriesId); foreach(int seriesPartId, seriesPartIds){ mSeriesPartSeriesMap.remove(seriesPartId); mSeriesPartSeriesMap.insert(seriesPartId, newSeriesId); } reset(); return true; } return false; } bool SeriesTreeModel::renameSeries(const QModelIndex &source, const QVariant &value){ int oldSeriesId = source.data(SeriesIdRole).toInt(); mUpdateSeriesNameQuery->bindValue(":newname", value); mUpdateSeriesNameQuery->bindValue(":id", oldSeriesId); if(mUpdateSeriesNameQuery->exec()){ SmTreeItem *curItem = static_cast(source.internalPointer()); curItem->setData(Name, value); emit dataChanged(source, source); for(int i = 0; i < curItem->childCount(); ++i){ SmTreeItem *child = curItem->child(i); child->setData(Name, value); } if(curItem->childCount()){ QModelIndex start = source.child(0, 0); QModelIndex end = source.child(curItem->childCount() - 1, 0); emit dataChanged(start, end); } emit needResort(); return true; } return false; } bool SeriesTreeModel::setNewSeries(const QModelIndex &source, const QVariant &value){ QString newName = value.toString(); if(newName.isEmpty()){ return false; } SmTreeItem *item = static_cast(source.internalPointer()); mDb.transaction(); mSeriesInsertQuery->bindValue(":name", value); if(mSeriesInsertQuery->exec()){ QSqlQuery lastId("SELECT currval('series_iseries_id__seq')", mDb); if(lastId.next()){ int newId = lastId.value(0).toInt(); item->setData(Name, value); item->setData(SeriesId, newId); item->setData(Type, Series); QModelIndex end = index(source.row(), item->childCount() - 1, source.parent()); emit dataChanged(source, end); emit needResort(); mDb.commit(); return true; } } mDb.rollback(); return false; } bool SeriesTreeModel::updateGeneric(const QModelIndex &source, const QVariant &value){ int column = source.column(); if(!mUpdateGenericMap.contains(column)){ return false; } SmTreeItem *item = static_cast(source.internalPointer()); QString table = mUpdateGenericMap.value(column); QString queryString = QString(mUpdateGenericTemplate).arg(table); mDb.transaction(); QSqlQuery query(mDb); query.prepare(queryString); query.bindValue(":id", item->data(SeriesPartId)); query.bindValue(":value", value); if(query.exec()){ item->setData(column, value); emit dataChanged(source, source); mDb.commit(); return true; } mDb.rollback(); return false; } bool SeriesTreeModel::setLocal(const QModelIndex &source, const QVariant &value){ SmTreeItem *item = static_cast(source.internalPointer()); item->setData(IsLocal, value); emit dataChanged(source, source); emit localsChanged(); return true; }