File indexing completed on 2024-05-05 05:13:01

0001 /*
0002     This file is part of Akregator.
0003 
0004     SPDX-FileCopyrightText: 2004 Frank Osterfeld <osterfeld@kde.org>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
0007 */
0008 
0009 #pragma once
0010 
0011 #include "akregator_export.h"
0012 
0013 #include "feedlistmanagementinterface.h"
0014 
0015 #include <QObject>
0016 
0017 #include <QSharedPointer>
0018 
0019 #include <memory>
0020 
0021 class QDomDocument;
0022 class QDomNode;
0023 template<class T>
0024 class QList;
0025 template<class K, class T>
0026 class QHash;
0027 class QString;
0028 
0029 class KJob;
0030 
0031 namespace Akregator
0032 {
0033 class Article;
0034 class Feed;
0035 class FeedList;
0036 class FetchQueue;
0037 class Folder;
0038 class TreeNode;
0039 
0040 namespace Backend
0041 {
0042 class Storage;
0043 }
0044 
0045 class AKREGATOR_EXPORT FeedListManagementImpl : public FeedListManagementInterface
0046 {
0047 public:
0048     explicit FeedListManagementImpl(const QSharedPointer<FeedList> &list = QSharedPointer<FeedList>());
0049     void setFeedList(const QSharedPointer<FeedList> &list);
0050 
0051     [[nodiscard]] QStringList categories() const override;
0052     [[nodiscard]] QStringList feeds(const QString &catId) const override;
0053     void addFeed(const QString &url, const QString &catId) override;
0054     void removeFeed(const QString &url, const QString &catId) override;
0055     [[nodiscard]] QString getCategoryName(const QString &catId) const override;
0056 
0057 private:
0058     QSharedPointer<FeedList> m_feedList;
0059 };
0060 
0061 class FeedListPrivate;
0062 
0063 /** @class FeedList
0064     The model of a feed tree, represents an OPML document. Contains an additional root node "All Feeds" which isn't stored. Note that a node instance must not
0065    be in more than one FeedList at a time! When deleting the feed list, all contained nodes are deleted! */
0066 
0067 class AKREGATOR_EXPORT FeedList : public QObject
0068 {
0069     Q_OBJECT
0070 public:
0071     explicit FeedList(Akregator::Backend::Storage *storage);
0072 
0073     /** Destructor. Contained nodes are deleted! */
0074     ~FeedList() override;
0075 
0076     const Folder *allFeedsFolder() const;
0077     Folder *allFeedsFolder();
0078 
0079     [[nodiscard]] bool isEmpty() const;
0080 
0081     const TreeNode *findByID(uint id) const;
0082     TreeNode *findByID(uint id);
0083 
0084     [[nodiscard]] QList<const TreeNode *> findByTitle(const QString &title) const;
0085     [[nodiscard]] QList<TreeNode *> findByTitle(const QString &title);
0086 
0087     /** returns the title of the feed list (as used in the OPML document) */
0088     [[nodiscard]] QString title() const;
0089 
0090     /** sets the title of the feed list */
0091     void setTitle(const QString &name);
0092 
0093     /**
0094      * returns all feeds in this list
0095      */
0096     [[nodiscard]] QList<const Akregator::Feed *> feeds() const;
0097     [[nodiscard]] QList<Akregator::Feed *> feeds();
0098 
0099     [[nodiscard]] QList<uint> feedIds() const;
0100 
0101     /**
0102      * returns all folders in this list
0103      */
0104     [[nodiscard]] QList<const Folder *> folders() const;
0105     [[nodiscard]] QList<Folder *> folders();
0106 
0107     /** appends another feed list as sub tree. The root node of @c list is ignored. NOTE: nodes are _moved_ from @c list to this feed list, not copied */
0108 
0109     void append(FeedList *list, Folder *parent = nullptr, TreeNode *after = nullptr);
0110 
0111     /** reads an OPML document and appends the items to this list
0112         @param doc the OPML document to parse
0113         @return whether parsing was successful or not (TODO: make errors more detailed)
0114     */
0115     [[nodiscard]] bool readFromOpml(const QDomDocument &doc);
0116 
0117     /** exports the feed list as OPML. The root node ("All Feeds") is ignored! */
0118     [[nodiscard]] QDomDocument toOpml() const;
0119 
0120     /** returns a feed object for a given feed URL. If the feed list does not contain a feed with @c url, NULL is returned. If it contains the same feed
0121      * multiple times, any of the Feed objects is returned. */
0122     const Feed *findByURL(const QString &feedURL) const;
0123     Feed *findByURL(const QString &feedURL);
0124 
0125     const Article findArticle(const QString &feedURL, const QString &guid) const;
0126 
0127     [[nodiscard]] int unread() const;
0128 
0129     void addToFetchQueue(FetchQueue *queue, bool intervalOnly = false);
0130     KJob *createMarkAsReadJob();
0131 
0132 Q_SIGNALS:
0133 
0134     void signalDestroyed(Akregator::FeedList *);
0135 
0136     /** emitted when a node was added to the list */
0137     void signalNodeAdded(Akregator::TreeNode *);
0138 
0139     /** emitted when a node was removed from the list */
0140     void signalNodeRemoved(Akregator::TreeNode *);
0141 
0142     void signalAboutToRemoveNode(Akregator::TreeNode *);
0143 
0144     void signalNodeChanged(Akregator::TreeNode *);
0145 
0146     /** emitted when fetching started */
0147     void fetchStarted(Akregator::Feed *);
0148 
0149     /** emitted when feed finished fetching */
0150     void fetched(Akregator::Feed *);
0151 
0152     /** emitted when a fetch error occurred */
0153     void fetchError(Akregator::Feed *);
0154     /** emitted when a feed URL was found by auto discovery */
0155     void fetchDiscovery(Akregator::Feed *);
0156 
0157     /** emitted when a fetch is aborted */
0158     void fetchAborted(Akregator::Feed *);
0159 
0160     void unreadCountChanged(int unread);
0161 
0162 private:
0163     void addNode(TreeNode *node, bool preserveID);
0164     void removeNode(TreeNode *node);
0165 
0166     uint generateID() const;
0167     void setRootNode(Folder *folder);
0168 
0169     void parseChildNodes(QDomNode &node, Folder *parent);
0170 
0171 private Q_SLOTS:
0172 
0173     void slotNodeDestroyed(Akregator::TreeNode *node);
0174     void slotNodeAdded(Akregator::TreeNode *node);
0175     void slotNodeRemoved(Akregator::Folder *parent, Akregator::TreeNode *node);
0176     void rootNodeChanged();
0177 
0178 private:
0179     friend class AddNodeVisitor;
0180     class AddNodeVisitor;
0181 
0182     friend class RemoveNodeVisitor;
0183     class RemoveNodeVisitor;
0184 
0185     friend class FeedListPrivate;
0186     std::unique_ptr<FeedListPrivate> const d;
0187 };
0188 } // namespace Akregator