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