00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "article.h"
00026 #include "folder.h"
00027 #include "fetchqueue.h"
00028 #include "treenodevisitor.h"
00029
00030 #include <qlistview.h>
00031 #include <qdom.h>
00032 #include <qstringlist.h>
00033 #include <qvaluelist.h>
00034
00035 #include <kdebug.h>
00036
00037 namespace Akregator {
00038
00039 class Folder::FolderPrivate
00040 {
00041 public:
00043 QValueList<TreeNode*> children;
00045 int unread;
00047 bool open;
00048
00050 QValueList<Article> addedArticlesNotify;
00052 QValueList<Article> removedArticlesNotify;
00053 };
00054
00055 bool Folder::accept(TreeNodeVisitor* visitor)
00056 {
00057 if (visitor->visitFolder(this))
00058 return true;
00059 else
00060 return visitor->visitTreeNode(this);
00061 }
00062
00063 Folder* Folder::fromOPML(QDomElement e)
00064 {
00065 Folder* fg = new Folder(e.hasAttribute(QString::fromLatin1("text")) ? e.attribute(QString::fromLatin1("text")) : e.attribute(QString::fromLatin1("title")));
00066 fg->setOpen( e.attribute(QString::fromLatin1("isOpen")) != QString::fromLatin1(("false")));
00067 fg->setId( e.attribute(QString::fromLatin1("id")).toUInt() );
00068 return fg;
00069 }
00070
00071 Folder::Folder(const QString& title) : TreeNode(), d(new FolderPrivate)
00072 {
00073 d->unread = 0;
00074 setTitle(title);
00075 }
00076
00077 Folder::~Folder()
00078 {
00079 TreeNode* tmp = 0;
00080 for (QValueList<TreeNode*>::ConstIterator it = d->children.begin(); it != d->children.end(); ++it)
00081 {
00082 delete tmp;
00083 tmp = *it;
00084 }
00085 delete tmp;
00086
00087 emitSignalDestroyed();
00088
00089 delete d;
00090 d = 0;
00091 }
00092
00093 QStringList Folder::tags() const
00094 {
00095 QStringList t;
00096 QValueList<TreeNode*>::ConstIterator en = d->children.end();
00097 for (QValueList<TreeNode*>::ConstIterator it = d->children.begin(); it != en; ++it)
00098 {
00099
00100 QStringList t2 = (*it)->tags();
00101 for (QStringList::ConstIterator it2 = t2.begin(); it2 != t2.end(); ++it2)
00102 if (!t.contains(*it2))
00103 t.append(*it2);
00104 }
00105 return t;
00106 }
00107
00108 QValueList<Article> Folder::articles(const QString& tag)
00109 {
00110 QValueList<Article> seq;
00111 QValueList<TreeNode*>::ConstIterator en = d->children.end();
00112 for (QValueList<TreeNode*>::ConstIterator it = d->children.begin(); it != en; ++it)
00113 seq += (*it)->articles(tag);
00114
00115 return seq;
00116 }
00117
00118 QDomElement Folder::toOPML( QDomElement parent, QDomDocument document ) const
00119 {
00120 QDomElement el = document.createElement( "outline" );
00121 el.setAttribute( "text", title() );
00122 parent.appendChild( el );
00123 el.setAttribute("isOpen", d->open ? "true" : "false");
00124 el.setAttribute( "id", QString::number(id()) );
00125
00126 QValueList<TreeNode*>::ConstIterator en = d->children.end();
00127 for (QValueList<TreeNode*>::ConstIterator it = d->children.begin(); it != en; ++it)
00128 el.appendChild( (*it)->toOPML(el, document) );
00129
00130 return el;
00131 }
00132
00133 QValueList<TreeNode*> Folder::children() const
00134 {
00135 return d->children;
00136 }
00137
00138 void Folder::insertChild(TreeNode* node, TreeNode* after)
00139 {
00140 int pos = d->children.findIndex(after);
00141
00142 if (pos < 0)
00143 prependChild(node);
00144 else
00145 insertChild(pos+1, node);
00146 }
00147
00148 void Folder::insertChild(uint index, TreeNode* node)
00149 {
00150
00151 if (node)
00152 {
00153 if (index >= d->children.size())
00154 d->children.append(node);
00155 else
00156 d->children.insert(d->children.at(index), node);
00157 node->setParent(this);
00158 connectToNode(node);
00159 updateUnreadCount();
00160 emit signalChildAdded(node);
00161 d->addedArticlesNotify += node->articles();
00162 articlesModified();
00163 nodeModified();
00164 }
00165
00166 }
00167
00168 void Folder::appendChild(TreeNode* node)
00169 {
00170
00171 if (node)
00172 {
00173 d->children.append(node);
00174 node->setParent(this);
00175 connectToNode(node);
00176 updateUnreadCount();
00177 emit signalChildAdded(node);
00178 d->addedArticlesNotify += node->articles();
00179 articlesModified();
00180 nodeModified();
00181 }
00182
00183 }
00184
00185 void Folder::prependChild(TreeNode* node)
00186 {
00187
00188 if (node)
00189 {
00190 d->children.prepend(node);
00191 node->setParent(this);
00192 connectToNode(node);
00193 updateUnreadCount();
00194 emit signalChildAdded(node);
00195 d->addedArticlesNotify += node->articles();
00196 articlesModified();
00197 nodeModified();
00198 }
00199
00200 }
00201
00202 void Folder::removeChild(TreeNode* node)
00203 {
00204
00205 if (node && d->children.contains(node))
00206 {
00207 node->setParent(0);
00208 d->children.remove(node);
00209 disconnectFromNode(node);
00210 updateUnreadCount();
00211 emit signalChildRemoved(this, node);
00212 d->removedArticlesNotify += node->articles();
00213 articlesModified();
00214 nodeModified();
00215 }
00216
00217 }
00218
00219
00220 TreeNode* Folder::firstChild()
00221 {
00222 return d->children.isEmpty() ? 0 : d->children.first();
00223 }
00224
00225 TreeNode* Folder::lastChild()
00226 {
00227 return d->children.isEmpty() ? 0 : d->children.last();
00228 }
00229
00230 bool Folder::isOpen() const
00231 {
00232 return d->open;
00233 }
00234
00235 void Folder::setOpen(bool open)
00236 {
00237 d->open = open;
00238 }
00239
00240 int Folder::unread() const
00241 {
00242 return d->unread;
00243 }
00244
00245 int Folder::totalCount() const
00246 {
00247 int totalCount = 0;
00248
00249 QValueList<TreeNode*>::ConstIterator en = d->children.end();
00250 for (QValueList<TreeNode*>::ConstIterator it = d->children.begin(); it != en; ++it)
00251 totalCount += (*it)->totalCount();
00252
00253 return totalCount;
00254 }
00255
00256 void Folder::updateUnreadCount()
00257 {
00258 int unread = 0;
00259
00260 QValueList<TreeNode*>::ConstIterator en = d->children.end();
00261 for (QValueList<TreeNode*>::ConstIterator it = d->children.begin(); it != en; ++it)
00262 unread += (*it)->unread();
00263
00264 d->unread = unread;
00265 }
00266
00267 void Folder::slotMarkAllArticlesAsRead()
00268 {
00269 setNotificationMode(false);
00270 QValueList<TreeNode*>::ConstIterator en = d->children.end();
00271 for (QValueList<TreeNode*>::ConstIterator it = d->children.begin(); it != en; ++it)
00272 (*it)->slotMarkAllArticlesAsRead();
00273 setNotificationMode(true, true);
00274 }
00275
00276 void Folder::slotChildChanged(TreeNode* )
00277 {
00278 updateUnreadCount();
00279 nodeModified();
00280 }
00281
00282 void Folder::slotChildDestroyed(TreeNode* node)
00283 {
00284 d->children.remove(node);
00285 updateUnreadCount();
00286 nodeModified();
00287 }
00288
00289 void Folder::slotDeleteExpiredArticles()
00290 {
00291 setNotificationMode(false);
00292 QValueList<TreeNode*>::ConstIterator en = d->children.end();
00293 for (QValueList<TreeNode*>::ConstIterator it = d->children.begin(); it != en; ++it)
00294 (*it)->slotDeleteExpiredArticles();
00295 setNotificationMode(true, true);
00296 }
00297
00298 void Folder::slotAddToFetchQueue(FetchQueue* queue, bool intervalFetchOnly)
00299 {
00300 QValueList<TreeNode*>::ConstIterator en = d->children.end();
00301 for (QValueList<TreeNode*>::ConstIterator it = d->children.begin(); it != en; ++it)
00302 (*it)->slotAddToFetchQueue(queue, intervalFetchOnly);
00303 }
00304
00305 void Folder::doArticleNotification()
00306 {
00307 }
00308
00309 void Folder::connectToNode(TreeNode* child)
00310 {
00311 connect(child, SIGNAL(signalChanged(TreeNode*)), this, SLOT(slotChildChanged(TreeNode*)));
00312 connect(child, SIGNAL(signalDestroyed(TreeNode*)), this, SLOT(slotChildDestroyed(TreeNode*)));
00313 connect(child, SIGNAL(signalArticlesAdded(TreeNode*, const QValueList<Article>&)), this, SIGNAL(signalArticlesAdded(TreeNode*, const QValueList<Article>&)));
00314 connect(child, SIGNAL(signalArticlesRemoved(TreeNode*, const QValueList<Article>&)), this, SIGNAL(signalArticlesRemoved(TreeNode*, const QValueList<Article>&)));
00315 connect(child, SIGNAL(signalArticlesUpdated(TreeNode*, const QValueList<Article>&)), this, SIGNAL(signalArticlesUpdated(TreeNode*, const QValueList<Article>&)));
00316 }
00317
00318 void Folder::disconnectFromNode(TreeNode* child)
00319 {
00320 disconnect(child, SIGNAL(signalChanged(TreeNode*)), this, SLOT(slotChildChanged(TreeNode*)));
00321 disconnect(child, SIGNAL(signalDestroyed(TreeNode*)), this, SLOT(slotChildDestroyed(TreeNode*)));
00322 disconnect(child, SIGNAL(signalArticlesAdded(TreeNode*, const QValueList<Article>&)), this, SIGNAL(signalArticlesAdded(TreeNode*, const QValueList<Article>&)));
00323 disconnect(child, SIGNAL(signalArticlesRemoved(TreeNode*, const QValueList<Article>&)), this, SIGNAL(signalArticlesRemoved(TreeNode*, const QValueList<Article>&)));
00324 disconnect(child, SIGNAL(signalArticlesUpdated(TreeNode*, const QValueList<Article>&)), this, SIGNAL(signalArticlesUpdated(TreeNode*, const QValueList<Article>&)));
00325 }
00326
00327 TreeNode* Folder::next()
00328 {
00329 if ( firstChild() )
00330 return firstChild();
00331
00332 if ( nextSibling() )
00333 return nextSibling();
00334
00335 Folder* p = parent();
00336 while (p)
00337 {
00338 if ( p->nextSibling() )
00339 return p->nextSibling();
00340 else
00341 p = p->parent();
00342 }
00343 return 0;
00344 }
00345
00346 }
00347 #include "folder.moc"