/* * This file Copyright (C) 2012-2014 Mnemosyne LLC * * It may be used under the GNU GPL versions 2 or 3 * or any future license endorsed by Mnemosyne LLC. * * $Id$ */ #include #include #include #include #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #include #else #include #endif #include "favicon.h" /*** **** ***/ Favicons::Favicons () { myNAM = new QNetworkAccessManager (); connect (myNAM, SIGNAL(finished(QNetworkReply*)), this, SLOT(onRequestFinished(QNetworkReply*))); } Favicons::~Favicons () { delete myNAM; } /*** **** ***/ QString Favicons::getCacheDir () { const QString base = #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) QDesktopServices::storageLocation (QDesktopServices::CacheLocation); #else QStandardPaths::writableLocation (QStandardPaths::CacheLocation); #endif return QDir(base).absoluteFilePath ("favicons"); } void Favicons::ensureCacheDirHasBeenScanned () { static bool hasBeenScanned = false; if (!hasBeenScanned) { hasBeenScanned = true; QDir cacheDir (getCacheDir ()); cacheDir.mkpath (cacheDir.absolutePath ()); QStringList files = cacheDir.entryList (QDir::Files|QDir::Readable); foreach (QString file, files) { QPixmap pixmap; pixmap.load (cacheDir.absoluteFilePath (file)); if (!pixmap.isNull ()) myPixmaps.insert (file, pixmap); } } } QString Favicons::getHost (const QUrl& url) { QString host = url.host (); const int first_dot = host.indexOf ('.'); const int last_dot = host.lastIndexOf ('.'); if ((first_dot != -1) && (last_dot != -1) && (first_dot != last_dot)) host.remove (0, first_dot + 1); return host; } QPixmap Favicons::find (const QUrl& url) { return findFromHost (getHost (url)); } namespace { const QSize rightSize (16, 16); }; QPixmap Favicons::findFromHost (const QString& host) { ensureCacheDirHasBeenScanned (); const QPixmap pixmap = myPixmaps[ host ]; return pixmap.size()==rightSize ? pixmap : pixmap.scaled(rightSize); } void Favicons::add (const QUrl& url) { ensureCacheDirHasBeenScanned (); const QString host = getHost (url); if (!myPixmaps.contains (host)) { // add a placholder s.t. we only ping the server once per session QPixmap tmp (rightSize); tmp.fill (Qt::transparent); myPixmaps.insert (host, tmp); // try to download the favicon const QString path = "http://" + host + "/favicon."; QStringList suffixes; suffixes << "ico" << "png" << "gif" << "jpg"; foreach (QString suffix, suffixes) myNAM->get (QNetworkRequest (path + suffix)); } } void Favicons::onRequestFinished (QNetworkReply * reply) { const QString host = reply->url().host(); QPixmap pixmap; const QByteArray content = reply->readAll (); if (!reply->error ()) pixmap.loadFromData (content); if (!pixmap.isNull ()) { // save it in memory... myPixmaps.insert (host, pixmap); // save it on disk... QDir cacheDir (getCacheDir ()); cacheDir.mkpath (cacheDir.absolutePath ()); QFile file (cacheDir.absoluteFilePath (host)); file.open (QIODevice::WriteOnly); file.write (content); file.close (); // notify listeners emit pixmapReady (host); } }