/* This file is part of Akregator. Copyright (C) 2004 Stanislav Karchebny 2004-2005 Frank Osterfeld 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 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. As a special exception, permission is given to link this program with any edition of TQt, and distribute the resulting executable, without including the source code for TQt in the source distribution. */ #include "article.h" #include "folder.h" #include "fetchqueue.h" #include "treenodevisitor.h" #include #include #include #include #include namespace Akregator { class Folder::FolderPrivate { public: /** List of tqchildren */ TQValueList tqchildren; /** caching unread count of tqchildren */ int unread; /** whether or not the folder is expanded */ bool open; /** caches guids for notifying added articles */ TQValueList
addedArticlesNotify; /** caches guids for notifying removed articles */ TQValueList
removedArticlesNotify; }; bool Folder::accept(TreeNodeVisitor* visitor) { if (visitor->visitFolder(this)) return true; else return visitor->visitTreeNode(this); } Folder* Folder::fromOPML(TQDomElement e) { Folder* fg = new Folder(e.hasAttribute(TQString::tqfromLatin1("text")) ? e.attribute(TQString::tqfromLatin1("text")) : e.attribute(TQString::tqfromLatin1("title"))); fg->setOpen( e.attribute(TQString::tqfromLatin1("isOpen")) != TQString::tqfromLatin1(("false"))); fg->setId( e.attribute(TQString::tqfromLatin1("id")).toUInt() ); return fg; } Folder::Folder(const TQString& title) : TreeNode(), d(new FolderPrivate) { d->unread = 0; setTitle(title); } Folder::~Folder() { TreeNode* tmp = 0; for (TQValueList::ConstIterator it = d->tqchildren.begin(); it != d->tqchildren.end(); ++it) { delete tmp; tmp = *it; } delete tmp; emitSignalDestroyed(); delete d; d = 0; } TQStringList Folder::tags() const { TQStringList t; TQValueList::ConstIterator en = d->tqchildren.end(); for (TQValueList::ConstIterator it = d->tqchildren.begin(); it != en; ++it) { // intersect tag sets instead of appending lists, to avoid dupes. This sucks. Definitely. I want TQSet. Now. TQStringList t2 = (*it)->tags(); for (TQStringList::ConstIterator it2 = t2.begin(); it2 != t2.end(); ++it2) if (!t.contains(*it2)) t.append(*it2); } return t; } TQValueList
Folder::articles(const TQString& tag) { TQValueList
seq; TQValueList::ConstIterator en = d->tqchildren.end(); for (TQValueList::ConstIterator it = d->tqchildren.begin(); it != en; ++it) seq += (*it)->articles(tag); return seq; } TQDomElement Folder::toOPML( TQDomElement tqparent, TQDomDocument document ) const { TQDomElement el = document.createElement( "outline" ); el.setAttribute( "text", title() ); tqparent.appendChild( el ); el.setAttribute("isOpen", d->open ? "true" : "false"); el.setAttribute( "id", TQString::number(id()) ); TQValueList::ConstIterator en = d->tqchildren.end(); for (TQValueList::ConstIterator it = d->tqchildren.begin(); it != en; ++it) el.appendChild( (*it)->toOPML(el, document) ); return el; } TQValueList Folder::tqchildren() const { return d->tqchildren; } void Folder::insertChild(TreeNode* node, TreeNode* after) { int pos = d->tqchildren.findIndex(after); if (pos < 0) prependChild(node); else insertChild(pos+1, node); } void Folder::insertChild(uint index, TreeNode* node) { // kdDebug() << "enter Folder::insertChild(int, node) " << node->title() << endl; if (node) { if (index >= d->tqchildren.size()) d->tqchildren.append(node); else d->tqchildren.insert(d->tqchildren.at(index), node); node->setParent(this); connectToNode(node); updateUnreadCount(); emit signalChildAdded(node); d->addedArticlesNotify += node->articles(); articlesModified(); nodeModified(); } // kdDebug() << "leave Folder::insertChild(int, node) " << node->title() << endl; } void Folder::appendChild(TreeNode* node) { // kdDebug() << "enter Folder::appendChild() " << node->title() << endl; if (node) { d->tqchildren.append(node); node->setParent(this); connectToNode(node); updateUnreadCount(); emit signalChildAdded(node); d->addedArticlesNotify += node->articles(); articlesModified(); nodeModified(); } // kdDebug() << "leave Folder::appendChild() " << node->title() << endl; } void Folder::prependChild(TreeNode* node) { // kdDebug() << "enter Folder::prependChild() " << node->title() << endl; if (node) { d->tqchildren.prepend(node); node->setParent(this); connectToNode(node); updateUnreadCount(); emit signalChildAdded(node); d->addedArticlesNotify += node->articles(); articlesModified(); nodeModified(); } // kdDebug() << "leave Folder::prependChild() " << node->title() << endl; } void Folder::removeChild(TreeNode* node) { // kdDebug() << "enter Folder::removeChild() node:" << (node ? node->title() : "null") << endl; if (node && d->tqchildren.contains(node)) { node->setParent(0); d->tqchildren.remove(node); disconnectFromNode(node); updateUnreadCount(); emit signalChildRemoved(this, node); d->removedArticlesNotify += node->articles(); articlesModified(); // articles were removed, TODO: add guids to a list nodeModified(); } // kdDebug() << "leave Folder::removeChild() node: " << (node ? node->title() : "null") << endl; } TreeNode* Folder::firstChild() { return d->tqchildren.isEmpty() ? 0 : d->tqchildren.first(); } TreeNode* Folder::lastChild() { return d->tqchildren.isEmpty() ? 0 : d->tqchildren.last(); } bool Folder::isOpen() const { return d->open; } void Folder::setOpen(bool open) { d->open = open; } int Folder::unread() const { return d->unread; } int Folder::totalCount() const { int totalCount = 0; TQValueList::ConstIterator en = d->tqchildren.end(); for (TQValueList::ConstIterator it = d->tqchildren.begin(); it != en; ++it) totalCount += (*it)->totalCount(); return totalCount; } void Folder::updateUnreadCount() { int unread = 0; TQValueList::ConstIterator en = d->tqchildren.end(); for (TQValueList::ConstIterator it = d->tqchildren.begin(); it != en; ++it) unread += (*it)->unread(); d->unread = unread; } void Folder::slotMarkAllArticlesAsRead() { setNotificationMode(false); TQValueList::ConstIterator en = d->tqchildren.end(); for (TQValueList::ConstIterator it = d->tqchildren.begin(); it != en; ++it) (*it)->slotMarkAllArticlesAsRead(); setNotificationMode(true, true); } void Folder::slotChildChanged(TreeNode* /*node*/) { updateUnreadCount(); nodeModified(); } void Folder::slotChildDestroyed(TreeNode* node) { d->tqchildren.remove(node); updateUnreadCount(); nodeModified(); } void Folder::slotDeleteExpiredArticles() { setNotificationMode(false); TQValueList::ConstIterator en = d->tqchildren.end(); for (TQValueList::ConstIterator it = d->tqchildren.begin(); it != en; ++it) (*it)->slotDeleteExpiredArticles(); setNotificationMode(true, true); } void Folder::slotAddToFetchQueue(FetchQueue* queue, bool intervalFetchOnly) { TQValueList::ConstIterator en = d->tqchildren.end(); for (TQValueList::ConstIterator it = d->tqchildren.begin(); it != en; ++it) (*it)->slotAddToFetchQueue(queue, intervalFetchOnly); } void Folder::doArticleNotification() { } void Folder::connectToNode(TreeNode* child) { connect(child, TQT_SIGNAL(signalChanged(TreeNode*)), this, TQT_SLOT(slotChildChanged(TreeNode*))); connect(child, TQT_SIGNAL(signalDestroyed(TreeNode*)), this, TQT_SLOT(slotChildDestroyed(TreeNode*))); connect(child, TQT_SIGNAL(signalArticlesAdded(TreeNode*, const TQValueList
&)), this, TQT_SIGNAL(signalArticlesAdded(TreeNode*, const TQValueList
&))); connect(child, TQT_SIGNAL(signalArticlesRemoved(TreeNode*, const TQValueList
&)), this, TQT_SIGNAL(signalArticlesRemoved(TreeNode*, const TQValueList
&))); connect(child, TQT_SIGNAL(signalArticlesUpdated(TreeNode*, const TQValueList
&)), this, TQT_SIGNAL(signalArticlesUpdated(TreeNode*, const TQValueList
&))); } void Folder::disconnectFromNode(TreeNode* child) { disconnect(child, TQT_SIGNAL(signalChanged(TreeNode*)), this, TQT_SLOT(slotChildChanged(TreeNode*))); disconnect(child, TQT_SIGNAL(signalDestroyed(TreeNode*)), this, TQT_SLOT(slotChildDestroyed(TreeNode*))); disconnect(child, TQT_SIGNAL(signalArticlesAdded(TreeNode*, const TQValueList
&)), this, TQT_SIGNAL(signalArticlesAdded(TreeNode*, const TQValueList
&))); disconnect(child, TQT_SIGNAL(signalArticlesRemoved(TreeNode*, const TQValueList
&)), this, TQT_SIGNAL(signalArticlesRemoved(TreeNode*, const TQValueList
&))); disconnect(child, TQT_SIGNAL(signalArticlesUpdated(TreeNode*, const TQValueList
&)), this, TQT_SIGNAL(signalArticlesUpdated(TreeNode*, const TQValueList
&))); } TreeNode* Folder::next() { if ( firstChild() ) return firstChild(); if ( nextSibling() ) return nextSibling(); Folder* p = tqparent(); while (p) { if ( p->nextSibling() ) return p->nextSibling(); else p = p->tqparent(); } return 0; } } // namespace Akregator #include "folder.moc"