Merge pull request #3186 from glassez/geoip

New GeoIP manager.
This commit is contained in:
sledgehammer999
2015-07-22 23:59:00 +03:00
41 changed files with 1476 additions and 548 deletions

View File

@@ -135,7 +135,7 @@ void AddNewTorrentDialog::show(QString source, QWidget *parent)
if (Utils::Misc::isUrl(source)) {
// Launch downloader
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, 10485760 /* 10MB */);
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, true, 10485760 /* 10MB */, true);
connect(handler, SIGNAL(downloadFinished(QString, QString)), dlg, SLOT(handleDownloadFinished(QString, QString)));
connect(handler, SIGNAL(downloadFailed(QString, QString)), dlg, SLOT(handleDownloadFailed(QString, QString)));
connect(handler, SIGNAL(redirectedToMagnet(QString, QString)), dlg, SLOT(handleRedirectedToMagnet(QString, QString)));

View File

@@ -1,12 +0,0 @@
If you wish to embed GeoIP database into qBittorrent executable, please download put GeoIP.dat in this folder.
GeoIP Database can be downloaded from here:
* http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
Note that the database should be uncompressed.
Embedding GeoIP database into qBittorrent executable is advised for:
* Windows
* Mac OS X
* Linux distributions that don't provide GeoIP database in a separate package
On Linux operating system, since this is not the default behavior, you also need to pass --with-geoip-database-embedded parameter to the configure file.

View File

@@ -1,19 +0,0 @@
INCLUDEPATH += $$PWD
HEADERS += $$PWD/geoipmanager.h
SOURCES += $$PWD/geoipmanager.cpp
# Add GeoIP resource file if the GeoIP database
# should be embedded in qBittorrent executable
contains(DEFINES, WITH_GEOIP_EMBEDDED) {
exists("GeoIP.dat") {
message("GeoIP.dat was found in src/gui/geoip/.")
RESOURCES += $$PWD/geoip.qrc
} else {
DEFINES -= WITH_GEOIP_EMBEDDED
error("GeoIP.dat was not found in src/gui/geoip/ folder, please follow instructions in src/gui/geoip/README.")
}
} else {
message("GeoIP database will not be embedded in qBittorrent executable.")
}

View File

@@ -1,5 +0,0 @@
<RCC>
<qresource prefix="/geoip">
<file>GeoIP.dat</file>
</qresource>
</RCC>

View File

@@ -1,203 +0,0 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*
* Contact : chris@qbittorrent.org
*/
#include "geoipmanager.h"
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*
* Contact : chris@qbittorrent.org
*/
#include <QDir>
#include <QFile>
#include <QChar>
#include "core/utils/fs.h"
#include <libtorrent/session.hpp>
using namespace libtorrent;
QString GeoIPManager::geoipFolder(bool embedded) {
#ifdef WITH_GEOIP_EMBEDDED
if (embedded)
return ":/geoip/";
return Utils::Fs::QDesktopServicesDataLocation()+"geoip"+"/";
#else
Q_UNUSED(embedded);
if (QFile::exists("/usr/local/share/GeoIP/GeoIP.dat"))
return "/usr/local/share/GeoIP/";
if (QFile::exists("/var/lib/GeoIP/GeoIP.dat"))
return "/var/lib/GeoIP/";
return "/usr/share/GeoIP/";
#endif
}
QString GeoIPManager::geoipDBpath(bool embedded) {
return geoipFolder(embedded)+"GeoIP.dat";
}
#ifdef WITH_GEOIP_EMBEDDED
void GeoIPManager::exportEmbeddedDb() {
if (!QFile::exists(geoipDBpath(false)) || QFile(geoipDBpath(false)).size() != QFile(geoipDBpath(true)).size()) { // Export is required
qDebug("A local Geoip database update is required, proceeding...");
// Create geoip folder is necessary
QDir gfolder(geoipFolder(false));
if (!gfolder.exists()) {
if (!gfolder.mkpath(geoipFolder(false))) {
std::cerr << "Failed to create geoip folder at " << qPrintable(geoipFolder(false)) << std::endl;
return;
}
}
// Remove destination files
if (QFile::exists(geoipDBpath(false)))
Utils::Fs::forceRemove(geoipDBpath(false));
// Copy from executable to hard disk
qDebug("%s -> %s", qPrintable(geoipDBpath(true)), qPrintable(geoipDBpath(false)));
if (!QFile::copy(geoipDBpath(true), geoipDBpath(false))) {
std::cerr << "ERROR: Failed to copy geoip.dat from executable to hard disk" << std::endl;
}
qDebug("Local Geoip database was updated");
}
}
#endif
void GeoIPManager::loadDatabase(session *s) {
#ifdef WITH_GEOIP_EMBEDDED
exportEmbeddedDb();
#endif
if (QFile::exists(geoipDBpath(false))) {
qDebug("Loading GeoIP database from %s...", qPrintable(geoipDBpath(false)));
s->load_country_db(geoipDBpath(false).toLocal8Bit().constData());
} else {
qDebug("ERROR: Impossible to find local Geoip Database");
}
}
const char country_code[253][3] =
{ "--","AP","EU","AD","AE","AF","AG","AI","AL","AM","AN",
"AO","AQ","AR","AS","AT","AU","AW","AZ","BA","BB",
"BD","BE","BF","BG","BH","BI","BJ","BM","BN","BO",
"BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD",
"CF","CG","CH","CI","CK","CL","CM","CN","CO","CR",
"CU","CV","CX","CY","CZ","DE","DJ","DK","DM","DO",
"DZ","EC","EE","EG","EH","ER","ES","ET","FI","FJ",
"FK","FM","FO","FR","FX","GA","GB","GD","GE","GF",
"GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT",
"GU","GW","GY","HK","HM","HN","HR","HT","HU","ID",
"IE","IL","IN","IO","IQ","IR","IS","IT","JM","JO",
"JP","KE","KG","KH","KI","KM","KN","KP","KR","KW",
"KY","KZ","LA","LB","LC","LI","LK","LR","LS","LT",
"LU","LV","LY","MA","MC","MD","MG","MH","MK","ML",
"MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV",
"MW","MX","MY","MZ","NA","NC","NE","NF","NG","NI",
"NL","NO","NP","NR","NU","NZ","OM","PA","PE","PF",
"PG","PH","PK","PL","PM","PN","PR","PS","PT","PW",
"PY","QA","RE","RO","RU","RW","SA","SB","SC","SD",
"SE","SG","SH","SI","SJ","SK","SL","SM","SN","SO",
"SR","ST","SV","SY","SZ","TC","TD","TF","TG","TH",
"TJ","TK","TM","TN","TO","TL","TR","TT","TV","TW",
"TZ","UA","UG","UM","US","UY","UZ","VA","VC","VE",
"VG","VI","VN","VU","WF","WS","YE","YT","RS","ZA",
"ZM","ME","ZW","A1","A2","O1","AX","GG","IM","JE",
"BL","MF"};
static const uint num_countries = (unsigned)(sizeof(country_code)/sizeof(country_code[0]));
const char * country_name[253] =
{"N/A","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Netherlands Antilles",
"Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados",
"Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia",
"Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the",
"Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica",
"Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic",
"Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji",
"Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","France, Metropolitan","Gabon","United Kingdom","Grenada","Georgia","French Guiana",
"Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala",
"Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia",
"Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan",
"Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait",
"Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania",
"Luxembourg","Latvia","Libyan Arab Jamahiriya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali",
"Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives",
"Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua",
"Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia",
"Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau",
"Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan",
"Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname",
"Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand",
"Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan",
"Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines","Venezuela",
"Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa",
"Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey",
"Saint Barthelemy","Saint Martin"};
QString GeoIPManager::CountryISOCodeToName(const QString &iso) {
if (iso.isEmpty()) return "N/A";
for (uint i = 0; i < num_countries; ++i) {
if (iso == country_code[i]) {
return QLatin1String(country_name[i]);
}
}
qDebug("GeoIPManager: Country name resolution failed for: %s", qPrintable(iso));
return "N/A";
}
// http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
QIcon GeoIPManager::CountryISOCodeToIcon(const QString &iso) {
if (iso.isEmpty() || (iso[0] == '!')) return QIcon();
return QIcon(":/icons/flags/" + iso.toLower() + ".png");
}

View File

@@ -1,58 +0,0 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*
* Contact : chris@qbittorrent.org
*/
#ifndef GEOIPMANAGER_H
#define GEOIPMANAGER_H
#include <QString>
#include <QIcon>
namespace libtorrent {
class session;
}
class GeoIPManager : public QObject {
Q_OBJECT
public:
static void loadDatabase(libtorrent::session *s);
static QIcon CountryISOCodeToIcon(const QString &iso);
static QString CountryISOCodeToName(const QString &iso);
private:
static QString geoipFolder(bool embedded=false);
static QString geoipDBpath(bool embedded=false);
#ifdef WITH_GEOIP_EMBEDDED
static void exportEmbeddedDb();
#endif
};
#endif // GEOIP_H

View File

@@ -3,7 +3,6 @@ INCLUDEPATH += $$PWD
include(lineedit/lineedit.pri)
include(properties/properties.pri)
include(rss/rss.pri)
include(geoip/geoip.pri)
include(powermanagement/powermanagement.pri)
unix:!macx:dbus: include(qtnotify/qtnotify.pri)

View File

@@ -68,6 +68,12 @@ QIcon GuiIconProvider::getIcon(const QString &iconId)
return QIcon(IconProvider::getIconPath(iconId));
}
QIcon GuiIconProvider::getFlagIcon(const QString &countryIsoCode)
{
if (countryIsoCode.isEmpty()) return QIcon();
return QIcon(":/icons/flags/" + countryIsoCode.toLower() + ".png");
}
// Makes sure the icon is at least available in 16px and 24px size
// It scales the icon from the theme if necessary
// Otherwise, the UI looks broken if the icon is not available

View File

@@ -44,6 +44,7 @@ public:
static GuiIconProvider *instance();
QIcon getIcon(const QString &iconId);
QIcon getFlagIcon(const QString &countryIsoCode);
QString getIconPath(const QString &iconId);
private slots:

View File

@@ -1626,7 +1626,7 @@ void MainWindow::installPython()
{
setCursor(QCursor(Qt::WaitCursor));
// Download python
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl("https://www.python.org/ftp/python/3.4.3/python-3.4.3.msi");
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl("https://www.python.org/ftp/python/3.4.3/python-3.4.3.msi", true);
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(pythonDownloadSuccess(QString, QString)));
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(pythonDownloadFailure(QString, QString)));
}

View File

@@ -42,7 +42,7 @@
#include "core/preferences.h"
#include "core/logger.h"
#include "propertieswidget.h"
#include "geoipmanager.h"
#include "core/net/geoipmanager.h"
#include "peersadditiondlg.h"
#include "speedlimitdlg.h"
#include "guiiconprovider.h"
@@ -141,8 +141,14 @@ void PeerListWidget::updatePeerCountryResolutionState()
{
if (Preferences::instance()->resolvePeerCountries() != m_displayFlags) {
m_displayFlags = !m_displayFlags;
if (m_displayFlags)
if (m_displayFlags) {
loadPeers(m_properties->getCurrentTorrent());
showColumn(PeerListDelegate::COUNTRY);
resizeColumnToContents(PeerListDelegate::COUNTRY);
}
else {
hideColumn(PeerListDelegate::COUNTRY);
}
}
}
@@ -303,10 +309,10 @@ QStandardItem* PeerListWidget::addPeer(const QString& ip, BitTorrent::TorrentHan
m_listModel->setData(m_listModel->index(row, PeerListDelegate::PORT), peer.address().port);
m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP_HIDDEN), ip);
if (m_displayFlags) {
const QIcon ico = GeoIPManager::CountryISOCodeToIcon(peer.country());
const QIcon ico = GuiIconProvider::instance()->getFlagIcon(peer.country());
if (!ico.isNull()) {
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), ico, Qt::DecorationRole);
const QString country_name = GeoIPManager::CountryISOCodeToName(peer.country());
const QString country_name = Net::GeoIPManager::CountryName(peer.country());
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), country_name, Qt::ToolTipRole);
} else {
m_missingFlags.insert(ip);
@@ -331,10 +337,10 @@ void PeerListWidget::updatePeer(const QString &ip, BitTorrent::TorrentHandle *co
QStandardItem *item = m_peerItems.value(ip);
int row = item->row();
if (m_displayFlags) {
const QIcon ico = GeoIPManager::CountryISOCodeToIcon(peer.country());
const QIcon ico = GuiIconProvider::instance()->getFlagIcon(peer.country());
if (!ico.isNull()) {
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), ico, Qt::DecorationRole);
const QString country_name = GeoIPManager::CountryISOCodeToName(peer.country());
const QString country_name = Net::GeoIPManager::CountryName(peer.country());
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), country_name, Qt::ToolTipRole);
m_missingFlags.remove(ip);
}

View File

@@ -59,7 +59,7 @@ QStringList TrackersAdditionDlg::newTrackers() const
void TrackersAdditionDlg::on_uTorrentListButton_clicked()
{
uTorrentListButton->setEnabled(false);
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(QString("http://www.torrentz.com/announce_%1").arg(m_torrent->hash()));
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(QString("http://www.torrentz.com/announce_%1").arg(m_torrent->hash()), true);
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(parseUTorrentList(QString, QString)));
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(getTrackerError(QString, QString)));
//Just to show that it takes times

View File

@@ -66,7 +66,7 @@ RssFeed::RssFeed(RssManager* manager, RssFolder* parent, const QString& url):
connect(manager->rssParser(), SIGNAL(feedParsingFinished(QString,QString)), SLOT(handleFeedParsingFinished(QString,QString)));
// Download the RSS Feed icon
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(iconUrl());
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(iconUrl(), true);
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFinishedDownload(QString, QString)));
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
m_iconUrl = handler->url();
@@ -167,7 +167,7 @@ bool RssFeed::refresh()
}
m_loading = true;
// Download the RSS again
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(m_url);
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(m_url, true);
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFinishedDownload(QString, QString)));
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
m_url = handler->url(); // sync URL encoding

View File

@@ -474,7 +474,7 @@ void TrackerFiltersList::addItem(const QString &tracker, const QString &hash)
trackerItem = new QListWidgetItem();
trackerItem->setData(Qt::DecorationRole, GuiIconProvider::instance()->getIcon("network-server"));
Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(QString("http://%1/favicon.ico").arg(host));
Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(QString("http://%1/favicon.ico").arg(host), true);
connect(h, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFavicoDownload(QString, QString)));
connect(h, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleFavicoFailure(QString, QString)));
}
@@ -634,7 +634,7 @@ void TrackerFiltersList::handleFavicoDownload(const QString& url, const QString&
if (url.endsWith(".ico", Qt::CaseInsensitive)) {
Logger::instance()->addMessage(tr("Couldn't decode favicon for URL `%1`. Trying to download favicon in PNG format.").arg(url),
Log::WARNING);
Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(url.left(url.size() - 4) + ".png");
Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(url.left(url.size() - 4) + ".png", true);
connect(h, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFavicoDownload(QString, QString)));
connect(h, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleFavicoFailure(QString, QString)));
}