LCOV - code coverage report
Current view: top level - src/parser - NewsParser.cpp (source / functions) Coverage Total Hit
Test: coverage.info.cleaned Lines: 52.8 % 106 56
Test Date: 2026-01-27 22:31:25 Functions: 61.5 % 13 8

            Line data    Source code
       1              : #include "NewsParser.h"
       2              : 
       3              : #include <QDebug>
       4              : #include <QFile>
       5              : #include <QFileInfo>
       6              : 
       7              : #include "../utilities/ErrorHandling.h"
       8              : #include "ParserXMLWorker.h"
       9              : 
      10           86 : NewsParser::NewsParser(QObject *parent) :
      11              :     ParserInterface(parent),
      12           86 :     feed(nullptr), result(OK), networkError(QNetworkReply::NetworkError::NoError),
      13          172 :     currentReply(nullptr), redirectReply(nullptr),
      14           86 :     fromCache(false), noParseIfCached(false)
      15              : {
      16              :     // Connex0r teh siganls.
      17           86 :     connect(&manager, &FangNetworkAccessManager::finished,
      18           86 :             this, &NewsParser::netFinished);
      19              :     
      20              :     // Setup the worker object.
      21           86 :     ParserXMLWorker* worker = new ParserXMLWorker();
      22           86 :     worker->moveToThread(&workerThread);
      23           86 :     connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
      24           86 :     connect(this, &NewsParser::triggerDocStart, worker, &ParserXMLWorker::documentStart);
      25           86 :     connect(this, &NewsParser::triggerDocEnd, worker, &ParserXMLWorker::documentEnd);
      26           86 :     connect(this, &NewsParser::triggerAddXML, worker, &ParserXMLWorker::addXML);
      27           86 :     connect(worker, &ParserXMLWorker::done, this, &NewsParser::workerDone);
      28              :     
      29           86 :     workerThread.start();
      30           86 : }
      31              : 
      32          113 : NewsParser::~NewsParser()
      33              : {
      34           86 :     workerThread.quit();
      35           86 :     workerThread.wait();
      36              :     
      37           86 :     delete currentReply;
      38          113 : }
      39              : 
      40            1 : void NewsParser::parse(const QUrl& url, bool noParseIfCached)
      41              : {
      42            1 :     initParse(url);
      43              :     
      44            1 :     this->noParseIfCached = noParseIfCached;
      45              :     
      46              :     // in with the new
      47            1 :     QNetworkRequest request(url);
      48            1 :     if (currentReply) {
      49            0 :         currentReply->disconnect(this);
      50            0 :         currentReply->deleteLater();
      51              :     }
      52              :     
      53            1 :     currentReply = manager.get(request);
      54            1 :     connect(currentReply, &QNetworkReply::readyRead, this, &NewsParser::readyRead);
      55            1 :     connect(currentReply, &QNetworkReply::metaDataChanged, this, &NewsParser::metaDataChanged);
      56            1 :     connect(currentReply, &QNetworkReply::errorOccurred, this, &NewsParser::error);
      57            1 : }
      58              : 
      59              : 
      60           59 : void NewsParser::parseFile(const QString &filename)
      61              : {
      62           59 :     initParse();
      63              : 
      64           59 :     QFile file(filename);
      65              : 
      66           59 :     if (!file.exists()) {
      67            0 :         qCritical() << "NewsParser::parseFile: File does not exist:" << filename;
      68            0 :         return;
      69              :     }
      70              : 
      71           59 :     if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
      72            0 :         qCritical() << "NewsParser::parseFile: Cannot open file:" << filename;
      73            0 :         return;
      74              :     }
      75              : 
      76           59 :     QByteArray data = file.readAll();
      77           59 :     emit triggerAddXML(data);
      78           59 :     emit triggerDocEnd();
      79           59 : }
      80              : 
      81            0 : void NewsParser::error(QNetworkReply::NetworkError ne)
      82              : {
      83              :     Q_UNUSED(ne);
      84            0 :     currentReply->disconnect(this);
      85            0 :     currentReply->deleteLater();
      86            0 :     currentReply = 0;
      87              :     
      88            0 :     result = NewsParser::NETWORK_ERROR;
      89            0 :     networkError = ne;
      90            0 :     emit done();
      91            0 : }
      92              : 
      93              : 
      94            0 : void NewsParser::readyRead()
      95              : {
      96            0 :     int statusCode = currentReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
      97            0 :     if (statusCode >= 200 && statusCode < 300) {
      98            0 :         QByteArray data = currentReply->readAll();
      99            0 :         emit triggerAddXML(data);
     100            0 :     }
     101            0 : }
     102              : 
     103            0 : void NewsParser::metaDataChanged()
     104              : {
     105            0 :     QUrl redirectionTarget = currentReply->attribute(
     106            0 :                 QNetworkRequest::RedirectionTargetAttribute).toUrl();
     107              :     
     108              :     // TODO: prevent endless loooooping!!!
     109            0 :     if (redirectionTarget.isValid()) {
     110            0 :         qDebug() << "Redirect: " << redirectionTarget.toString();
     111            0 :         redirectReply = currentReply;
     112            0 :         parse(redirectionTarget, noParseIfCached);
     113              :     }
     114              :     
     115            0 :     if (currentReply->attribute(
     116            0 :                 QNetworkRequest::SourceIsFromCacheAttribute).isValid()) {
     117            0 :         if (currentReply->attribute(
     118            0 :                     QNetworkRequest::SourceIsFromCacheAttribute).toBool()) {
     119            0 :             if (noParseIfCached) {
     120              :                 // Early exit for cache.
     121            0 :                 currentReply->disconnect(this);
     122            0 :                 currentReply->deleteLater();
     123            0 :                 currentReply = 0;
     124              :                 
     125            0 :                 result = NewsParser::OK;
     126            0 :                 emit done();
     127              :                 
     128            0 :                 return;
     129              :             }
     130              :         }
     131              :     }
     132            0 : }
     133              : 
     134            0 : NewsParser::ParseResult NewsParser::getResult()
     135              : {
     136            0 :     return result;
     137              : }
     138              : 
     139           59 : RawFeed* NewsParser::getFeed()
     140              : {
     141           59 :     return result == NewsParser::OK ? feed : nullptr;
     142              : }
     143              : 
     144            0 : void NewsParser::netFinished(QNetworkReply *reply)
     145              : {
     146            0 :     if (redirectReply == reply) {
     147            0 :         return; // This was the previous redirect.
     148              :     }
     149              :     
     150              :     // Remember this URL.
     151            0 :     finalFeedURL = reply->url();
     152              :     
     153              :     // Tell the worker that we're done.
     154            0 :     emit triggerDocEnd();
     155              : }
     156              : 
     157           59 : void NewsParser::workerDone(RawFeed* rawFeed)
     158              : {
     159           59 :     if (result != NewsParser::IN_PROGRESS) {
     160              :         // Already emitted a finished signal.  Nothing to dooooo.
     161            0 :         return;
     162              :     }
     163              :     
     164           59 :     if (rawFeed) {
     165           59 :         feed = rawFeed;
     166              : 
     167              :         // This means we saw... something.  Do a sanity check here to
     168              :         // make sure what we found was an actual feed.
     169           59 :         if (feed->items.size() > 0 || feed->title != "") {
     170           59 :             feed->url = finalFeedURL;
     171              :             
     172           59 :             result = NewsParser::OK;
     173           59 :             emit done();
     174              :             
     175           59 :             return; // Early exit on SUCCESS!! (yay)
     176              :         }
     177              :     }
     178              :     
     179              :     // What we found must not have been an RSS/Atom feed.
     180            0 :     result = NewsParser::PARSE_ERROR;
     181            0 :     emit done();
     182              : }
     183              : 
     184           60 : void NewsParser::initParse(const QUrl& url)
     185              : {
     186           60 :     result = NewsParser::IN_PROGRESS;
     187           60 :     networkError = QNetworkReply::NetworkError::NoError;
     188           60 :     finalFeedURL = url;
     189           60 :     emit triggerDocStart();
     190           60 : }
        

Generated by: LCOV version 2.0-1