transmission/qt/favicon.cc

165 lines
3.5 KiB
C++
Raw Normal View History

/*
* 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 <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"
/***
****
***/
2013-09-14 22:45:04 +00:00
Favicons :: Favicons ()
{
2013-09-14 22:45:04 +00:00
myNAM = new QNetworkAccessManager ();
connect (myNAM, SIGNAL(finished(QNetworkReply*)), this, SLOT(onRequestFinished(QNetworkReply*)));
}
2013-09-14 22:45:04 +00:00
Favicons :: ~Favicons ()
{
2013-09-14 22:45:04 +00:00
delete myNAM;
}
/***
****
***/
QString
2013-09-14 22:45:04 +00:00
Favicons :: getCacheDir ()
{
2013-09-14 22:45:04 +00:00
const QString base =
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
2013-09-14 22:45:04 +00:00
QDesktopServices::storageLocation (QDesktopServices::CacheLocation);
#else
2013-09-14 22:45:04 +00:00
QStandardPaths::writableLocation (QStandardPaths::CacheLocation);
#endif
2013-09-14 22:45:04 +00:00
return QDir(base).absoluteFilePath ("favicons");
}
void
2013-09-14 22:45:04 +00:00
Favicons :: ensureCacheDirHasBeenScanned ()
{
2013-09-14 22:45:04 +00:00
static bool hasBeenScanned = false;
2013-09-14 22:45:04 +00:00
if (!hasBeenScanned)
{
2013-09-14 22:45:04 +00:00
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
2013-09-14 22:45:04 +00:00
Favicons :: getHost (const QUrl& url)
{
2013-09-14 22:45:04 +00:00
QString host = url.host ();
const int first_dot = host.indexOf ('.');
const int last_dot = host.lastIndexOf ('.');
2013-09-14 22:45:04 +00:00
if ((first_dot != -1) && (last_dot != -1) && (first_dot != last_dot))
host.remove (0, first_dot + 1);
2013-09-14 22:45:04 +00:00
return host;
}
QPixmap
2013-09-14 22:45:04 +00:00
Favicons :: find (const QUrl& url)
{
2013-09-14 22:45:04 +00:00
return findFromHost (getHost (url));
}
namespace
{
2013-09-14 22:45:04 +00:00
const QSize rightSize (16, 16);
};
QPixmap
2013-09-14 22:45:04 +00:00
Favicons :: findFromHost (const QString& host)
{
2013-09-14 22:45:04 +00:00
ensureCacheDirHasBeenScanned ();
2013-09-14 22:45:04 +00:00
const QPixmap pixmap = myPixmaps[ host ];
return pixmap.size()==rightSize ? pixmap : pixmap.scaled(rightSize);
}
void
2013-09-14 22:45:04 +00:00
Favicons :: add (const QUrl& url)
{
2013-09-14 22:45:04 +00:00
ensureCacheDirHasBeenScanned ();
2013-09-14 22:45:04 +00:00
const QString host = getHost (url);
2013-09-14 22:45:04 +00:00
if (!myPixmaps.contains (host))
{
2013-09-14 22:45:04 +00:00
// 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
2013-09-14 22:45:04 +00:00
Favicons :: onRequestFinished (QNetworkReply * reply)
{
2013-09-14 22:45:04 +00:00
const QString host = reply->url().host();
2013-09-14 22:45:04 +00:00
QPixmap pixmap;
2013-09-14 22:45:04 +00:00
const QByteArray content = reply->readAll ();
if (!reply->error ())
pixmap.loadFromData (content);
2013-09-14 22:45:04 +00:00
if (!pixmap.isNull ())
{
2013-09-14 22:45:04 +00:00
// 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);
}
}