/* * This file Copyright (C) 2010-2014 Mnemosyne LLC * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * * $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); } }