1 /*
2 This file is part of Akregator.
3
4 SPDX-FileCopyrightText: 2004 Sashmit Bhaduri <smt@vfemail.net>
5 SPDX-FileCopyrightText: 2005 Frank Osterfeld <osterfeld@kde.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
8 */
9
10 #include "fetchqueue.h"
11 #include "akregatorconfig.h"
12 #include "feed.h"
13 #include "treenode.h"
14
15 using namespace Akregator;
16
FetchQueue(QObject * parent)17 FetchQueue::FetchQueue(QObject *parent)
18 : QObject(parent)
19 {
20 }
21
~FetchQueue()22 FetchQueue::~FetchQueue()
23 {
24 slotAbort();
25 }
26
slotAbort()27 void FetchQueue::slotAbort()
28 {
29 for (Feed *const i : std::as_const(m_fetchingFeeds)) {
30 disconnectFromFeed(i);
31 i->slotAbortFetch();
32 }
33 m_fetchingFeeds.clear();
34
35 for (Feed *const i : std::as_const(m_queuedFeeds)) {
36 disconnectFromFeed(i);
37 }
38 m_queuedFeeds.clear();
39
40 Q_EMIT signalStopped();
41 }
42
addFeed(Feed * f)43 void FetchQueue::addFeed(Feed *f)
44 {
45 if (!m_queuedFeeds.contains(f) && !m_fetchingFeeds.contains(f)) {
46 connectToFeed(f);
47 m_queuedFeeds.append(f);
48 fetchNextFeed();
49 }
50 }
51
fetchNextFeed()52 void FetchQueue::fetchNextFeed()
53 {
54 if (!m_queuedFeeds.isEmpty() && m_fetchingFeeds.count() < Settings::concurrentFetches()) {
55 if (m_fetchingFeeds.isEmpty() && m_queuedFeeds.count() == 1) {
56 Q_EMIT signalStarted();
57 }
58 Feed *f = *(m_queuedFeeds.begin());
59 m_queuedFeeds.pop_front();
60 m_fetchingFeeds.append(f);
61 f->fetch(false);
62 }
63 }
64
slotFeedFetched(Feed * f)65 void FetchQueue::slotFeedFetched(Feed *f)
66 {
67 Q_EMIT fetched(f);
68 feedDone(f);
69 }
70
slotFetchError(Feed * f)71 void FetchQueue::slotFetchError(Feed *f)
72 {
73 Q_EMIT fetchError(f);
74 feedDone(f);
75 }
76
slotFetchAborted(Feed * f)77 void FetchQueue::slotFetchAborted(Feed *f)
78 {
79 Q_EMIT fetched(f); // FIXME: better use a signal like signalAborted(Feed*)
80 feedDone(f);
81 }
82
isEmpty() const83 bool FetchQueue::isEmpty() const
84 {
85 return m_queuedFeeds.isEmpty() && m_fetchingFeeds.isEmpty();
86 }
87
feedDone(Feed * f)88 void FetchQueue::feedDone(Feed *f)
89 {
90 disconnectFromFeed(f);
91 m_fetchingFeeds.removeAll(f);
92 if (isEmpty()) {
93 Q_EMIT signalStopped();
94 } else {
95 fetchNextFeed();
96 }
97 }
98
connectToFeed(Feed * feed)99 void FetchQueue::connectToFeed(Feed *feed)
100 {
101 connect(feed, &Feed::fetched, this, &FetchQueue::slotFeedFetched);
102 connect(feed, &Feed::fetchError, this, &FetchQueue::slotFetchError);
103 connect(feed, &Feed::fetchAborted, this, &FetchQueue::slotFetchAborted);
104 connect(feed, &TreeNode::signalDestroyed, this, &FetchQueue::slotNodeDestroyed);
105 }
106
disconnectFromFeed(Feed * feed)107 void FetchQueue::disconnectFromFeed(Feed *feed)
108 {
109 feed->disconnect(this);
110 }
111
slotNodeDestroyed(TreeNode * node)112 void FetchQueue::slotNodeDestroyed(TreeNode *node)
113 {
114 Feed *const feed = qobject_cast<Feed *>(node);
115 Q_ASSERT(feed);
116
117 m_fetchingFeeds.removeAll(feed);
118 m_queuedFeeds.removeAll(feed);
119 }
120