• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

akregator

  • sources
  • kde-4.14
  • kdepim
  • akregator
  • src
folder.cpp
Go to the documentation of this file.
1 /*
2  This file is part of Akregator.
3 
4  Copyright (C) 2004 Stanislav Karchebny <Stanislav.Karchebny@kdemail.net>
5  2004-2005 Frank Osterfeld <osterfeld@kde.org>
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 
21  As a special exception, permission is given to link this program
22  with any edition of Qt, and distribute the resulting executable,
23  without including the source code for Qt in the source distribution.
24 */
25 #include "folder.h"
26 #include "article.h"
27 #include "articlejobs.h"
28 #include "feed.h"
29 #include "fetchqueue.h"
30 #include "treenodevisitor.h"
31 
32 #include <qdom.h>
33 #include <QList>
34 
35 #include <KIcon>
36 #include <kdebug.h>
37 
38 #include <cassert>
39 
40 using namespace Akregator;
41 
42 class Folder::FolderPrivate
43 {
44  Folder* const q;
45  public:
46  explicit FolderPrivate( Folder* qq );
47  ~FolderPrivate();
48 
50  QList<TreeNode*> children;
52  mutable int unread;
54  bool open;
55 
57  QList<Article> addedArticlesNotify;
59  QList<Article> removedArticlesNotify;
60 };
61 
62 Folder::FolderPrivate::FolderPrivate( Folder* qq ) : q( qq ), unread( 0 ), open( false )
63 {
64 }
65 
66 Folder::FolderPrivate::~FolderPrivate()
67 {
68  while (!children.isEmpty()) {
69  // child removes itself from list in its destructor
70  delete children.first();
71  }
72  emit q->emitSignalDestroyed();
73 }
74 
75 bool Folder::accept(TreeNodeVisitor* visitor)
76 {
77  if (visitor->visitFolder(this))
78  return true;
79  else
80  return visitor->visitTreeNode(this);
81 }
82 
83 Folder* Folder::fromOPML(const QDomElement& e)
84 {
85  Folder* fg = new Folder(e.hasAttribute(QString::fromLatin1("text")) ? e.attribute(QString::fromLatin1("text")) : e.attribute(QString::fromLatin1("title")));
86  fg->setOpen( e.attribute(QString::fromLatin1("isOpen")) == QString::fromLatin1(("true")));
87  fg->setId( e.attribute(QString::fromLatin1("id")).toUInt() );
88  return fg;
89 }
90 
91 Folder::Folder( const QString& title ) : TreeNode(), d( new FolderPrivate( this ) )
92 {
93  setTitle( title );
94 }
95 
96 Folder::~Folder()
97 {
98  delete d;
99  d = 0;
100 }
101 
102 QList<Article> Folder::articles()
103 {
104  QList<Article> seq;
105  Q_FOREACH( Feed* const i, feeds() )
106  seq += i->articles();
107  return seq;
108 }
109 
110 QDomElement Folder::toOPML( QDomElement parent, QDomDocument document ) const
111 {
112  QDomElement el = document.createElement( QLatin1String("outline") );
113  el.setAttribute( QLatin1String("text"), title() );
114  parent.appendChild( el );
115  el.setAttribute(QLatin1String("isOpen"), d->open ? QLatin1String("true") : QLatin1String("false"));
116  el.setAttribute( QLatin1String("id"), QString::number(id()) );
117 
118  Q_FOREACH ( const Akregator::TreeNode* i, d->children )
119  el.appendChild( i->toOPML(el, document) );
120  return el;
121 }
122 
123 
124 QList<const TreeNode*> Folder::children() const
125 {
126  QList<const TreeNode*> children;
127  Q_FOREACH( const TreeNode* i, d->children )
128  children.append( i );
129  return children;
130 }
131 
132 QList<TreeNode*> Folder::children()
133 {
134  return d->children;
135 }
136 
137 QVector<const Akregator::Feed*> Folder::feeds() const
138 {
139  QHash<int, const Akregator::Feed*> feedsById;
140  Q_FOREACH( const TreeNode* i, d->children )
141  Q_FOREACH ( const Akregator::Feed* j, i->feeds() )
142  feedsById.insert( j->id(), j );
143  return feedsById.values().toVector();
144 }
145 
146 QVector<Akregator::Feed*> Folder::feeds()
147 {
148  QHash<int, Akregator::Feed*> feedsById;
149  Q_FOREACH( TreeNode* i, d->children )
150  Q_FOREACH ( Akregator::Feed* j, i->feeds() )
151  feedsById.insert( j->id(), j );
152  return feedsById.values().toVector();
153 }
154 
155 QVector<const Folder*> Folder::folders() const
156 {
157  QHash<int, const Folder*> foldersById;
158  foldersById.insert( id(), this );
159  Q_FOREACH( const TreeNode* i, d->children )
160  Q_FOREACH ( const Folder* j, i->folders() )
161  foldersById.insert( j->id(), j );
162  return foldersById.values().toVector();
163 }
164 
165 QVector<Folder*> Folder::folders()
166 {
167  QHash<int, Folder*> foldersById;
168  foldersById.insert( id(), this );
169  Q_FOREACH( TreeNode* i, d->children )
170  Q_FOREACH ( Folder* j, i->folders() )
171  foldersById.insert( j->id(), j );
172  return foldersById.values().toVector();
173 }
174 
175 int Folder::indexOf( const TreeNode* node ) const
176 {
177  return children().indexOf( node );
178 }
179 
180 void Folder::insertChild(TreeNode* node, TreeNode* after)
181 {
182  int pos = d->children.indexOf(after);
183 
184  if (pos < 0)
185  prependChild(node);
186  else
187  insertChild(pos, node);
188 }
189 
190 QIcon Folder::icon() const
191 {
192  return KIcon(QLatin1String("folder"));
193 }
194 
195 void Folder::insertChild(int index, TreeNode* node)
196 {
197 // kDebug() <<"enter Folder::insertChild(int, node)" << node->title();
198  if (node)
199  {
200  if (index >= d->children.size())
201  d->children.append(node);
202  else
203  d->children.insert(index, node);
204  node->setParent(this);
205  connectToNode(node);
206  updateUnreadCount();
207  emit signalChildAdded(node);
208  d->addedArticlesNotify += node->articles();
209  articlesModified();
210  nodeModified();
211  }
212 // kDebug() <<"leave Folder::insertChild(int, node)" << node->title();
213 }
214 
215 void Folder::appendChild(TreeNode* node)
216 {
217 // kDebug() <<"enter Folder::appendChild()" << node->title();
218  if (node)
219  {
220  d->children.append(node);
221  node->setParent(this);
222  connectToNode(node);
223  updateUnreadCount();
224  emit signalChildAdded(node);
225  d->addedArticlesNotify += node->articles();
226  articlesModified();
227  nodeModified();
228  }
229 // kDebug() <<"leave Folder::appendChild()" << node->title();
230 }
231 
232 void Folder::prependChild(TreeNode* node)
233 {
234 // kDebug() <<"enter Folder::prependChild()" << node->title();
235  if (node)
236  {
237  d->children.prepend(node);
238  node->setParent(this);
239  connectToNode(node);
240  updateUnreadCount();
241  emit signalChildAdded(node);
242  d->addedArticlesNotify += node->articles();
243  articlesModified();
244  nodeModified();
245  }
246 // kDebug() <<"leave Folder::prependChild()" << node->title();
247 }
248 
249 void Folder::removeChild(TreeNode* node)
250 {
251  if (!node || !d->children.contains(node))
252  return;
253 
254  emit signalAboutToRemoveChild( node );
255  node->setParent(0);
256  d->children.removeOne(node);
257  disconnectFromNode(node);
258  updateUnreadCount();
259  emit signalChildRemoved(this, node);
260  d->removedArticlesNotify += node->articles();
261  articlesModified(); // articles were removed, TODO: add guids to a list
262  nodeModified();
263 }
264 
265 
266 TreeNode* Folder::firstChild()
267 {
268  return d->children.isEmpty() ? 0 : children().first();
269 }
270 
271 const TreeNode* Folder::firstChild() const
272 {
273  return d->children.isEmpty() ? 0 : children().first();
274 }
275 
276 TreeNode* Folder::lastChild()
277 {
278  return d->children.isEmpty() ? 0 : children().last();
279 }
280 
281 const TreeNode* Folder::lastChild() const
282 {
283  return d->children.isEmpty() ? 0 : children().last();
284 }
285 
286 bool Folder::isOpen() const
287 {
288  return d->open;
289 }
290 
291 void Folder::setOpen(bool open)
292 {
293  d->open = open;
294 }
295 
296 int Folder::unread() const
297 {
298  return d->unread;
299 }
300 
301 int Folder::totalCount() const
302 {
303  int total = 0;
304  Q_FOREACH( const Feed* const i, feeds() )
305  total += i->totalCount();
306  return total;
307 }
308 
309 void Folder::updateUnreadCount() const
310 {
311  int unread = 0;
312  Q_FOREACH ( const Feed* const i, feeds() )
313  unread += i->unread();
314  d->unread = unread;
315 }
316 
317 KJob* Folder::createMarkAsReadJob()
318 {
319  std::auto_ptr<CompositeJob> job( new CompositeJob );
320  Q_FOREACH( Feed* const i, feeds() )
321  job->addSubjob( i->createMarkAsReadJob() );
322  return job.release();
323 }
324 
325 void Folder::slotChildChanged(TreeNode* /*node*/)
326 {
327  updateUnreadCount();
328  nodeModified();
329 }
330 
331 void Folder::slotChildDestroyed(TreeNode* node)
332 {
333  d->children.removeAll(node);
334  updateUnreadCount();
335  nodeModified();
336 }
337 
338 bool Folder::subtreeContains( const TreeNode* node ) const
339 {
340  if ( node == this )
341  return false;
342  const Folder* parent = node ? node->parent() : 0;
343  while ( parent )
344  {
345  if ( parent == this )
346  return true;
347  parent = parent->parent();
348  }
349 
350  return false;
351 }
352 
353 void Folder::slotAddToFetchQueue(FetchQueue* queue, bool intervalFetchOnly)
354 {
355  Q_FOREACH( Feed* const i, feeds() )
356  i->slotAddToFetchQueue( queue, intervalFetchOnly );
357 }
358 
359 void Folder::doArticleNotification()
360 {
361 }
362 
363 void Folder::connectToNode(TreeNode* child)
364 {
365  connect(child, SIGNAL(signalChanged(Akregator::TreeNode*)), this, SLOT(slotChildChanged(Akregator::TreeNode*)));
366  connect(child, SIGNAL(signalDestroyed(Akregator::TreeNode*)), this, SLOT(slotChildDestroyed(Akregator::TreeNode*)));
367  connect(child, SIGNAL(signalArticlesAdded(Akregator::TreeNode*,QList<Akregator::Article>)), this, SIGNAL(signalArticlesAdded(Akregator::TreeNode*,QList<Akregator::Article>)));
368  connect(child, SIGNAL(signalArticlesRemoved(Akregator::TreeNode*,QList<Akregator::Article>)), this, SIGNAL(signalArticlesRemoved(Akregator::TreeNode*,QList<Akregator::Article>)));
369  connect(child, SIGNAL(signalArticlesUpdated(Akregator::TreeNode*,QList<Akregator::Article>)), this, SIGNAL(signalArticlesUpdated(Akregator::TreeNode*,QList<Akregator::Article>)));
370 }
371 
372 void Folder::disconnectFromNode(TreeNode* child)
373 {
374  assert( child );
375  child->disconnect( this );
376 }
377 
378 
379 TreeNode* Folder::childAt( int pos )
380 {
381  if ( pos < 0 || pos >= d->children.count() )
382  return 0;
383  return d->children.at( pos );
384 }
385 
386 const TreeNode* Folder::childAt( int pos ) const
387 {
388  if ( pos < 0 || pos >= d->children.count() )
389  return 0;
390  return d->children.at( pos );
391 }
392 
393 TreeNode* Folder::next()
394 {
395  if ( firstChild() )
396  return firstChild();
397 
398  if ( nextSibling() )
399  return nextSibling();
400 
401  Folder* p = parent();
402  while (p)
403  {
404  if ( p->nextSibling() )
405  return p->nextSibling();
406  else
407  p = p->parent();
408  }
409  return 0;
410 }
411 
412 const TreeNode* Folder::next() const
413 {
414  if ( firstChild() )
415  return firstChild();
416 
417  if ( nextSibling() )
418  return nextSibling();
419 
420  const Folder* p = parent();
421  while (p)
422  {
423  if ( p->nextSibling() )
424  return p->nextSibling();
425  else
426  p = p->parent();
427  }
428  return 0;
429 }
430 
431 QList<const TreeNode*> Folder::namedChildren( const QString& title ) const
432 {
433  QList<const TreeNode*> nodeList;
434  foreach( const TreeNode * child, children() ) {
435  if ( child->title() == title ) {
436  nodeList.append( child );
437  }
438  const Folder * fld = dynamic_cast<const Folder*>( child );
439  if ( fld ) {
440  nodeList += fld->namedChildren( title );
441  }
442  }
443  return nodeList;
444 }
445 
446 QList<TreeNode*> Folder::namedChildren( const QString& title )
447 {
448  QList<TreeNode*> nodeList;
449  foreach( TreeNode * const child, children() ) {
450  if ( child->title() == title ) {
451  nodeList.append( child );
452  }
453  Folder * const fld = qobject_cast<Folder*>( child );
454  if ( fld )
455  nodeList += fld->namedChildren( title );
456  }
457  return nodeList;
458 }
459 
QObject::child
QObject * child(const char *objName, const char *inheritsClass, bool recursiveSearch) const
Akregator::Feed::totalCount
int totalCount() const
returns the number of total articles in this feed
Definition: feed.cpp:785
Akregator::Folder::toOPML
QDomElement toOPML(QDomElement parent, QDomDocument document) const
converts the feed group into OPML format for save and export and appends it to node parent in documen...
Definition: folder.cpp:110
Akregator::TreeNode::folders
virtual QVector< const Folder * > folders() const =0
QHash::insert
iterator insert(const Key &key, const T &value)
Akregator::TreeNode::signalArticlesRemoved
void signalArticlesRemoved(Akregator::TreeNode *, const QList< Akregator::Article > &guids)
emitted when articles were removed from this subtree.
QDomNode::appendChild
QDomNode appendChild(const QDomNode &newChild)
QDomElement::attribute
QString attribute(const QString &name, const QString &defValue) const
Akregator::Folder::fromOPML
static Folder * fromOPML(const QDomElement &e)
creates a feed group parsed from a XML dom element.
Definition: folder.cpp:83
Akregator::TreeNode::feeds
virtual QVector< const Feed * > feeds() const =0
Akregator::TreeNode::title
QString title() const
Get title of node.
Definition: treenode.cpp:87
articlejobs.h
QList::toVector
QVector< T > toVector() const
Akregator::TreeNode::setId
virtual void setId(uint id)
sets the ID
Definition: treenode.cpp:203
Akregator::Folder::removeChild
void removeChild(TreeNode *node)
remove node from children.
Definition: folder.cpp:249
Akregator::CompositeJob
Definition: articlejobs.h:60
Akregator::Folder::isOpen
bool isOpen() const
returns whether the feed group is opened or not.
Definition: folder.cpp:286
Akregator::Folder::Folder
Folder(const QString &title=QString())
Creates a new folder with a given title.
Definition: folder.cpp:91
QObject::disconnect
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
Akregator::Folder::~Folder
~Folder()
Definition: folder.cpp:96
Akregator::TreeNode::signalDestroyed
void signalDestroyed(Akregator::TreeNode *)
Emitted when this object is deleted.
feed.h
Akregator::Folder::signalChildAdded
void signalChildAdded(Akregator::TreeNode *)
emitted when a child was added
Akregator::Folder::lastChild
TreeNode * lastChild()
returns the last child of the group, 0 if none exist
Definition: folder.cpp:276
Akregator::TreeNode::toOPML
virtual QDomElement toOPML(QDomElement parent, QDomDocument document) const =0
exports node and child nodes to OPML (with akregator settings)
Akregator::TreeNode::parent
virtual const Folder * parent() const
Returns the parent node.
Definition: treenode.cpp:141
treenodevisitor.h
Akregator::Folder::prependChild
void prependChild(TreeNode *node)
inserts node as first child
Definition: folder.cpp:232
Akregator::Folder::childAt
TreeNode * childAt(int pos)
Definition: folder.cpp:379
Akregator::TreeNode::nodeModified
virtual void nodeModified()
call this if you modified the actual node (title, unread count).
Definition: treenode.cpp:208
Akregator::Folder::signalChildRemoved
void signalChildRemoved(Akregator::Folder *, Akregator::TreeNode *)
emitted when a child was removed
QString::number
QString number(int n, int base)
QList::append
void append(const T &value)
Akregator::TreeNode::signalArticlesAdded
void signalArticlesAdded(Akregator::TreeNode *, const QList< Akregator::Article > &guids)
emitted when new articles were added to this node or any node in the subtree (for folders)...
QDomElement::hasAttribute
bool hasAttribute(const QString &name) const
QHash
Definition: feedlist.h:41
QDomElement::setAttribute
void setAttribute(const QString &name, const QString &value)
Akregator::Folder::createMarkAsReadJob
KJob * createMarkAsReadJob()
Definition: folder.cpp:317
Akregator::Folder::setOpen
void setOpen(bool open)
open/close the feed group (display it as expanded/collapsed in the tree view).
Definition: folder.cpp:291
Akregator::Folder::next
TreeNode * next()
returns the next node in the tree.
Definition: folder.cpp:393
Akregator::TreeNode::setTitle
void setTitle(const QString &title)
Sets the title of the node.
Definition: treenode.cpp:92
Akregator::Folder::appendChild
void appendChild(TreeNode *node)
inserts node as last child
Definition: folder.cpp:215
fetchqueue.h
Akregator::Folder::accept
bool accept(TreeNodeVisitor *visitor)
Definition: folder.cpp:75
Akregator::Folder::children
QList< const TreeNode * > children() const
returns the (direct) children of this node.
Definition: folder.cpp:124
Akregator::Folder::signalAboutToRemoveChild
void signalAboutToRemoveChild(Akregator::TreeNode *)
QString
QList
Definition: article.h:41
article.h
Akregator::TreeNode::setParent
virtual void setParent(Folder *parent)
Sets parent node; Don't call this directly, is done automatically by insertChild-methods in Folder...
Definition: treenode.cpp:173
Akregator::Folder::slotChildChanged
void slotChildChanged(Akregator::TreeNode *node)
Called when a child was modified.
Definition: folder.cpp:325
Akregator::TreeNode::signalArticlesUpdated
void signalArticlesUpdated(Akregator::TreeNode *, const QList< Akregator::Article > &guids)
emitted when articles were updated
QDomDocument
Akregator::Folder::icon
QIcon icon() const
Definition: folder.cpp:190
folder.h
Akregator::TreeNode::signalChanged
void signalChanged(Akregator::TreeNode *)
Notification mechanism: emitted, when the node was modified and notification is enabled.
Akregator::TreeNodeVisitor::visitFolder
virtual bool visitFolder(Folder *)
Definition: treenodevisitor.h:41
Akregator::Feed::slotAddToFetchQueue
void slotAddToFetchQueue(Akregator::FetchQueue *queue, bool intervalFetchOnly=false)
add this feed to the fetch queue queue
Definition: feed.cpp:433
Akregator::Folder::feeds
QVector< const Feed * > feeds() const
Definition: folder.cpp:137
Akregator::TreeNode::nextSibling
virtual const TreeNode * nextSibling() const
Get the next sibling.
Definition: treenode.cpp:112
QVector
QLatin1String
Akregator::TreeNodeVisitor
Definition: treenodevisitor.h:35
Akregator::Feed
represents a feed
Definition: feed.h:53
Akregator::Folder
Represents a folder (containing feeds and/or other folders)
Definition: folder.h:44
Akregator::Folder::folders
QVector< const Folder * > folders() const
Definition: folder.cpp:155
Akregator::Folder::slotChildDestroyed
void slotChildDestroyed(Akregator::TreeNode *node)
Called when a child was destroyed.
Definition: folder.cpp:331
Akregator::Folder::slotAddToFetchQueue
void slotAddToFetchQueue(Akregator::FetchQueue *queue, bool intervalFetchesOnly=false)
enqueues children recursively for fetching
Definition: folder.cpp:353
Akregator::Folder::indexOf
int indexOf(const TreeNode *node) const
Definition: folder.cpp:175
QHash::values
QList< T > values() const
Akregator::Folder::totalCount
int totalCount() const
returns the number of articles in all children
Definition: folder.cpp:301
Akregator::Folder::namedChildren
QList< const TreeNode * > namedChildren(const QString &title) const
Definition: folder.cpp:431
Akregator::TreeNode::articlesModified
virtual void articlesModified()
call this if the articles in the node were changed.
Definition: treenode.cpp:216
QString::fromLatin1
QString fromLatin1(const char *str, int size)
Akregator::Feed::createMarkAsReadJob
KJob * createMarkAsReadJob()
Definition: feed.cpp:422
Akregator::Folder::doArticleNotification
void doArticleNotification()
reimplement this in subclasses to do the actual notification called by articlesModified ...
Definition: folder.cpp:359
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QDomElement
Akregator::TreeNode
Abstract base class for all kind of elements in the feed tree, like feeds and feed groups (and search...
Definition: treenode.h:58
Akregator::TreeNode::id
virtual uint id() const
returns the ID of this node.
Definition: treenode.cpp:198
Akregator::Folder::insertChild
void insertChild(TreeNode *node, TreeNode *after)
inserts node as child after child node after.
Definition: folder.cpp:180
KJob
Akregator::FetchQueue
Definition: fetchqueue.h:37
Akregator::Folder::firstChild
TreeNode * firstChild()
returns the first child of the group, 0 if none exist
Definition: folder.cpp:266
QIcon
Akregator::Folder::unread
int unread() const
returns the number of unread articles in all children
Definition: folder.cpp:296
Akregator::TreeNodeVisitor::visitTreeNode
virtual bool visitTreeNode(TreeNode *)
Definition: treenodevisitor.h:40
QString::toUInt
uint toUInt(bool *ok, int base) const
Akregator::Folder::subtreeContains
bool subtreeContains(const Akregator::TreeNode *node) const
Definition: folder.cpp:338
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:34:00 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akregator

Skip menu "akregator"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer
  • pimprint

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal