mirror of
https://bitbucket.org/smil3y/kde-workspace.git
synced 2025-02-23 18:32:50 +00:00
libs: favicons KDED module rewrite
saves a lot of I/O and network trafic if there are multiple bookmarks to the same host and multiple queries are made (which essentially will end up being many jobs for the same icon). also implemented fallback to alternative http://foo.bar/favicon.png and added tests for more cases, bonus points? Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
parent
1cbda72fad
commit
d811882f97
9 changed files with 175 additions and 435 deletions
|
@ -50,10 +50,10 @@ void FavIconsItr::setStatus(const QString & status)
|
||||||
model()->emitDataChanged(currentBookmark());
|
model()->emitDataChanged(currentBookmark());
|
||||||
}
|
}
|
||||||
|
|
||||||
void FavIconsItr::slotDone(bool succeeded, const QString& errorString)
|
void FavIconsItr::slotDone(bool succeeded)
|
||||||
{
|
{
|
||||||
// kDebug() << "FavIconsItr::slotDone()";
|
// kDebug() << "FavIconsItr::slotDone()";
|
||||||
setStatus(succeeded ? i18n("OK") : errorString);
|
setStatus(succeeded ? i18n("OK") : i18n("Download failed"));
|
||||||
holder()->addAffectedBookmark(KBookmark::parentAddress(currentBookmark().address()));
|
holder()->addAffectedBookmark(KBookmark::parentAddress(currentBookmark().address()));
|
||||||
delayedEmitNextOne();
|
delayedEmitNextOne();
|
||||||
}
|
}
|
||||||
|
@ -72,8 +72,8 @@ void FavIconsItr::doAction()
|
||||||
setStatus(i18n("Updating favicon..."));
|
setStatus(i18n("Updating favicon..."));
|
||||||
if (!m_updater) {
|
if (!m_updater) {
|
||||||
m_updater = new FavIconUpdater(this);
|
m_updater = new FavIconUpdater(this);
|
||||||
connect(m_updater, SIGNAL(done(bool,QString)),
|
connect(m_updater, SIGNAL(done(bool)),
|
||||||
this, SLOT(slotDone(bool,QString)) );
|
this, SLOT(slotDone(bool)) );
|
||||||
}
|
}
|
||||||
m_updater->downloadIcon(currentBookmark());
|
m_updater->downloadIcon(currentBookmark());
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ public:
|
||||||
virtual void cancel();
|
virtual void cancel();
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void slotDone(bool succeeded, const QString& errorString);
|
void slotDone(bool succeeded);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void doAction();
|
virtual void doAction();
|
||||||
|
|
|
@ -38,10 +38,10 @@ FavIconUpdater::FavIconUpdater(QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
m_favIconModule("org.kde.kded", "/modules/favicons", QDBusConnection::sessionBus())
|
m_favIconModule("org.kde.kded", "/modules/favicons", QDBusConnection::sessionBus())
|
||||||
{
|
{
|
||||||
connect(&m_favIconModule, SIGNAL(iconChanged(bool,QString,QString)),
|
connect(
|
||||||
this, SLOT(notifyChange(bool,QString,QString)) );
|
&m_favIconModule, SIGNAL(iconChanged(QString,QString)),
|
||||||
connect(&m_favIconModule, SIGNAL(error(bool,QString,QString)),
|
this, SLOT(notifyChange(QString,QString))
|
||||||
this, SLOT(slotFavIconError(bool,QString,QString)) );
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FavIconUpdater::downloadIcon(const KBookmark &bk)
|
void FavIconUpdater::downloadIcon(const KBookmark &bk)
|
||||||
|
@ -54,46 +54,26 @@ void FavIconUpdater::downloadIcon(const KBookmark &bk)
|
||||||
m_bk.setIcon(favicon);
|
m_bk.setIcon(favicon);
|
||||||
KEBApp::self()->notifyCommandExecuted();
|
KEBApp::self()->notifyCommandExecuted();
|
||||||
// kDebug() << "emit done(true)";
|
// kDebug() << "emit done(true)";
|
||||||
emit done(true, QString());
|
emit done(true);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
kDebug() << "no favicon found";
|
kDebug() << "no favicon found";
|
||||||
m_favIconModule.forceDownloadHostIcon(url);
|
m_favIconModule.forceDownloadUrlIcon(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FavIconUpdater::~FavIconUpdater()
|
void FavIconUpdater::notifyChange(const QString &url, const QString &iconName)
|
||||||
{
|
{
|
||||||
}
|
kDebug() << url << iconName;
|
||||||
|
if (m_bk.url().url() == url) {
|
||||||
bool FavIconUpdater::isFavIconSignalRelevant(bool isHost, const QString& hostOrURL) const
|
// kded module emits empty iconName on error
|
||||||
{
|
if (iconName.isEmpty()) {
|
||||||
// Is this signal interesting to us? (Don't react on an unrelated favicon)
|
emit done(false);
|
||||||
return (isHost && hostOrURL == m_bk.url().host()) ||
|
|
||||||
(!isHost && hostOrURL == m_bk.url().url()); // should we use the api that ignores trailing slashes?
|
|
||||||
}
|
|
||||||
|
|
||||||
void FavIconUpdater::notifyChange(bool isHost,
|
|
||||||
const QString& hostOrURL,
|
|
||||||
const QString& iconName)
|
|
||||||
{
|
|
||||||
kDebug() << hostOrURL << iconName;
|
|
||||||
if (isFavIconSignalRelevant(isHost, hostOrURL)) {
|
|
||||||
if (iconName.isEmpty()) { // old version of the kded module could emit with an empty iconName on error
|
|
||||||
slotFavIconError(isHost, hostOrURL, QString());
|
|
||||||
} else {
|
} else {
|
||||||
m_bk.setIcon(iconName);
|
m_bk.setIcon(iconName);
|
||||||
emit done(true, QString());
|
emit done(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FavIconUpdater::slotFavIconError(bool isHost, const QString& hostOrURL, const QString& errorString)
|
|
||||||
{
|
|
||||||
kDebug() << hostOrURL << errorString;
|
|
||||||
if (isFavIconSignalRelevant(isHost, hostOrURL)) {
|
|
||||||
emit done(false, errorString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "moc_faviconupdater.cpp"
|
#include "moc_faviconupdater.cpp"
|
||||||
|
|
|
@ -29,18 +29,13 @@ class FavIconUpdater : public QObject
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FavIconUpdater(QObject *parent);
|
FavIconUpdater(QObject *parent);
|
||||||
~FavIconUpdater();
|
|
||||||
void downloadIcon(const KBookmark &bk);
|
void downloadIcon(const KBookmark &bk);
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void notifyChange(bool isHost, const QString& hostOrURL, const QString& iconName);
|
void notifyChange(const QString &url, const QString& iconName);
|
||||||
void slotFavIconError(bool isHost, const QString& hostOrURL, const QString& errorString);
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void done(bool succeeded, const QString& error);
|
void done(bool succeeded);
|
||||||
|
|
||||||
private:
|
|
||||||
bool isFavIconSignalRelevant(bool isHost, const QString& hostOrURL) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
KBookmark m_bk;
|
KBookmark m_bk;
|
||||||
|
|
|
@ -42,115 +42,54 @@
|
||||||
K_PLUGIN_FACTORY(FavIconsFactory, registerPlugin<FavIconsModule>();)
|
K_PLUGIN_FACTORY(FavIconsFactory, registerPlugin<FavIconsModule>();)
|
||||||
K_EXPORT_PLUGIN(FavIconsFactory("favicons"))
|
K_EXPORT_PLUGIN(FavIconsFactory("favicons"))
|
||||||
|
|
||||||
static QString portForUrl(const KUrl& url)
|
static bool isIconOld(const QString &iconFile)
|
||||||
{
|
{
|
||||||
if (url.port() > 0) {
|
const QFileInfo iconInfo(iconFile);
|
||||||
return (QString(QLatin1Char('_')) + QString::number(url.port()));
|
|
||||||
}
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString simplifyURL(const KUrl &url)
|
|
||||||
{
|
|
||||||
// splat any = in the URL so it can be safely used as a config key
|
|
||||||
QString result = url.host() + portForUrl(url) + url.path();
|
|
||||||
for (int i = 0; i < result.length(); ++i) {
|
|
||||||
if (result[i] == QLatin1Char('=')) {
|
|
||||||
result[i] = QLatin1Char('_');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString iconNameFromURL(const KUrl &iconURL)
|
|
||||||
{
|
|
||||||
if (iconURL.path() == QLatin1String("/favicon.ico")) {
|
|
||||||
return iconURL.host() + portForUrl(iconURL);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString result = simplifyURL(iconURL);
|
|
||||||
// splat / so it can be safely used as a file name
|
|
||||||
for (int i = 0; i < result.length(); ++i) {
|
|
||||||
if (result[i] == QLatin1Char('/')) {
|
|
||||||
result[i] = QLatin1Char('_');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ext = result.right(4);
|
|
||||||
if (ext == QLatin1String(".ico") || ext == QLatin1String(".png") || ext == QLatin1String(".xpm")) {
|
|
||||||
result.remove(result.length() - 4, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString removeSlash(QString result)
|
|
||||||
{
|
|
||||||
for (unsigned int i = result.length() - 1; i > 0; --i) {
|
|
||||||
if (result[i] != QLatin1Char('/')) {
|
|
||||||
result.truncate(i + 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString faviconsCacheDir()
|
|
||||||
{
|
|
||||||
QString faviconsDir = KGlobal::dirs()->saveLocation("cache", QLatin1String("favicons/"));
|
|
||||||
faviconsDir.truncate(faviconsDir.length() - 9); // Strip off "favicons/"
|
|
||||||
return faviconsDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isIconOld(const QString &icon)
|
|
||||||
{
|
|
||||||
const QFileInfo iconInfo(icon);
|
|
||||||
const QDateTime iconLastModified = iconInfo.lastModified();
|
const QDateTime iconLastModified = iconInfo.lastModified();
|
||||||
if (!iconInfo.isFile() || !iconLastModified.isValid()) {
|
if (!iconInfo.isFile() || !iconLastModified.isValid()) {
|
||||||
// kDebug() << "isIconOld" << icon << "yes, no such file";
|
// kDebug() << "isIconOld" << iconFile << "yes, no such file";
|
||||||
return true; // Trigger a new download on error
|
return true; // Trigger a new download on error
|
||||||
}
|
}
|
||||||
|
|
||||||
// kDebug() << "isIconOld" << icon << "?";
|
// kDebug() << "isIconOld" << iconFile << "?";
|
||||||
const QDateTime currentTime = QDateTime::currentDateTime();
|
const QDateTime currentTime = QDateTime::currentDateTime();
|
||||||
return ((currentTime.toTime_t() - iconLastModified.toTime_t()) > 604800); // arbitrary value (one week)
|
return ((currentTime.toTime_t() - iconLastModified.toTime_t()) > 604800); // arbitrary value (one week)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FavIconsDownloadInfo
|
static QString iconNameFromURL(const QString &url)
|
||||||
{
|
{
|
||||||
QString hostOrURL;
|
return QString::fromLatin1("favicons/%1").arg(KUrl(url).host());
|
||||||
bool isHost;
|
|
||||||
QByteArray iconData;
|
|
||||||
};
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
Q_DECLARE_TYPEINFO(FavIconsDownloadInfo, Q_PRIMITIVE_TYPE);
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
static QString makeIconName(const FavIconsDownloadInfo& download, const KUrl& iconURL)
|
|
||||||
{
|
|
||||||
QString iconName = QString::fromLatin1("favicons/");
|
|
||||||
iconName += (download.isHost ? download.hostOrURL : iconNameFromURL(iconURL));
|
|
||||||
return iconName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FavIconsModulePrivate
|
static QString iconFilePath(const QString &iconName)
|
||||||
{
|
{
|
||||||
FavIconsModulePrivate() : config(nullptr) { }
|
return QString::fromLatin1("%1/%2.png").arg(KGlobal::dirs()->saveLocation("cache"), iconName);
|
||||||
~FavIconsModulePrivate() { delete config; }
|
}
|
||||||
|
|
||||||
QMap<KIO::TransferJob*, FavIconsDownloadInfo> downloads;
|
static QString faviconFromUrl(const QString &url, const QLatin1String &extension)
|
||||||
|
{
|
||||||
|
KUrl faviconUrl(url);
|
||||||
|
faviconUrl.setPath(QString::fromLatin1("/favicon.%1").arg(extension));
|
||||||
|
faviconUrl.setEncodedQuery(QByteArray());
|
||||||
|
return faviconUrl.url();
|
||||||
|
}
|
||||||
|
|
||||||
|
class FavIconsModulePrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KUrl::List queuedDownloads;
|
||||||
KUrl::List failedDownloads;
|
KUrl::List failedDownloads;
|
||||||
KConfig *config;
|
|
||||||
KIO::MetaData metaData;
|
KIO::MetaData metaData;
|
||||||
};
|
};
|
||||||
|
|
||||||
FavIconsModule::FavIconsModule(QObject* parent, const QList<QVariant>&)
|
FavIconsModule::FavIconsModule(QObject* parent, const QList<QVariant> &args)
|
||||||
: KDEDModule(parent)
|
: KDEDModule(parent),
|
||||||
|
d(new FavIconsModulePrivate())
|
||||||
{
|
{
|
||||||
d = new FavIconsModulePrivate;
|
Q_UNUSED(args);
|
||||||
|
|
||||||
d->metaData.insert(QLatin1String("cache"), "reload");
|
d->metaData.insert(QLatin1String("cache"), "reload");
|
||||||
d->metaData.insert(QLatin1String("no-www-auth"), QLatin1String("true"));
|
d->metaData.insert(QLatin1String("no-www-auth"), QLatin1String("true"));
|
||||||
d->config = new KConfig(KStandardDirs::locateLocal("data", QLatin1String("konqueror/faviconrc")));
|
|
||||||
|
|
||||||
new FavIconsAdaptor(this);
|
new FavIconsAdaptor(this);
|
||||||
}
|
}
|
||||||
|
@ -160,162 +99,135 @@ FavIconsModule::~FavIconsModule()
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FavIconsModule::iconForUrl(const KUrl &url)
|
QString FavIconsModule::iconForUrl(const QString &url)
|
||||||
{
|
{
|
||||||
if (url.host().isEmpty()) {
|
if (url.isEmpty()) {
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// kDebug() << url;
|
const QString iconName = iconNameFromURL(url);
|
||||||
|
const QString iconFile = iconFilePath(iconName);
|
||||||
const QString simplifiedURL = removeSlash(simplifyURL(url));
|
if (QFile::exists(iconFile)) {
|
||||||
QString icon = d->config->group(QString()).readEntry(simplifiedURL, QString());
|
kDebug() << "URL" << url << "icon" << iconName;
|
||||||
|
return iconName;
|
||||||
if (!icon.isEmpty()) {
|
|
||||||
icon = iconNameFromURL(KUrl(icon));
|
|
||||||
} else {
|
|
||||||
icon = url.host();
|
|
||||||
}
|
|
||||||
|
|
||||||
icon = QLatin1String("favicons/") + icon;
|
|
||||||
|
|
||||||
kDebug() << "URL:" << url << "ICON:" << icon;
|
|
||||||
|
|
||||||
if (QFile::exists(faviconsCacheDir() + icon + QLatin1String(".png"))) {
|
|
||||||
return icon;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FavIconsModule::setIconForUrl(const KUrl &url, const KUrl &iconURL)
|
void FavIconsModule::downloadUrlIcon(const QString &url)
|
||||||
{
|
{
|
||||||
// kDebug() << url << iconURL;
|
const QString iconName = iconNameFromURL(url);
|
||||||
const QString iconName = QLatin1String("favicons/") + iconNameFromURL(iconURL);
|
const QString iconFile = iconFilePath(iconName);
|
||||||
const QString iconFile = faviconsCacheDir() + iconName + QLatin1String(".png");
|
|
||||||
|
|
||||||
if (!isIconOld(iconFile)) {
|
if (!isIconOld(iconFile)) {
|
||||||
// kDebug() << "emit iconChanged" << false << url << iconName;
|
kDebug() << "Icon for URL already downloaded" << url;
|
||||||
emit iconChanged(false, url.url(), iconName);
|
emit iconChanged(url, iconName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
startDownload(url.url(), false, iconURL);
|
startDownload(url, iconFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FavIconsModule::downloadHostIcon(const KUrl &url)
|
void FavIconsModule::forceDownloadUrlIcon(const QString &url)
|
||||||
{
|
{
|
||||||
// kDebug() << url;
|
d->failedDownloads.removeAll(url); // force a download to happen
|
||||||
const QString iconFile = faviconsCacheDir() + QLatin1String("favicons/") + url.host() + QLatin1String(".png");
|
const QString iconName = iconNameFromURL(url);
|
||||||
if (!isIconOld(iconFile)) {
|
const QString iconFile = iconFilePath(iconName);
|
||||||
// kDebug() << "not old -> doing nothing";
|
QFile::remove(iconFile);
|
||||||
|
downloadUrlIcon(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FavIconsModule::startDownload(const QString &url, const QString &iconFile)
|
||||||
|
{
|
||||||
|
const QString iconName = iconNameFromURL(url);
|
||||||
|
if (d->queuedDownloads.contains(iconName)) {
|
||||||
|
kDebug() << "Icon download queued for" << url;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
startDownload(url.host(), true, KUrl(url, QLatin1String("/favicon.ico")));
|
if (d->failedDownloads.contains(url)) {
|
||||||
}
|
kDebug() << "Icon download already failed for" << url;
|
||||||
|
emit iconChanged(url, QString());
|
||||||
void FavIconsModule::forceDownloadHostIcon(const KUrl &url)
|
|
||||||
{
|
|
||||||
// kDebug() << url;
|
|
||||||
KUrl iconURL = KUrl(url, QLatin1String("/favicon.ico"));
|
|
||||||
d->failedDownloads.removeAll(iconURL); // force a download to happen
|
|
||||||
startDownload(url.host(), true, iconURL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FavIconsModule::startDownload(const QString &hostOrURL, bool isHost, const KUrl &iconURL)
|
|
||||||
{
|
|
||||||
if (d->failedDownloads.contains(iconURL)) {
|
|
||||||
// kDebug() << iconURL << "already in failedDownloads, emitting error";
|
|
||||||
emit error(isHost, hostOrURL, i18n("No favicon found"));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// kDebug() << iconURL;
|
d->queuedDownloads.append(iconName);
|
||||||
FavIconsDownloadInfo download;
|
const QString faviconUrl = faviconFromUrl(url, QLatin1String("ico"));
|
||||||
download.hostOrURL = hostOrURL;
|
startJob(url, faviconUrl, iconFile);
|
||||||
download.isHost = isHost;
|
}
|
||||||
KIO::TransferJob *tjob = KIO::get(iconURL, KIO::NoReload, KIO::HideProgressInfo);
|
|
||||||
|
void FavIconsModule::startJob(const QString &url, const QString &faviconUrl, const QString &iconFile)
|
||||||
|
{
|
||||||
|
kDebug() << "Downloading" << faviconUrl << "as" << iconFile;
|
||||||
|
KIO::StoredTransferJob *tjob = KIO::storedGet(faviconUrl, KIO::NoReload, KIO::HideProgressInfo);
|
||||||
tjob->setAutoDelete(false);
|
tjob->setAutoDelete(false);
|
||||||
tjob->addMetaData(d->metaData);
|
tjob->addMetaData(d->metaData);
|
||||||
d->downloads.insert(tjob, download);
|
tjob->setProperty("faviconsUrl", url);
|
||||||
connect(tjob, SIGNAL(infoMessage(KJob*,QString,QString)), SLOT(slotInfoMessage(KJob*,QString)));
|
tjob->setProperty("faviconsFile", iconFile);
|
||||||
connect(tjob, SIGNAL(data(KIO::Job*,QByteArray)), SLOT(slotData(KIO::Job*,QByteArray)));
|
connect(tjob, SIGNAL(finished(KJob*)), SLOT(slotFinished(KJob*)));
|
||||||
connect(tjob, SIGNAL(result(KJob*)), SLOT(slotResult(KJob*)));
|
|
||||||
tjob->start();
|
tjob->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FavIconsModule::slotData(KIO::Job *job, const QByteArray &data)
|
void FavIconsModule::slotFinished(KJob *kjob)
|
||||||
{
|
{
|
||||||
KIO::TransferJob* tjob = qobject_cast<KIO::TransferJob*>(job);
|
KIO::StoredTransferJob* tjob = qobject_cast<KIO::StoredTransferJob*>(kjob);
|
||||||
FavIconsDownloadInfo &download = d->downloads[tjob];
|
const QString faviconsUrl = tjob->property("faviconsUrl").toString();
|
||||||
const int oldSize = download.iconData.size();
|
const QString faviconsFile = tjob->property("faviconsFile").toString();
|
||||||
// Size limit. Stop downloading if the file is huge.
|
if (tjob->error()) {
|
||||||
// Testcase (as of june 2008, at least): http://planet-soc.com/favicon.ico, 136K and strange format.
|
const QString tjoburl = tjob->url().url();
|
||||||
if (oldSize > 500000) {
|
if (tjoburl.endsWith(QLatin1String(".ico"))) {
|
||||||
kWarning() << "Favicon too big, aborting download of" << tjob->url();
|
const QString faviconUrl = faviconFromUrl(faviconsUrl, QLatin1String("png"));
|
||||||
const KUrl iconURL = tjob->url();
|
kDebug() << "Attempting alternative icon" << faviconUrl;
|
||||||
d->failedDownloads.append(iconURL);
|
tjob->deleteLater();
|
||||||
d->downloads.remove(tjob);
|
startJob(faviconsUrl, faviconUrl, faviconsFile);
|
||||||
tjob->kill();
|
return;
|
||||||
|
}
|
||||||
|
kWarning() << "Job error" << tjob->errorString();
|
||||||
|
downloadError(faviconsUrl);
|
||||||
tjob->deleteLater();
|
tjob->deleteLater();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
download.iconData.append(data);
|
QBuffer buffer;
|
||||||
}
|
buffer.setData(tjob->data());
|
||||||
|
buffer.open(QIODevice::ReadOnly);
|
||||||
void FavIconsModule::slotResult(KJob *job)
|
QImageReader ir(&buffer);
|
||||||
{
|
if (!ir.canRead()) {
|
||||||
KIO::TransferJob* tjob = qobject_cast<KIO::TransferJob*>(job);
|
kWarning() << "Image reader cannot read the data" << ir.errorString();
|
||||||
FavIconsDownloadInfo download = d->downloads[tjob];
|
downloadError(faviconsUrl);
|
||||||
d->downloads.remove(tjob);
|
tjob->deleteLater();
|
||||||
const KUrl iconURL = tjob->url();
|
return;
|
||||||
QString iconName;
|
|
||||||
QString errorMessage;
|
|
||||||
if (!tjob->error()) {
|
|
||||||
QBuffer buffer(&download.iconData);
|
|
||||||
buffer.open(QIODevice::ReadOnly);
|
|
||||||
QImageReader ir(&buffer);
|
|
||||||
if (ir.canRead()) {
|
|
||||||
const QImage img = ir.read();
|
|
||||||
if (!img.isNull()) {
|
|
||||||
iconName = makeIconName(download, iconURL);
|
|
||||||
const QString localPath = faviconsCacheDir() + iconName + QLatin1String(".png");
|
|
||||||
if (!img.save(localPath, "PNG")) {
|
|
||||||
iconName.clear();
|
|
||||||
errorMessage = i18n("Error saving image to %1", localPath);
|
|
||||||
kWarning() << "Error saving image to" << localPath;
|
|
||||||
} else {
|
|
||||||
if (!download.isHost) {
|
|
||||||
d->config->group(QString()).writeEntry(removeSlash(download.hostOrURL), iconURL.url());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
errorMessage = i18n("Image reader returned null image");
|
|
||||||
kWarning() << "Image reader returned null image" << ir.errorString();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
errorMessage = i18n("Image reader cannot read the data");
|
|
||||||
kWarning() << "Image reader cannot read the data" << ir.errorString();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
errorMessage = tjob->errorString();
|
|
||||||
kWarning() << "Job error" << tjob->errorString();
|
|
||||||
}
|
}
|
||||||
|
const QImage img = ir.read();
|
||||||
tjob->deleteLater();
|
tjob->deleteLater();
|
||||||
if (iconName.isEmpty()) {
|
if (img.isNull()) {
|
||||||
// kDebug() << "adding" << iconURL << "to failed downloads";
|
kWarning() << "Image reader returned null image" << ir.errorString();
|
||||||
d->failedDownloads.append(iconURL);
|
downloadError(faviconsUrl);
|
||||||
emit error(download.isHost, download.hostOrURL, errorMessage);
|
return;
|
||||||
} else {
|
|
||||||
// kDebug() << "emit iconChanged" << download.isHost << download.hostOrURL << iconName;
|
|
||||||
emit iconChanged(download.isHost, download.hostOrURL, iconName);
|
|
||||||
}
|
}
|
||||||
|
if (!img.save(faviconsFile, "PNG")) {
|
||||||
|
kWarning() << "Error saving image to" << faviconsFile;
|
||||||
|
downloadError(faviconsUrl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
downloadSuccess(faviconsUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FavIconsModule::slotInfoMessage(KJob *job, const QString &msg)
|
void FavIconsModule::downloadSuccess(const QString &url)
|
||||||
{
|
{
|
||||||
KIO::TransferJob* tjob = qobject_cast<KIO::TransferJob*>(job);
|
kDebug() << "Downloaded icon for" << url;
|
||||||
emit infoMessage(tjob->url().url(), msg);
|
const QString iconName = iconNameFromURL(url);
|
||||||
|
d->queuedDownloads.removeAll(iconName);
|
||||||
|
emit iconChanged(url, iconName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FavIconsModule::downloadError(const QString &url)
|
||||||
|
{
|
||||||
|
if (!d->failedDownloads.contains(url)) {
|
||||||
|
kDebug() << "Adding" << url << "to failed downloads";
|
||||||
|
d->failedDownloads.append(url);
|
||||||
|
}
|
||||||
|
const QString iconName = iconNameFromURL(url);
|
||||||
|
d->queuedDownloads.removeAll(iconName);
|
||||||
|
emit iconChanged(url, QString());
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "moc_favicons.cpp"
|
#include "moc_favicons.cpp"
|
||||||
|
|
|
@ -19,28 +19,15 @@
|
||||||
#ifndef _FAVICONS_H_
|
#ifndef _FAVICONS_H_
|
||||||
#define _FAVICONS_H_
|
#define _FAVICONS_H_
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
#include <kdedmodule.h>
|
#include <kdedmodule.h>
|
||||||
#include <kurl.h>
|
#include <kjob.h>
|
||||||
|
|
||||||
class KJob;
|
|
||||||
namespace KIO { class Job; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* KDED Module to handle shortcut icons ("favicons")
|
* KDED Module to handle shortcut icons ("favicons")
|
||||||
* FavIconsModule implements a KDED Module that handles the association of
|
* FavIconsModule implements a KDED Module that handles the association of
|
||||||
* URLs and hosts with shortcut icons and the icons' downloads in a central
|
* URLs with shortcut icons and downloads such on demand.
|
||||||
* place.
|
|
||||||
*
|
*
|
||||||
* After a successful download, the D-Bus signal iconChanged() is emitted.
|
|
||||||
* It has the signature void iconChanged(bool, QString, QString);
|
|
||||||
* The first parameter is true if the icon is a "host" icon, that is it is
|
|
||||||
* the default icon for all URLs on the given host. In this case, the
|
|
||||||
* second parameter is a host name, otherwise the second parameter is the
|
|
||||||
* URL which is associated with the icon. The third parameter is the
|
|
||||||
* @ref KIconLoader friendly name of the downloaded icon, the same as
|
|
||||||
* @ref iconForUrl will from now on return for any matching URL.
|
|
||||||
*
|
|
||||||
* @short KDED Module for favicons
|
|
||||||
* @author Malte Starostik <malte@kde.org>
|
* @author Malte Starostik <malte@kde.org>
|
||||||
*/
|
*/
|
||||||
class FavIconsModule : public KDEDModule
|
class FavIconsModule : public KDEDModule
|
||||||
|
@ -49,10 +36,10 @@ class FavIconsModule : public KDEDModule
|
||||||
Q_CLASSINFO("D-Bus Interface", "org.kde.FavIcon")
|
Q_CLASSINFO("D-Bus Interface", "org.kde.FavIcon")
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FavIconsModule(QObject* parent, const QList<QVariant>&);
|
FavIconsModule(QObject* parent, const QList<QVariant> &args);
|
||||||
virtual ~FavIconsModule();
|
~FavIconsModule();
|
||||||
|
|
||||||
public Q_SLOTS: // dbus methods, called by the adaptor
|
public Q_SLOTS:
|
||||||
/**
|
/**
|
||||||
* Looks up an icon name for a given URL. This function does not
|
* Looks up an icon name for a given URL. This function does not
|
||||||
* initiate any download. If no icon for the URL or its host has
|
* initiate any download. If no icon for the URL or its host has
|
||||||
|
@ -62,18 +49,8 @@ public Q_SLOTS: // dbus methods, called by the adaptor
|
||||||
* @return the icon name suitable to pass to @ref KIconLoader or
|
* @return the icon name suitable to pass to @ref KIconLoader or
|
||||||
* QString() if no icon for this URL was found.
|
* QString() if no icon for this URL was found.
|
||||||
*/
|
*/
|
||||||
QString iconForUrl(const KUrl &url);
|
QString iconForUrl(const QString &url);
|
||||||
|
|
||||||
/**
|
|
||||||
* Associates an icon with the given URL. If the icon was not
|
|
||||||
* downloaded before or the downloaded was too long ago, a
|
|
||||||
* download attempt will be started and the iconChanged() D-Bus
|
|
||||||
* signal is emitted after the download finished successfully.
|
|
||||||
*
|
|
||||||
* @param url the URL which will be associated with the icon
|
|
||||||
* @param iconURL the URL of the icon to be downloaded
|
|
||||||
*/
|
|
||||||
void setIconForUrl(const KUrl &url, const KUrl &iconURL);
|
|
||||||
/**
|
/**
|
||||||
* Downloads the icon for a given host if it was not downloaded before
|
* Downloads the icon for a given host if it was not downloaded before
|
||||||
* or the download was too long ago. If the download finishes
|
* or the download was too long ago. If the download finishes
|
||||||
|
@ -81,7 +58,7 @@ public Q_SLOTS: // dbus methods, called by the adaptor
|
||||||
*
|
*
|
||||||
* @param url any URL on the host for which the icon is to be downloaded
|
* @param url any URL on the host for which the icon is to be downloaded
|
||||||
*/
|
*/
|
||||||
void downloadHostIcon(const KUrl &url);
|
void downloadUrlIcon(const QString &url);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Downloads the icon for a given host, even if we tried very recently.
|
* Downloads the icon for a given host, even if we tried very recently.
|
||||||
|
@ -92,37 +69,25 @@ public Q_SLOTS: // dbus methods, called by the adaptor
|
||||||
*
|
*
|
||||||
* @param url any URL on the host for which the icon is to be downloaded
|
* @param url any URL on the host for which the icon is to be downloaded
|
||||||
*/
|
*/
|
||||||
void forceDownloadHostIcon(const KUrl &url);
|
void forceDownloadUrlIcon(const QString &url);
|
||||||
|
|
||||||
signals: // D-Bus signals
|
Q_SIGNALS: // D-Bus signals
|
||||||
/**
|
/**
|
||||||
* Emitted once a new icon is available, for a host or url
|
* Emitted once a new icon is available, for a host or url
|
||||||
*/
|
*/
|
||||||
void iconChanged(bool isHost, QString hostOrURL, QString iconName);
|
void iconChanged(QString url, QString iconName);
|
||||||
/**
|
|
||||||
* Progress info while downloading an icon
|
|
||||||
*/
|
|
||||||
void infoMessage(QString iconURL, QString msg);
|
|
||||||
/**
|
|
||||||
* Emitted if an error occurred while downloading the icon for the given host or url.
|
|
||||||
* You can usually ignore this (e.g. web browsers don't need to do anything if
|
|
||||||
* no favicon was found), but this signal can be useful in some cases, e.g.
|
|
||||||
* to let keditbookmarks know that it should move on to the next bookmark.
|
|
||||||
*/
|
|
||||||
void error(bool isHost, QString hostOrURL, QString errorString);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void startDownload(const QString &, bool, const KUrl &);
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void slotData(KIO::Job *, const QByteArray &);
|
void slotFinished(KJob *kjob);
|
||||||
void slotResult(KJob *);
|
|
||||||
void slotInfoMessage(KJob *, const QString &);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct FavIconsModulePrivate *d;
|
void startDownload(const QString &url, const QString &iconFile);
|
||||||
|
void startJob(const QString &url, const QString &faviconUrl, const QString &iconFile);
|
||||||
|
void downloadSuccess(const QString &url);
|
||||||
|
void downloadError(const QString &url);
|
||||||
|
|
||||||
|
private:
|
||||||
|
class FavIconsModulePrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // _FAVICONS_H_
|
||||||
|
|
||||||
// vim: ts=4 sw=4 et
|
|
||||||
|
|
|
@ -2,31 +2,17 @@
|
||||||
<node>
|
<node>
|
||||||
<interface name="org.kde.FavIcon">
|
<interface name="org.kde.FavIcon">
|
||||||
<signal name="iconChanged">
|
<signal name="iconChanged">
|
||||||
<arg name="isHost" type="b" direction="out"/>
|
<arg name="url" type="s" direction="out"/>
|
||||||
<arg name="hostOrUrl" type="s" direction="out"/>
|
|
||||||
<arg name="iconName" type="s" direction="out"/>
|
|
||||||
</signal>
|
|
||||||
<signal name="infoMessage">
|
|
||||||
<arg name="iconUrl" type="s" direction="out"/>
|
|
||||||
<arg name="msg" type="s" direction="out"/>
|
|
||||||
</signal>
|
|
||||||
<signal name="error">
|
|
||||||
<arg name="isHost" type="b" direction="out"/>
|
|
||||||
<arg name="hostOrUrl" type="s" direction="out"/>
|
|
||||||
<arg name="iconName" type="s" direction="out"/>
|
<arg name="iconName" type="s" direction="out"/>
|
||||||
</signal>
|
</signal>
|
||||||
<method name="iconForUrl">
|
<method name="iconForUrl">
|
||||||
<arg type="s" direction="out"/>
|
<arg type="s" direction="out"/>
|
||||||
<arg name="url" type="s" direction="in"/>
|
<arg name="url" type="s" direction="in"/>
|
||||||
</method>
|
</method>
|
||||||
<method name="setIconForUrl">
|
<method name="downloadUrlIcon">
|
||||||
<arg name="url" type="s" direction="in"/>
|
|
||||||
<arg name="iconUrl" type="s" direction="in"/>
|
|
||||||
</method>
|
|
||||||
<method name="downloadHostIcon">
|
|
||||||
<arg name="url" type="s" direction="in"/>
|
<arg name="url" type="s" direction="in"/>
|
||||||
</method>
|
</method>
|
||||||
<method name="forceDownloadHostIcon">
|
<method name="forceDownloadUrlIcon">
|
||||||
<arg name="url" type="s" direction="in"/>
|
<arg name="url" type="s" direction="in"/>
|
||||||
</method>
|
</method>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
|
@ -89,20 +89,11 @@ static void cleanCache()
|
||||||
FavIconTest::FavIconTest()
|
FavIconTest::FavIconTest()
|
||||||
: QObject(),
|
: QObject(),
|
||||||
m_iconChanged(false),
|
m_iconChanged(false),
|
||||||
m_isHost(false),
|
|
||||||
m_favIconModule("org.kde.kded", "/modules/favicons", QDBusConnection::sessionBus())
|
m_favIconModule("org.kde.kded", "/modules/favicons", QDBusConnection::sessionBus())
|
||||||
{
|
{
|
||||||
connect(
|
connect(
|
||||||
&m_favIconModule, SIGNAL(iconChanged(bool,QString,QString)),
|
&m_favIconModule, SIGNAL(iconChanged(QString,QString)),
|
||||||
this, SLOT(slotIconChanged(bool,QString,QString))
|
this, SLOT(slotIconChanged(QString,QString))
|
||||||
);
|
|
||||||
connect(
|
|
||||||
&m_favIconModule, SIGNAL(infoMessage(QString,QString)),
|
|
||||||
this, SLOT(slotInfoMessage(QString,QString))
|
|
||||||
);
|
|
||||||
connect(
|
|
||||||
&m_favIconModule, SIGNAL(error(bool,QString,QString)),
|
|
||||||
this, SLOT(slotError(bool,QString,QString))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,79 +101,6 @@ void FavIconTest::initTestCase()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void FavIconTest::testSetIconForURL_data()
|
|
||||||
{
|
|
||||||
QTest::addColumn<QString>("url");
|
|
||||||
QTest::addColumn<QString>("icon");
|
|
||||||
QTest::addColumn<QString>("result");
|
|
||||||
|
|
||||||
QTest::newRow("https://www.google.com")
|
|
||||||
<< QString::fromLatin1("https://www.google.com") << QString::fromLatin1("https://www.google.com/favicon.ico")
|
|
||||||
<< QString::fromLatin1("favicons/www.google.com");
|
|
||||||
QTest::newRow("https://www.ibm.com")
|
|
||||||
<< QString::fromLatin1("https://www.ibm.com") << QString::fromLatin1("https://www.ibm.com/favicon.ico")
|
|
||||||
<< QString::fromLatin1("favicons/www.ibm.com");
|
|
||||||
QTest::newRow("https://github.com/")
|
|
||||||
<< QString::fromLatin1("https://github.com/") << QString::fromLatin1("https://github.com/favicon.ico")
|
|
||||||
<< QString::fromLatin1("favicons/github.com");
|
|
||||||
// lb-140-82-121-3-fra.github.com if not address
|
|
||||||
QTest::newRow("https://140.82.121.3/")
|
|
||||||
<< QString::fromLatin1("https://140.82.121.3/") << QString::fromLatin1("https://140.82.121.3/favicon.ico")
|
|
||||||
<< QString::fromLatin1("favicons/lb-140-82-121-3-fra.github.com");
|
|
||||||
}
|
|
||||||
|
|
||||||
void FavIconTest::testSetIconForURL()
|
|
||||||
{
|
|
||||||
QFETCH(QString, url);
|
|
||||||
QFETCH(QString, icon);
|
|
||||||
QFETCH(QString, result);
|
|
||||||
|
|
||||||
if (!checkICOReadable()) {
|
|
||||||
QSKIP("ico not readable", SkipAll);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!checkNetworkAccess()) {
|
|
||||||
QSKIP("no network access", SkipAll);
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanCache();
|
|
||||||
|
|
||||||
#if USE_EVENT_LOOP
|
|
||||||
QEventLoop eventLoop;
|
|
||||||
connect(&m_favIconModule, SIGNAL(iconChanged(bool,QString,QString)), &eventLoop, SLOT(quit()));
|
|
||||||
QSignalSpy spy(&m_favIconModule, SIGNAL(iconChanged(bool,QString,QString)));
|
|
||||||
QVERIFY(spy.isValid());
|
|
||||||
QCOMPARE(spy.count(), 0);
|
|
||||||
m_favIconModule.setIconForUrl(url, icon);
|
|
||||||
qDebug("called setIconForUrl, waiting");
|
|
||||||
if (spy.count() < 1) {
|
|
||||||
QTimer::singleShot(s_waitTime, &eventLoop, SLOT(quit()));
|
|
||||||
eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
|
|
||||||
}
|
|
||||||
|
|
||||||
QCOMPARE(spy.count(), 1);
|
|
||||||
QCOMPARE(spy[0][0].toBool(), false);
|
|
||||||
QCOMPARE(spy[0][1].toString(), url);
|
|
||||||
QCOMPARE(spy[0][2].toString(), result);
|
|
||||||
#else
|
|
||||||
m_iconChanged = false;
|
|
||||||
m_favIconModule.setIconForUrl(url, icon);
|
|
||||||
qDebug("called setIconForUrl, waiting");
|
|
||||||
QElapsedTimer elapsedTimer;
|
|
||||||
elapsedTimer.start();
|
|
||||||
while (!m_iconChanged && elapsedTimer.elapsed() < s_waitTime) {
|
|
||||||
QTest::qWait(400);
|
|
||||||
}
|
|
||||||
QVERIFY(m_iconChanged);
|
|
||||||
if (m_isHost) {
|
|
||||||
QCOMPARE(m_hostOrURL, KUrl(url).host());
|
|
||||||
} else {
|
|
||||||
QCOMPARE(m_hostOrURL, url);
|
|
||||||
}
|
|
||||||
QCOMPARE(m_iconName, result);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void FavIconTest::testIconForURL_data()
|
void FavIconTest::testIconForURL_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<QString>("url");
|
QTest::addColumn<QString>("url");
|
||||||
|
@ -190,10 +108,10 @@ void FavIconTest::testIconForURL_data()
|
||||||
|
|
||||||
QTest::newRow("https://www.google.com")
|
QTest::newRow("https://www.google.com")
|
||||||
<< QString::fromLatin1("https://www.google.com") << QString::fromLatin1("favicons/www.google.com");
|
<< QString::fromLatin1("https://www.google.com") << QString::fromLatin1("favicons/www.google.com");
|
||||||
QTest::newRow("https://www.ibm.com")
|
QTest::newRow("https://www.ibm.com/foo?bar=baz")
|
||||||
<< QString::fromLatin1("https://www.ibm.com") << QString::fromLatin1("favicons/www.ibm.com");
|
<< QString::fromLatin1("https://www.ibm.com") << QString::fromLatin1("favicons/www.ibm.com");
|
||||||
QTest::newRow("https://github.com/")
|
QTest::newRow("https://www.wpoven.com/") // NOTE: favicon.png
|
||||||
<< QString::fromLatin1("https://github.com/") << QString::fromLatin1("favicons/github.com");
|
<< QString::fromLatin1("https://www.wpoven.com/") << QString::fromLatin1("favicons/www.wpoven.com");
|
||||||
QTest::newRow("https://140.82.121.3/")
|
QTest::newRow("https://140.82.121.3/")
|
||||||
<< QString::fromLatin1("https://140.82.121.3/") << QString::fromLatin1("favicons/140.82.121.3");
|
<< QString::fromLatin1("https://140.82.121.3/") << QString::fromLatin1("favicons/140.82.121.3");
|
||||||
}
|
}
|
||||||
|
@ -219,11 +137,11 @@ void FavIconTest::testIconForURL()
|
||||||
|
|
||||||
#if USE_EVENT_LOOP
|
#if USE_EVENT_LOOP
|
||||||
QEventLoop eventLoop;
|
QEventLoop eventLoop;
|
||||||
connect(&m_favIconModule, SIGNAL(iconChanged(bool,QString,QString)), &eventLoop, SLOT(quit()));
|
connect(&m_favIconModule, SIGNAL(iconChanged(QString,QString)), &eventLoop, SLOT(quit()));
|
||||||
QSignalSpy spy(&m_favIconModule, SIGNAL(iconChanged(bool,QString,QString)));
|
QSignalSpy spy(&m_favIconModule, SIGNAL(iconChanged(QString,QString)));
|
||||||
QVERIFY(spy.isValid());
|
QVERIFY(spy.isValid());
|
||||||
QCOMPARE(spy.count(), 0);
|
QCOMPARE(spy.count(), 0);
|
||||||
m_favIconModule.downloadHostIcon(url);
|
m_favIconModule.downloadUrlIcon(url);
|
||||||
qDebug("called downloadHostIcon, waiting");
|
qDebug("called downloadHostIcon, waiting");
|
||||||
if (spy.count() < 1) {
|
if (spy.count() < 1) {
|
||||||
QTimer::singleShot(s_waitTime, &eventLoop, SLOT(quit()));
|
QTimer::singleShot(s_waitTime, &eventLoop, SLOT(quit()));
|
||||||
|
@ -232,7 +150,7 @@ void FavIconTest::testIconForURL()
|
||||||
QCOMPARE(spy.count(), 1);
|
QCOMPARE(spy.count(), 1);
|
||||||
#else
|
#else
|
||||||
m_iconChanged = false;
|
m_iconChanged = false;
|
||||||
m_favIconModule.downloadHostIcon(url);
|
m_favIconModule.downloadUrlIcon(url);
|
||||||
qDebug("called downloadHostIcon, waiting");
|
qDebug("called downloadHostIcon, waiting");
|
||||||
QElapsedTimer elapsedTimer;
|
QElapsedTimer elapsedTimer;
|
||||||
elapsedTimer.start();
|
elapsedTimer.start();
|
||||||
|
@ -246,23 +164,12 @@ void FavIconTest::testIconForURL()
|
||||||
QCOMPARE(favicon, icon);
|
QCOMPARE(favicon, icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FavIconTest::slotIconChanged(const bool isHost, const QString &hostOrURL, const QString &iconName)
|
void FavIconTest::slotIconChanged(const QString &url, const QString &iconName)
|
||||||
{
|
{
|
||||||
qDebug() << isHost << hostOrURL << iconName;
|
qDebug() << url << iconName;
|
||||||
m_iconChanged = true;
|
m_iconChanged = true;
|
||||||
m_isHost = isHost;
|
m_url = url;
|
||||||
m_hostOrURL = hostOrURL;
|
|
||||||
m_iconName = iconName;
|
m_iconName = iconName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FavIconTest::slotInfoMessage(const QString &iconURL, const QString &msg)
|
|
||||||
{
|
|
||||||
qDebug() << iconURL << msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FavIconTest::slotError(const bool isHost, const QString &hostOrURL, const QString &errorString)
|
|
||||||
{
|
|
||||||
qWarning() << isHost << hostOrURL << errorString;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "moc_favicontest.cpp"
|
#include "moc_favicontest.cpp"
|
||||||
|
|
|
@ -31,19 +31,14 @@ public:
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void initTestCase();
|
void initTestCase();
|
||||||
void testSetIconForURL_data();
|
|
||||||
void testSetIconForURL();
|
|
||||||
void testIconForURL_data();
|
void testIconForURL_data();
|
||||||
void testIconForURL();
|
void testIconForURL();
|
||||||
|
|
||||||
void slotIconChanged(const bool isHost, const QString &hostOrURL, const QString &iconName);
|
void slotIconChanged(const QString &url, const QString &iconName);
|
||||||
void slotInfoMessage(const QString &iconURL, const QString &msg);
|
|
||||||
void slotError(const bool isHost, const QString &hostOrURL, const QString &errorString);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_iconChanged;
|
bool m_iconChanged;
|
||||||
bool m_isHost;
|
QString m_url;
|
||||||
QString m_hostOrURL;
|
|
||||||
QString m_iconName;
|
QString m_iconName;
|
||||||
|
|
||||||
org::kde::FavIcon m_favIconModule;
|
org::kde::FavIcon m_favIconModule;
|
||||||
|
|
Loading…
Add table
Reference in a new issue