#include "atomchannel.h" #include #include #include #include "constants.h" #include "macros.h" #include "rsshit_db.h" AtomChannel::AtomChannel(QXmlStreamReader *xmlReader) { Q_ASSERT(xmlReader != nullptr); const QString titleTag{"title"}; const QString linkTag{"link"}; const QString descriptionTag{"description"}; const QString lastBuildDateTag{"lastBuildDate"}; const QString languageTag{"language"}; while (!xmlReader->atEnd() && !xmlReader->hasError()) { const auto itemNext = xmlReader->readNext(); switch (itemNext) { case QXmlStreamReader::TokenType::StartElement: { const auto name = xmlReader->name(); // qDebug() << __func__ << ": StartElement" << name; // qDebug() << __func__ << "namespaceUri:" << xmlReader->namespaceUri(); // qDebug() << __func__ << "prefix:" << xmlReader->prefix(); // qDebug() << __func__ << "qualifiedName:" << xmlReader->qualifiedName(); // const auto elementText = xmlReader->readElementText(); if (name == titleTag) title = xmlReader->readElementText(); else if (name == linkTag) link = xmlReader->readElementText(); else if (name == descriptionTag) description = xmlReader->readElementText(); else if (name == lastBuildDateTag) lastBuildDate = QDateTime::fromString(xmlReader->readElementText(), Qt::DateFormat::RFC2822Date); else if (name == languageTag) language = QLocale{xmlReader->readElementText()}.language(); else if (name == AtomChannelImage::tag) { // qDebug() << "got image tag"; image = AtomChannelImage{xmlReader}; // qDebug() << image; } else if (name == AtomItem::tag) { items << AtomItem{xmlReader}; // qDebug() << items.constLast(); // qDebug() << __func__ << "got feed item"; } else { // qDebug() << "exit" << __func__; // qDebug() << __func__ << "unknown tag:" << name; continue; } break; } case QXmlStreamReader::TokenType::EndElement: { // qDebug() << "EndElement: " << xmlReader->name(); if (xmlReader->name() == AtomChannel::xmlTag) return; } case QXmlStreamReader::TokenType::Characters: { const auto characters = xmlReader->text().toString().simplified(); if (characters.isEmpty()) break; qDebug() << "channel: characters: " << characters; break; } } } qDebug() << "exit " << __func__; } int AtomChannel::getDbId() { if (dbId != rsshit::db::IdNotFound) return dbId; const auto db = rsshit::db::open(); if (!db) return rsshit::db::IdNotFound; QSqlQuery selectQ{"select id from feeds where link=?"}; selectQ.addBindValue(link); if (!selectQ.exec()) { qWarning() << "cannot exec query" << selectQ.lastQuery() << ":" << selectQ.lastError().text() << ":" << selectQ.executedQuery(); return rsshit::db::IdNotFound; } if (!selectQ.next()) return rsshit::db::IdNotFound; const auto idVariant = selectQ.value(rsshit::db::idTag); if (!idVariant.isValid() || !idVariant.canConvert()) return rsshit::db::IdNotFound; bool ok{false}; const auto result = idVariant.toInt(&ok); if (!ok) { qWarning() << "got invalid id from db:" << idVariant; return rsshit::db::IdNotFound; } return result; } int AtomChannel::createInDb() { if (dbId != rsshit::db::IdNotFound) return dbId; const auto db = rsshit::db::open(); if (!db) return rsshit::db::IdNotFound; QSqlQuery insertQ{"insert into feeds(link, title, image_url) values(?, ?, ?)"}; insertQ.addBindValue(link); insertQ.addBindValue(title); insertQ.addBindValue(image.url); if (!insertQ.exec()) { qWarning() << "cannot exec query" << insertQ.lastQuery() << ":" << insertQ.lastError().text() << ":" << insertQ.executedQuery(); return rsshit::db::IdNotFound; } return insertQ.lastInsertId().toInt(); } // TODO: can be moved to IDbObject int AtomChannel::getOrInsertDbId() { const auto id = getDbId(); if (id != rsshit::db::IdNotFound) return id; return createInDb(); } QList AtomChannel::syncDbItems() { if (dbId == rsshit::db::IdNotFound) dbId = getOrInsertDbId(); if (dbId == rsshit::db::IdNotFound) return {}; QList result; for (auto &item : items) { auto id = item.getOrInsertDbId(this->dbId); if (id != rsshit::db::IdNotFound) result << id; } return result; } QDebug operator<<(QDebug debug, const AtomChannel &channel) { QDebugStateSaver saver{debug}; debug.nospace() << typeid(AtomChannel).name() << " {" << Qt::endl; PRINT_ATOM_FIELD(channel, title); PRINT_ATOM_FIELD(channel, link); PRINT_ATOM_FIELD(channel, description); PRINT_ATOM_FIELD(channel, lastBuildDate); PRINT_ATOM_FIELD(channel, language); debug << "\timage:\n" << channel.image << Qt::endl; debug << "\titems count:" << channel.items.size() << Qt::endl; for (const auto &item : channel.items) debug << item << Qt::endl; debug.nospace() << "}"; return debug; }