LCOV - code coverage report
Current view: top level - src/utilities - RawFeedRewriter.cpp (source / functions) Coverage Total Hit
Test: coverage.info.cleaned Lines: 77.6 % 58 45
Test Date: 2026-03-23 10:19:47 Functions: 100.0 % 8 8

            Line data    Source code
       1              : #include "RawFeedRewriter.h"
       2              : 
       3              : #include <QDebug>
       4              : #include <QtConcurrent>
       5              : 
       6              : #include "ImageCache.h"
       7              : 
       8           31 : RawFeedRewriter::RawFeedRewriter(QObject *parent, QNetworkAccessManager* networkManager) :
       9              :     FangObject(parent),
      10           31 :     newsList(nullptr),
      11           31 :     sanitizer(),
      12           31 :     imageGrabber(nullptr, networkManager)
      13              : {
      14           31 :     connect(&imageGrabber, &ImageGrabber::finished, this, &RawFeedRewriter::onImageGrabberFinished);
      15           31 :     connect(&sanitizeWatcher, &QFutureWatcher<QSet<QUrl>>::finished, this, &RawFeedRewriter::onSanitizeFinished);
      16           38 :     connect(&finalizeWatcher, &QFutureWatcher<void>::finished, this, [this]() { emit finished(); });
      17           31 : }
      18              : 
      19           31 : void RawFeedRewriter::rewrite(QList<RawNews *> *newsList)
      20              : {
      21           31 :     this->newsList = newsList;
      22              : 
      23              :     // Reset sanitizer state for new batch.
      24           31 :     sanitizer.reset();
      25              : 
      26              :     // First pass: sanitize all HTML and collect image URLs.
      27              :     // Run on a background thread to avoid blocking the UI.
      28            0 :     auto future = QtConcurrent::run([this]() -> QSet<QUrl> {
      29           31 :         QSet<QUrl> allImageURLs;
      30              : 
      31           62 :         for (RawNews* news : *this->newsList) {
      32           31 :             QSet<QUrl> imageURLs;
      33              : 
      34           31 :             if (!news->content.isEmpty()) {
      35            0 :                 news->content = sanitizer.sanitize(news->content, imageURLs);
      36            0 :                 allImageURLs.unite(imageURLs);
      37              :             }
      38              : 
      39           31 :             if (!news->description.isEmpty()) {
      40           30 :                 news->description = sanitizer.sanitize(news->description, imageURLs);
      41           30 :                 allImageURLs.unite(imageURLs);
      42              :             }
      43              : 
      44              :             // Include media image URLs for downloading and caching.
      45           31 :             if (!news->mediaImageURL.isEmpty()) {
      46            0 :                 allImageURLs.insert(QUrl(news->mediaImageURL));
      47              :             }
      48           31 :         }
      49              : 
      50           31 :         return allImageURLs;
      51           31 :     });
      52           31 :     sanitizeWatcher.setFuture(future);
      53           31 : }
      54              : 
      55           31 : void RawFeedRewriter::onSanitizeFinished()
      56              : {
      57           31 :     QSet<QUrl> allImageURLs = sanitizeWatcher.result();
      58              : 
      59              :     // No images? Finalize and we're done.
      60           31 :     if (allImageURLs.isEmpty()) {
      61           24 :         finalizeAll();
      62           24 :         emit finished();
      63           24 :         return;
      64              :     }
      65              : 
      66              :     // Fetch images, then finalize when done.
      67            7 :     imageGrabber.fetchUrls(allImageURLs.values());
      68           31 : }
      69              : 
      70            7 : void RawFeedRewriter::onImageGrabberFinished()
      71              : {
      72              :     // Run finalization on a background thread to avoid blocking the UI
      73              :     // during XML parsing and image caching.
      74            0 :     auto future = QtConcurrent::run([this]() {
      75            7 :         finalizeAll();
      76            7 :     });
      77            7 :     finalizeWatcher.setFuture(future);
      78            7 : }
      79              : 
      80           31 : void RawFeedRewriter::finalizeAll()
      81              : {
      82           31 :     QMap<QUrl, ImageData> imageResults = *imageGrabber.getResults();
      83              : 
      84           62 :     for (RawNews* news : *newsList) {
      85           31 :         if (!news->content.isEmpty()) {
      86            0 :             news->content = sanitizer.finalize(news->content, imageResults);
      87              :         }
      88              : 
      89           31 :         if (!news->description.isEmpty()) {
      90           30 :             news->description = sanitizer.finalize(news->description, imageResults);
      91              :         }
      92              : 
      93              :         // Cache media image and store cached path.
      94           31 :         if (!news->mediaImageURL.isEmpty()) {
      95            0 :             QUrl mediaUrl(news->mediaImageURL);
      96            0 :             if (imageResults.contains(mediaUrl)) {
      97            0 :                 QString cachedPath = ImageCache::saveImage(mediaUrl, imageResults.value(mediaUrl));
      98            0 :                 news->mediaImageURL = cachedPath;
      99            0 :             } else {
     100            0 :                 news->mediaImageURL = "";
     101              :             }
     102            0 :         }
     103              :     }
     104           31 : }
        

Generated by: LCOV version 2.0-1