(trunk qt) add code for a favicon cache -- it even shares the GTK+ client's favicon cache directory. :) This isn't plugged in anywhere yet, but will be useful when the filterbar and trackers tab are synced with the GTK+ client.
This commit is contained in:
parent
12feea7c42
commit
8034e06cf2
4
qt/app.h
4
qt/app.h
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <QApplication>
|
||||
#include <QTimer>
|
||||
#include "favicon.h"
|
||||
|
||||
class Prefs;
|
||||
class Session;
|
||||
|
@ -33,6 +34,9 @@ class MyApp: public QApplication
|
|||
public:
|
||||
void raise( );
|
||||
|
||||
public:
|
||||
Favicons favicons;
|
||||
|
||||
private:
|
||||
Prefs * myPrefs;
|
||||
Session * mySession;
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* This file Copyright (C) 2010 Mnemosyne LLC
|
||||
*
|
||||
* This file is licensed by the GPL version 2. Works owned by the
|
||||
* Transmission project are granted a special exemption to clause 2(b)
|
||||
* so that the bulk of its code can remain under the MIT license.
|
||||
* This exemption does not extend to derived works not owned by
|
||||
* the Transmission project.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QDesktopServices>
|
||||
#include <QDir>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
|
||||
#include "favicon.h"
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
QString
|
||||
Favicons :: getCacheDir( )
|
||||
{
|
||||
const QString base = QDesktopServices::storageLocation( QDesktopServices::CacheLocation );
|
||||
return QDir( base ).absoluteFilePath( "favicons" );
|
||||
};
|
||||
|
||||
|
||||
Favicons :: Favicons( )
|
||||
{
|
||||
myNAM = new QNetworkAccessManager( );
|
||||
connect( myNAM, SIGNAL(finished(QNetworkReply*)), this, SLOT(onRequestFinished(QNetworkReply*)) );
|
||||
}
|
||||
|
||||
Favicons :: ~Favicons( )
|
||||
{
|
||||
delete myNAM;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
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 )
|
||||
{
|
||||
ensureCacheDirHasBeenScanned( );
|
||||
|
||||
return myPixmaps[ getHost(url) ];
|
||||
}
|
||||
|
||||
void
|
||||
Favicons :: add( const QUrl& url_in )
|
||||
{
|
||||
ensureCacheDirHasBeenScanned( );
|
||||
|
||||
const QString host = getHost(url_in);
|
||||
if( !myPixmaps.contains(host) && !myPending.contains(host) )
|
||||
{
|
||||
const int IMAGE_TYPES = 4;
|
||||
const QString image_types[IMAGE_TYPES] = { "ico", "png", "gif", "jpg" };
|
||||
|
||||
myPending.append( host );
|
||||
for( int i=0; i<IMAGE_TYPES; ++i )
|
||||
{
|
||||
QString url( "http://" + host + "/favicon." + image_types[i]);
|
||||
myNAM->get( QNetworkRequest( url ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Favicons :: onRequestFinished( QNetworkReply * reply )
|
||||
{
|
||||
const QString host = reply->url().host();
|
||||
|
||||
myPending.removeAll( host );
|
||||
|
||||
const QByteArray content = reply->readAll( );
|
||||
|
||||
QPixmap pixmap;
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* This file Copyright (C) 2010 Mnemosyne LLC
|
||||
*
|
||||
* This file is licensed by the GPL version 2. Works owned by the
|
||||
* Transmission project are granted a special exemption to clause 2(b)
|
||||
* so that the bulk of its code can remain under the MIT license.
|
||||
* This exemption does not extend to derived works not owned by
|
||||
* the Transmission project.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef FAVICON_CACHE_H
|
||||
#define FAVICON_CACHE_H
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
class QUrl;
|
||||
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QObject>
|
||||
#include <QPixmap>
|
||||
|
||||
class Favicons: public QObject
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
|
||||
Favicons();
|
||||
virtual ~Favicons();
|
||||
|
||||
/* returns a cached pixmap, or a NULL pixmap if there's no match in the cache */
|
||||
QPixmap find( const QUrl& url );
|
||||
|
||||
/* this will emit a signal when (if) the icon becomes ready */
|
||||
void add( const QUrl& url );
|
||||
|
||||
signals:
|
||||
|
||||
void pixmapReady( const QString& host );
|
||||
|
||||
private:
|
||||
|
||||
QStringList myPending;
|
||||
QNetworkAccessManager * myNAM;
|
||||
QMap<QString,QPixmap> myPixmaps;
|
||||
|
||||
QString getHost( const QUrl& url );
|
||||
|
||||
QString getCacheDir( );
|
||||
|
||||
void ensureCacheDirHasBeenScanned( );
|
||||
|
||||
private slots:
|
||||
|
||||
void onRequestFinished( QNetworkReply * reply );
|
||||
};
|
||||
|
||||
#endif
|
13
qt/qtr.pro
13
qt/qtr.pro
|
@ -30,12 +30,13 @@ TRANSLATIONS += transmission_en.ts transmission_ru.ts
|
|||
|
||||
FORMS += mainwin.ui
|
||||
RESOURCES += application.qrc
|
||||
SOURCES += about.cc app.cc dbus-adaptor.cc details.cc file-tree.cc filters.cc \
|
||||
formatter.cc hig.cc license.cc mainwin.cc make-dialog.cc options.cc \
|
||||
prefs.cc prefs-dialog.cc qticonloader.cc relocate.cc session.cc \
|
||||
session-dialog.cc squeezelabel.cc stats-dialog.cc torrent.cc \
|
||||
torrent-delegate.cc torrent-delegate-min.cc torrent-filter.cc \
|
||||
torrent-model.cc triconpushbutton.cc utils.cc watchdir.cc
|
||||
SOURCES += about.cc app.cc dbus-adaptor.cc details.cc favicon.cc file-tree.cc \
|
||||
filters.cc formatter.cc hig.cc license.cc mainwin.cc \
|
||||
make-dialog.cc options.cc prefs.cc prefs-dialog.cc qticonloader.cc \
|
||||
relocate.cc session.cc session-dialog.cc squeezelabel.cc \
|
||||
stats-dialog.cc torrent.cc torrent-delegate.cc \
|
||||
torrent-delegate-min.cc torrent-filter.cc torrent-model.cc \
|
||||
triconpushbutton.cc utils.cc watchdir.cc
|
||||
HEADERS += $$replace(SOURCES, .cc, .h)
|
||||
HEADERS += speed.h types.h
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <QSet>
|
||||
#include <QString>
|
||||
#include <QStyle>
|
||||
#include <QUrl>
|
||||
#include <QVariant>
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
|
@ -543,9 +544,12 @@ Torrent :: update( tr_benc * d )
|
|||
int i = 0;
|
||||
QStringList list;
|
||||
tr_benc * child;
|
||||
while(( child = tr_bencListChild( trackers, i++ )))
|
||||
if( tr_bencDictFindStr( child, "announce", &str ))
|
||||
while(( child = tr_bencListChild( trackers, i++ ))) {
|
||||
if( tr_bencDictFindStr( child, "announce", &str )) {
|
||||
dynamic_cast<MyApp*>(QApplication::instance())->favicons.add( QUrl(str) );
|
||||
list.append( QString::fromUtf8( str ) );
|
||||
}
|
||||
}
|
||||
if( myValues[TRACKERS] != list ) {
|
||||
myValues[TRACKERS].setValue( list );
|
||||
changed = true;
|
||||
|
|
Loading…
Reference in New Issue