164 lines
3.6 KiB
C++
164 lines
3.6 KiB
C++
/*
|
|
* This file Copyright (C) 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"
|
|
|
|
/***
|
|
****
|
|
***/
|
|
|
|
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 );
|
|
}
|
|
}
|