1 /*
2     This file is part of Akregator.
3 
4     SPDX-FileCopyrightText: 2004 Frank Osterfeld <osterfeld@kde.org>
5 
6     SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
7 */
8 
9 #pragma once
10 
11 #include "akregator_export.h"
12 #include <QObject>
13 #include <QPoint>
14 #include <QVector>
15 
16 class KJob;
17 
18 class QDomDocument;
19 class QDomElement;
20 class QIcon;
21 class QString;
22 template<class T> class QList;
23 
24 namespace Akregator
25 {
26 class ArticleListJob;
27 class TreeNodeVisitor;
28 class Article;
29 class Feed;
30 class Folder;
31 class FetchQueue;
32 
33 /**
34     \brief Abstract base class for all kind of elements in the feed tree, like feeds and feed groups (and search folders later).
35 
36     TODO: detailed description goes here
37 */
38 class AKREGATOR_EXPORT TreeNode : public QObject
39 {
40     friend class ::Akregator::ArticleListJob;
41     friend class ::Akregator::Folder;
42 
43     Q_OBJECT
44 
45 public:
46     /** Standard constructor */
47     TreeNode();
48 
49     /** Standard destructor */
50     ~TreeNode() override;
51 
52     virtual bool accept(TreeNodeVisitor *visitor) = 0;
53 
54     /** The unread count, returns the number of new/unread articles in the node (for groups: the accumulated count of the subtree)
55     @return number of new/unread articles */
56 
57     virtual int unread() const = 0;
58 
59     /** returns the number of total articles in the node (for groups: the accumulated count of the subtree)
60     @return number of articles */
61 
62     virtual int totalCount() const = 0;
63 
64     /** Get title of node.
65     @return the title of the node */
66 
67     Q_REQUIRED_RESULT QString title() const;
68 
69     /** Sets the title of the node.
70     @c title should not contain entities.
71     @param title the title string */
72 
73     void setTitle(const QString &title);
74 
75     /** Get the next sibling.
76     @return the next sibling, 0 if there is none */
77 
78     virtual const TreeNode *nextSibling() const;
79     virtual TreeNode *nextSibling();
80 
81     /** Get the previous sibling.
82     @return the previous sibling, 0 if there is none */
83 
84     virtual const TreeNode *prevSibling() const;
85     virtual TreeNode *prevSibling();
86 
87     /** Returns the parent node.
88     @return the parent feed group, 0 if there is none */
89 
90     virtual const Folder *parent() const;
91     virtual Folder *parent();
92 
93     /** returns the (direct) children of this node.
94         @return a list of pointers to the child nodes
95      */
96     virtual QList<const TreeNode *> children() const;
97     virtual QList<TreeNode *> children();
98 
99     virtual QVector<const Feed *> feeds() const = 0;
100     virtual QVector<Feed *> feeds() = 0;
101 
102     virtual QVector<const Folder *> folders() const = 0;
103     virtual QVector<Folder *> folders() = 0;
104 
105     virtual TreeNode *childAt(int pos);
106     virtual const TreeNode *childAt(int pos) const;
107 
108     /** Sets parent node; Don't call this directly, is done automatically by
109     insertChild-methods in @ref Folder. */
110 
111     virtual void setParent(Folder *parent);
112 
113     virtual QIcon icon() const = 0;
114 
115     ArticleListJob *createListJob();
116 
117     /** Helps the rest of the app to decide if node should be handled as group or not. Only use where necessary, use polymorphism where possible.
118     @return whether the node is a feed group or not */
119 
120     virtual bool isGroup() const = 0;
121 
122     /** returns if the node represents an aggregation, i.e. containing
123      * items from more than once source feed. Folders and virtual folders
124      * are aggregations, feeds are not.
125      */
126     virtual bool isAggregation() const = 0;
127 
128     /** exports node and child nodes to OPML (with akregator settings)
129         @param parent the dom element the child node will be attached to
130         @param document the opml document */
131 
132     virtual QDomElement toOPML(QDomElement parent, QDomDocument document) const = 0;
133 
134     /**
135     @param doNotify notification on changes on/off flag
136     */
137 
138     virtual void setNotificationMode(bool doNotify);
139 
140     /** returns the next node in the tree.
141         Calling next() unless it returns 0 iterates through the tree in pre-order
142      */
143     virtual const TreeNode *next() const = 0;
144     virtual TreeNode *next() = 0;
145 
146     /** returns the ID of this node. IDs are managed by FeedList objects and must be unique within the list. Some IDs have a special meaning:
147     @c 0 is the default value and indicates that no ID was set
148     @c 1 is reserved for the "All Feeds" root node */
149     virtual uint id() const;
150 
151     /** sets the ID */
152     virtual void setId(uint id);
153 
154     QPoint listViewScrollBarPositions() const;
155     void setListViewScrollBarPositions(const QPoint &pos);
156 
157     virtual KJob *createMarkAsReadJob() = 0;
158 
159 public Q_SLOTS:
160 
161     /** adds node to a fetch queue
162         @param queue pointer to the queue
163         @param intervalFetchesOnly determines whether to allow only interval fetches
164     */
165     virtual void slotAddToFetchQueue(Akregator::FetchQueue *queue, bool intervalFetchesOnly = false) = 0;
166 
167 Q_SIGNALS:
168 
169     /** Emitted when this object is deleted. */
170     void signalDestroyed(Akregator::TreeNode *);
171 
172     /** Notification mechanism: emitted, when the node was modified and notification is enabled. A node change is renamed title, icon, unread count. Added,
173      * updated or removed articles are not notified via this signal */
174     void signalChanged(Akregator::TreeNode *);
175 
176     /** emitted when new articles were added to this node or any node in the subtree (for folders). Note that this has nothing to do with fetching, the article
177        might have been moved from somewhere else in the tree into this subtree, e.g. by moving the feed the article is in.
178         @param TreeNode* the node articles were added to
179         @param guids the guids of the articles added
180     */
181     void signalArticlesAdded(Akregator::TreeNode *, const QVector<Akregator::Article> &guids);
182 
183     /** emitted when articles were updated */
184     void signalArticlesUpdated(Akregator::TreeNode *, const QVector<Akregator::Article> &guids);
185 
186     /** emitted when articles were removed from this subtree. Note that this has nothing to do with actual article deletion! The article might have moved
187      * somewhere else in the tree, e.g. if the user moved the feed */
188     void signalArticlesRemoved(Akregator::TreeNode *, const QVector<Akregator::Article> &guids);
189 
190 protected:
191     /** call this if you modified the actual node (title, unread count).
192      Call this only when the _actual_ _node_ has changed, i.e. title, unread count. Don't use for article changes!
193      Will do notification immediately or cache it, depending on @c m_doNotify. */
194     virtual void nodeModified();
195 
196     /** call this if the articles in the node were changed. Sends signalArticlesAdded/Updated/Removed signals
197      Will do notification immediately or cache it, depending on @c m_doNotify. */
198     virtual void articlesModified();
199 
200     /** reimplement this in subclasses to do the actual notification
201       called by articlesModified
202     */
203     virtual void doArticleNotification();
204 
205     void emitSignalDestroyed();
206 
207 private:
208     /** Returns a sequence of the articles this node contains. For feed groups, this returns a concatenated list of all articles in the sub tree.
209     @return sequence of articles */
210 
211     virtual QVector<Article> articles() = 0;
212 
213 private:
214     bool m_doNotify = true;
215     bool m_nodeChangeOccurred = false;
216     bool m_articleChangeOccurred = false;
217     QString m_title;
218     Folder *m_parent = nullptr;
219     QPoint m_scrollBarPositions;
220     uint m_id = 0;
221     bool m_signalDestroyedEmitted = false;
222 };
223 } // namespace Akregator
224 
225