fetchqueue.cpp 3.65 KB
Newer Older
Frank Osterfeld's avatar
Frank Osterfeld committed
1 2 3 4
/*
    This file is part of Akregator.

    Copyright (C) 2004 Sashmit Bhaduri <smt@vfemail.net>
5
                  2005 Frank Osterfeld <osterfeld@kde.org>
Frank Osterfeld's avatar
Frank Osterfeld committed
6 7 8 9 10 11 12 13 14 15 16 17 18

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
19
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Frank Osterfeld's avatar
Frank Osterfeld committed
20 21 22 23 24

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/
25

Frank Osterfeld's avatar
Frank Osterfeld committed
26
#include "fetchqueue.h"
27
#include "akregatorconfig.h"
28
#include "feed.h"
29
#include "treenode.h"
30

31

32
#include <QList>
33

Frank Osterfeld's avatar
Frank Osterfeld committed
34 35
#include <cassert>

Frank Osterfeld's avatar
cleanup  
Frank Osterfeld committed
36
using namespace Akregator;
37

38
class FetchQueue::FetchQueuePrivate
39
{
Laurent Montel's avatar
Laurent Montel committed
40
public:
41

Laurent Montel's avatar
Laurent Montel committed
42 43
    QList<Feed *> queuedFeeds;
    QList<Feed *> fetchingFeeds;
44 45
};

Laurent Montel's avatar
Laurent Montel committed
46 47
FetchQueue::FetchQueue(QObject *parent): QObject(parent), d(new FetchQueuePrivate)
{
48
}
49

50 51 52 53 54
FetchQueue::~FetchQueue()
{
    slotAbort();
    delete d;
    d = 0;
55 56
}

57
void FetchQueue::slotAbort()
58
{
Laurent Montel's avatar
Laurent Montel committed
59
    for (Feed *const i : qAsConst(d->fetchingFeeds)) {
Laurent Montel's avatar
Laurent Montel committed
60
        disconnectFromFeed(i);
Frank Osterfeld's avatar
cleanup  
Frank Osterfeld committed
61
        i->slotAbortFetch();
62 63
    }
    d->fetchingFeeds.clear();
64

Laurent Montel's avatar
Laurent Montel committed
65
    for (Feed *const i : qAsConst(d->queuedFeeds)) {
Laurent Montel's avatar
Laurent Montel committed
66 67
        disconnectFromFeed(i);
    }
68
    d->queuedFeeds.clear();
69

Laurent Montel's avatar
Laurent Montel committed
70
    Q_EMIT signalStopped();
71 72
}

73
void FetchQueue::addFeed(Feed *f)
74
{
Laurent Montel's avatar
Laurent Montel committed
75
    if (!d->queuedFeeds.contains(f) && !d->fetchingFeeds.contains(f)) {
76 77 78 79
        connectToFeed(f);
        d->queuedFeeds.append(f);
        fetchNextFeed();
    }
80 81
}

82
void FetchQueue::fetchNextFeed()
83
{
Laurent Montel's avatar
Laurent Montel committed
84 85
    if (!d->queuedFeeds.isEmpty() && d->fetchingFeeds.count() < Settings::concurrentFetches()) {
        if (d->fetchingFeeds.isEmpty() && d->queuedFeeds.count() == 1) {
Laurent Montel's avatar
Laurent Montel committed
86
            Q_EMIT signalStarted();
Laurent Montel's avatar
Laurent Montel committed
87 88
        }
        Feed *f = *(d->queuedFeeds.begin());
89 90 91
        d->queuedFeeds.pop_front();
        d->fetchingFeeds.append(f);
        f->fetch(false);
92

93
    }
94 95
}

96
void FetchQueue::slotFeedFetched(Feed *f)
97
{
Laurent Montel's avatar
Laurent Montel committed
98
    Q_EMIT fetched(f);
99 100 101
    feedDone(f);
}

102
void FetchQueue::slotFetchError(Feed *f)
103
{
Laurent Montel's avatar
Laurent Montel committed
104
    Q_EMIT fetchError(f);
105 106 107
    feedDone(f);
}

108
void FetchQueue::slotFetchAborted(Feed *f)
109
{
Laurent Montel's avatar
Laurent Montel committed
110
    Q_EMIT fetched(f); // FIXME: better use a signal like signalAborted(Feed*)
111 112 113
    feedDone(f);
}

114
bool FetchQueue::isEmpty() const
115 116 117
{
    return d->queuedFeeds.isEmpty() && d->fetchingFeeds.isEmpty();
}
118

119
void FetchQueue::feedDone(Feed *f)
120
{
121
    disconnectFromFeed(f);
122
    d->fetchingFeeds.removeAll(f);
Laurent Montel's avatar
Laurent Montel committed
123
    if (isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
124
        Q_EMIT signalStopped();
Laurent Montel's avatar
Laurent Montel committed
125
    } else {
126
        fetchNextFeed();
Laurent Montel's avatar
Laurent Montel committed
127
    }
128 129
}

Laurent Montel's avatar
Laurent Montel committed
130
void FetchQueue::connectToFeed(Feed *feed)
131
{
Laurent Montel's avatar
Laurent Montel committed
132 133 134 135
    connect(feed, &Feed::fetched, this, &FetchQueue::slotFeedFetched);
    connect(feed, &Feed::fetchError, this, &FetchQueue::slotFetchError);
    connect(feed, &Feed::fetchAborted, this, &FetchQueue::slotFetchAborted);
    connect(feed, &TreeNode::signalDestroyed, this, &FetchQueue::slotNodeDestroyed);
136 137
}

Laurent Montel's avatar
Laurent Montel committed
138
void FetchQueue::disconnectFromFeed(Feed *feed)
139
{
Laurent Montel's avatar
Laurent Montel committed
140
    feed->disconnect(this);
141 142
}

Laurent Montel's avatar
Laurent Montel committed
143
void FetchQueue::slotNodeDestroyed(TreeNode *node)
144
{
Laurent Montel's avatar
Laurent Montel committed
145
    Feed *const feed = qobject_cast<Feed *>(node);
Aleix Pol Gonzalez's avatar
Aleix Pol Gonzalez committed
146
    Q_ASSERT(feed);
147

Frank Osterfeld's avatar
Frank Osterfeld committed
148 149
    d->fetchingFeeds.removeAll(feed);
    d->queuedFeeds.removeAll(feed);
150 151
}