akregator/src
feedlist.cpp00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "feedlist.h"
00025
00026 #include <tqdatetime.h>
00027 #include <tqdom.h>
00028 #include <tqmap.h>
00029 #include <tqvaluelist.h>
00030
00031 #include <kdebug.h>
00032 #include <tdelocale.h>
00033
00034 #include "article.h"
00035 #include "feed.h"
00036 #include "folder.h"
00037 #include "treenode.h"
00038 #include "treenodevisitor.h"
00039
00040 namespace Akregator {
00041
00042 class FeedList::FeedListPrivate
00043 {
00044 public:
00045
00046 TQMap<TQString, TQValueList<Feed*> > urlMap;
00047 AddNodeVisitor* addNodeVisitor;
00048 RemoveNodeVisitor* removeNodeVisitor;
00049 };
00050
00051 class FeedList::AddNodeVisitor : public TreeNodeVisitor
00052 {
00053 public:
00054 AddNodeVisitor(FeedList* list) : m_list(list) {}
00055 virtual ~AddNodeVisitor() {}
00056
00057
00058 virtual bool visitFeed(Feed* node)
00059 {
00060 m_list->idMap()->insert(node->id(), node);
00061 m_list->flatList()->append(node);
00062 return true;
00063 }
00064
00065 private:
00066 FeedList* m_list;
00067 };
00068
00069 class FeedList::RemoveNodeVisitor : public TreeNodeVisitor
00070 {
00071 public:
00072 RemoveNodeVisitor(FeedList* list) : m_list(list) {}
00073 virtual ~RemoveNodeVisitor() {}
00074
00075 virtual bool visitFeed(Feed* node)
00076 {
00077 m_list->d->urlMap[node->xmlUrl()].remove(node);
00078 return true;
00079 }
00080
00081 private:
00082 FeedList* m_list;
00083 };
00084
00085 FeedList::FeedList(TQObject *parent, const char *name)
00086 : NodeList(parent, name), d(new FeedListPrivate)
00087 {
00088 d->addNodeVisitor = new AddNodeVisitor(this);
00089 d->removeNodeVisitor = new RemoveNodeVisitor(this);
00090
00091 Folder* rootNode = new Folder(i18n("All Feeds"));
00092 rootNode->setId(1);
00093 setRootNode(rootNode);
00094 addNode(rootNode, true);
00095 }
00096
00097 void FeedList::addNode(TreeNode* node, bool preserveID)
00098 {
00099 NodeList::addNode(node, preserveID);
00100 d->addNodeVisitor->visit(node);
00101 }
00102
00103 void FeedList::removeNode(TreeNode* node)
00104 {
00105 NodeList::removeNode(node);
00106 d->removeNodeVisitor->visit(node);
00107 }
00108
00109 void FeedList::parseChildNodes(TQDomNode &node, Folder* parent)
00110 {
00111 TQDomElement e = node.toElement();
00112
00113 if( !e.isNull() )
00114 {
00115 TQString title = e.hasAttribute("text") ? e.attribute("text") : e.attribute("title");
00116
00117 if (e.hasAttribute("xmlUrl") || e.hasAttribute("xmlurl") || e.hasAttribute("xmlURL") )
00118 {
00119 Feed* feed = Feed::fromOPML(e);
00120 if (feed)
00121 {
00122 if (!d->urlMap[feed->xmlUrl()].contains(feed))
00123 d->urlMap[feed->xmlUrl()].append(feed);
00124 parent->appendChild(feed);
00125 }
00126 }
00127 else
00128 {
00129 Folder* fg = Folder::fromOPML(e);
00130 parent->appendChild(fg);
00131
00132 if (e.hasChildNodes())
00133 {
00134 TQDomNode child = e.firstChild();
00135 while(!child.isNull())
00136 {
00137 parseChildNodes(child, fg);
00138 child = child.nextSibling();
00139 }
00140 }
00141 }
00142 }
00143 }
00144
00145 bool FeedList::readFromXML(const TQDomDocument& doc)
00146 {
00147 TQDomElement root = doc.documentElement();
00148
00149 kdDebug() << "loading OPML feed " << root.tagName().lower() << endl;
00150
00151 kdDebug() << "measuring startup time: START" << endl;
00152 TQTime spent;
00153 spent.start();
00154
00155 if (root.tagName().lower() != "opml")
00156 {
00157 return false;
00158 }
00159 TQDomNode bodyNode = root.firstChild();
00160
00161 while (!bodyNode.isNull() && bodyNode.toElement().tagName().lower() != "body")
00162 bodyNode = bodyNode.nextSibling();
00163
00164
00165 if (bodyNode.isNull())
00166 {
00167 kdDebug() << "Failed to acquire body node, markup broken?" << endl;
00168 return false;
00169 }
00170
00171 TQDomElement body = bodyNode.toElement();
00172
00173 TQDomNode i = body.firstChild();
00174
00175 while( !i.isNull() )
00176 {
00177 parseChildNodes(i, rootNode());
00178 i = i.nextSibling();
00179 }
00180
00181 for (TreeNode* i = rootNode()->firstChild(); i && i != rootNode(); i = i->next() )
00182 if (i->id() == 0)
00183 {
00184 uint id = generateID();
00185 i->setId(id);
00186 idMap()->insert(id, i);
00187 }
00188
00189 kdDebug() << "measuring startup time: STOP, " << spent.elapsed() << "ms" << endl;
00190 kdDebug() << "Number of articles loaded: " << rootNode()->totalCount() << endl;
00191 return true;
00192 }
00193
00194 FeedList::~FeedList()
00195 {
00196 emit signalDestroyed(this);
00197 setRootNode(0);
00198 delete d->addNodeVisitor;
00199 delete d->removeNodeVisitor;
00200 delete d;
00201 d = 0;
00202 }
00203
00204 Feed* FeedList::findByURL(const TQString& feedURL) const
00205 {
00206 if (d->urlMap[feedURL].isEmpty())
00207 return 0;
00208 else
00209 return *(d->urlMap[feedURL].begin());
00210 }
00211
00212 Article FeedList::findArticle(const TQString& feedURL, const TQString& guid) const
00213 {
00214 Feed* feed = findByURL(feedURL);
00215
00216 return feed ? feed->findArticle(guid) : Article();
00217 }
00218
00219 void FeedList::append(FeedList* list, Folder* parent, TreeNode* after)
00220 {
00221 if ( list == this )
00222 return;
00223
00224 if ( !flatList()->contains(parent) )
00225 parent = rootNode();
00226
00227 TQValueList<TreeNode*> children = list->rootNode()->children();
00228
00229 TQValueList<TreeNode*>::ConstIterator end( children.end() );
00230 for (TQValueList<TreeNode*>::ConstIterator it = children.begin(); it != end; ++it)
00231 {
00232 list->rootNode()->removeChild(*it);
00233 parent->insertChild(*it, after);
00234 after = *it;
00235 }
00236 }
00237
00238 TQDomDocument FeedList::toXML() const
00239 {
00240 TQDomDocument doc;
00241 doc.appendChild( doc.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) );
00242
00243 TQDomElement root = doc.createElement( "opml" );
00244 root.setAttribute( "version", "1.0" );
00245 doc.appendChild( root );
00246
00247 TQDomElement head = doc.createElement( "head" );
00248 root.appendChild( head );
00249
00250 TQDomElement ti = doc.createElement( "text" );
00251 head.appendChild( ti );
00252
00253 TQDomText t = doc.createTextNode( title() );
00254 ti.appendChild( t );
00255
00256 TQDomElement body = doc.createElement( "body" );
00257 root.appendChild( body );
00258
00259 TQValueList<TreeNode*> children = rootNode()->children();
00260
00261 TQValueList<TreeNode*>::ConstIterator end( children.end() );
00262
00263 for (TQValueList<TreeNode*>::ConstIterator it = children.begin(); it != end; ++it)
00264 body.appendChild( (*it)->toOPML(body, doc) );
00265
00266 return doc;
00267 }
00268
00269 }
00270 #include "feedlist.moc"
|