akregator/src

feediconmanager.cpp
00001 /*
00002     This file is part of Akregator.
00003 
00004     Copyright (C) 2004 Sashmit Bhaduri <smt@vfemail.net>
00005                   2005 Frank Osterfeld <frank.osterfeld@kdemail.net>
00006 
00007     This program is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020 
00021     As a special exception, permission is given to link this program
00022     with any edition of TQt, and distribute the resulting executable,
00023     without including the source code for TQt in the source distribution.
00024 */
00025 
00026 #include "feed.h"
00027 #include "feediconmanager.h"
00028 
00029 #include <dcopclient.h>
00030 #include <kapplication.h>
00031 #include <kdebug.h>
00032 #include <kstandarddirs.h>
00033 #include <kstaticdeleter.h>
00034 #include <kurl.h>
00035 
00036 #include <tqdict.h>
00037 #include <tqpixmap.h>
00038 #include <tqvaluelist.h>
00039 
00040 namespace Akregator {
00041 
00042 class FeedIconManager::FeedIconManagerPrivate
00043 {
00044     public:
00045     TQValueList<Feed*> registeredFeeds;
00046     TQDict<Feed> urlDict;
00047 };
00048 
00049 FeedIconManager *FeedIconManager::m_instance = 0;
00050 
00051 static KStaticDeleter<FeedIconManager> feediconmanagersd;
00052 
00053 FeedIconManager* FeedIconManager::self()
00054 {
00055     if (!m_instance)
00056         m_instance = feediconmanagersd.setObject(m_instance, new FeedIconManager);
00057     return m_instance;
00058 }
00059 
00060 void FeedIconManager::fetchIcon(Feed* feed)
00061 {
00062     if (!d->registeredFeeds.contains(feed))
00063     {
00064         d->registeredFeeds.append(feed);
00065         connect(feed, TQT_SIGNAL(signalDestroyed(TreeNode*)), this, TQT_SLOT(slotFeedDestroyed(TreeNode*)));
00066     }
00067     TQString iconURL = getIconURL(KURL(feed->xmlUrl()));
00068     d->urlDict.insert(iconURL, feed);
00069     loadIcon(iconURL);
00070 }
00071 
00072 FeedIconManager::FeedIconManager(TQObject * parent, const char *name)
00073 :  TQObject(parent, name), DCOPObject("FeedIconManager"), d(new FeedIconManagerPrivate)
00074 {
00075     connectDCOPSignal("kded",
00076                       "favicons", "iconChanged(bool, TQString, TQString)",
00077                       "slotIconChanged(bool, TQString, TQString)", false);
00078 }
00079 
00080 
00081 FeedIconManager::~FeedIconManager()
00082 {
00083     delete d;
00084     d = 0;
00085 }
00086 
00087 void FeedIconManager::loadIcon(const TQString & url)
00088 {
00089     KURL u(url);
00090 
00091     TQString iconFile = iconLocation(u);
00092     
00093     if (iconFile.isNull())
00094     {
00095         TQByteArray data;
00096         TQDataStream ds(data, IO_WriteOnly);
00097         ds << u;
00098         kapp->dcopClient()->send("kded", "favicons", "downloadHostIcon(KURL)",
00099                                  data);
00100     }
00101     else
00102         slotIconChanged(false, url, iconFile);
00103 
00104 }
00105 
00106 TQString FeedIconManager::getIconURL(const KURL& url)
00107 {
00108     return "http://" +url.host() + "/";
00109 }
00110 
00111 TQString FeedIconManager::iconLocation(const KURL & url) const
00112 {
00113     TQByteArray data, reply;
00114     TQCString replyType;
00115     TQDataStream ds(data, IO_WriteOnly);
00116 
00117     ds << url;
00118 
00119     kapp->dcopClient()->call("kded", "favicons", "iconForURL(KURL)", data,
00120                              replyType, reply);
00121 
00122     if (replyType == TQSTRING_OBJECT_NAME_STRING) {
00123         TQDataStream replyStream(reply, IO_ReadOnly);
00124         TQString result;
00125         replyStream >> result;
00126         return result;
00127     }
00128 
00129     return TQString();
00130 }
00131 
00132 void FeedIconManager::slotFeedDestroyed(TreeNode* node)
00133 {
00134     Feed* feed = dynamic_cast<Feed*>(node);
00135     if (feed)
00136         while (d->registeredFeeds.contains(feed))
00137             d->registeredFeeds.remove(d->registeredFeeds.find(feed));
00138 }
00139 
00140 void FeedIconManager::slotIconChanged(bool /*isHost*/, const TQString& hostOrURL,
00141                                   const TQString& iconName)
00142 {
00143     TQString iconFile = KGlobal::dirs()->findResource("cache",
00144                                  iconName+".png");
00145     Feed* f;
00146     TQPixmap p = TQPixmap(iconFile);
00147     if (!p.isNull()) // we don't set null pixmaps, as feed checks pixmap.isNull() to find out whether the icon was already loaded or not. It would request the icon another time, resulting an infinite loop (until stack overflow that is
00148     {
00149         while (( f = d->urlDict.take(hostOrURL) ))
00150             if (d->registeredFeeds.contains(f))
00151                 f->setFavicon(p);
00152     }
00153     emit signalIconChanged(hostOrURL, iconFile);
00154 }
00155 
00156 } // namespace Akregator
00157 #include "feediconmanager.moc"