160 lines
3.3 KiB
C++
160 lines
3.3 KiB
C++
/*
|
|
* 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 <QDir>
|
|
#include <QNetworkAccessManager>
|
|
#include <QNetworkReply>
|
|
#include <QNetworkRequest>
|
|
|
|
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
|
#include <QDesktopServices>
|
|
#else
|
|
#include <QStandardPaths>
|
|
#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.isNull () || 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
|
|
myPixmaps.insert (host, QPixmap ());
|
|
|
|
// 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);
|
|
}
|
|
}
|