File indexing completed on 2024-04-21 05:10:35

0001 /*
0002     This file is part of Akregator.
0003 
0004     SPDX-FileCopyrightText: 2004 Sashmit Bhaduri <smt@vfemail.net>
0005     SPDX-FileCopyrightText: 2005 Frank Osterfeld <osterfeld@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
0008 */
0009 
0010 #include "fetchqueue.h"
0011 #include "akregatorconfig.h"
0012 #include "feed.h"
0013 #include "treenode.h"
0014 
0015 using namespace Akregator;
0016 
0017 FetchQueue::FetchQueue(QObject *parent)
0018     : QObject(parent)
0019 {
0020 }
0021 
0022 FetchQueue::~FetchQueue()
0023 {
0024     slotAbort();
0025 }
0026 
0027 void FetchQueue::slotAbort()
0028 {
0029     for (Feed *const i : std::as_const(m_fetchingFeeds)) {
0030         disconnectFromFeed(i);
0031         i->slotAbortFetch();
0032     }
0033     m_fetchingFeeds.clear();
0034 
0035     for (Feed *const i : std::as_const(m_queuedFeeds)) {
0036         disconnectFromFeed(i);
0037     }
0038     m_queuedFeeds.clear();
0039 
0040     Q_EMIT signalStopped();
0041 }
0042 
0043 void FetchQueue::addFeed(Feed *f)
0044 {
0045     if (!m_queuedFeeds.contains(f) && !m_fetchingFeeds.contains(f)) {
0046         connectToFeed(f);
0047         m_queuedFeeds.append(f);
0048         fetchNextFeed();
0049     }
0050 }
0051 
0052 void FetchQueue::fetchNextFeed()
0053 {
0054     if (!m_queuedFeeds.isEmpty() && m_fetchingFeeds.count() < Settings::concurrentFetches()) {
0055         if (m_fetchingFeeds.isEmpty() && m_queuedFeeds.count() == 1) {
0056             Q_EMIT signalStarted();
0057         }
0058         Feed *f = *(m_queuedFeeds.begin());
0059         m_queuedFeeds.pop_front();
0060         m_fetchingFeeds.append(f);
0061         f->fetch(false);
0062     }
0063 }
0064 
0065 void FetchQueue::slotFeedFetched(Feed *f)
0066 {
0067     Q_EMIT fetched(f);
0068     feedDone(f);
0069 }
0070 
0071 void FetchQueue::slotFetchError(Feed *f)
0072 {
0073     Q_EMIT fetchError(f);
0074     feedDone(f);
0075 }
0076 
0077 void FetchQueue::slotFetchAborted(Feed *f)
0078 {
0079     Q_EMIT fetched(f); // FIXME: better use a signal like signalAborted(Feed*)
0080     feedDone(f);
0081 }
0082 
0083 bool FetchQueue::isEmpty() const
0084 {
0085     return m_queuedFeeds.isEmpty() && m_fetchingFeeds.isEmpty();
0086 }
0087 
0088 void FetchQueue::feedDone(Feed *f)
0089 {
0090     disconnectFromFeed(f);
0091     m_fetchingFeeds.removeAll(f);
0092     if (isEmpty()) {
0093         Q_EMIT signalStopped();
0094     } else {
0095         fetchNextFeed();
0096     }
0097 }
0098 
0099 void FetchQueue::connectToFeed(Feed *feed)
0100 {
0101     connect(feed, &Feed::fetched, this, &FetchQueue::slotFeedFetched);
0102     connect(feed, &Feed::fetchError, this, &FetchQueue::slotFetchError);
0103     connect(feed, &Feed::fetchAborted, this, &FetchQueue::slotFetchAborted);
0104     connect(feed, &TreeNode::signalDestroyed, this, &FetchQueue::slotNodeDestroyed);
0105 }
0106 
0107 void FetchQueue::disconnectFromFeed(Feed *feed)
0108 {
0109     feed->disconnect(this);
0110 }
0111 
0112 void FetchQueue::slotNodeDestroyed(TreeNode *node)
0113 {
0114     Feed *const feed = qobject_cast<Feed *>(node);
0115     Q_ASSERT(feed);
0116 
0117     m_fetchingFeeds.removeAll(feed);
0118     m_queuedFeeds.removeAll(feed);
0119 }
0120 
0121 #include "moc_fetchqueue.cpp"