From 7ff475977e8d5f345b1129a3457e8de99cd310c8 Mon Sep 17 00:00:00 2001 From: Francois Ferrand Date: Fri, 19 Apr 2013 19:38:29 +0200 Subject: [PATCH] Favicon download button. --- src/gui/EditWidgetIcons.cpp | 80 ++++++++++++++++++++++++++++++- src/gui/EditWidgetIcons.h | 16 ++++++- src/gui/EditWidgetIcons.ui | 7 +++ src/gui/entry/EditEntryWidget.cpp | 3 +- 4 files changed, 103 insertions(+), 3 deletions(-) diff --git a/src/gui/EditWidgetIcons.cpp b/src/gui/EditWidgetIcons.cpp index db4a29176..73f726f4f 100644 --- a/src/gui/EditWidgetIcons.cpp +++ b/src/gui/EditWidgetIcons.cpp @@ -18,6 +18,7 @@ #include "EditWidgetIcons.h" #include "ui_EditWidgetIcons.h" +#include #include #include @@ -37,6 +38,7 @@ EditWidgetIcons::EditWidgetIcons(QWidget* parent) , m_ui(new Ui::EditWidgetIcons()) , m_defaultIconModel(new DefaultIconModel(this)) , m_customIconModel(new CustomIconModel(this)) + , m_networkAccessMngr(new QNetworkAccessManager(this)) { m_ui->setupUi(this); @@ -53,6 +55,11 @@ EditWidgetIcons::EditWidgetIcons(QWidget* parent) this, SLOT(updateWidgetsCustomIcons(bool))); connect(m_ui->addButton, SIGNAL(clicked()), SLOT(addCustomIcon())); connect(m_ui->deleteButton, SIGNAL(clicked()), SLOT(removeCustomIcon())); + connect(m_ui->faviconButton, SIGNAL(clicked()), SLOT(downloadFavicon())); + connect(m_networkAccessMngr, SIGNAL(finished(QNetworkReply*)), + this, SLOT(onRequestFinished(QNetworkReply*)) ); + + m_ui->faviconButton->setVisible(false); } EditWidgetIcons::~EditWidgetIcons() @@ -89,13 +96,14 @@ IconStruct EditWidgetIcons::save() return iconStruct; } -void EditWidgetIcons::load(Uuid currentUuid, Database* database, IconStruct iconStruct) +void EditWidgetIcons::load(Uuid currentUuid, Database* database, IconStruct iconStruct, const QString &url) { Q_ASSERT(database); Q_ASSERT(!currentUuid.isNull()); m_database = database; m_currentUuid = currentUuid; + setUrl(url); m_customIconModel->setIcons(database->metadata()->customIcons(), database->metadata()->customIconsOrder()); @@ -119,6 +127,76 @@ void EditWidgetIcons::load(Uuid currentUuid, Database* database, IconStruct icon } } +void EditWidgetIcons::setUrl(const QString &url) +{ + m_url = url; + m_ui->faviconButton->setVisible(!url.isEmpty()); + abortFaviconDownload(); +} + +static QStringList getHost(QUrl url, const QString& path) +{ + QStringList hosts; + + QString host = url.host(); + for(;;) { + QString s = host; + if (url.port() >= 0) + s += ":" + QString::number(url.port()); + hosts << s + path; + + 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 ); + else + break; + } + return hosts; +} + +void EditWidgetIcons::downloadFavicon() +{ + const QStringList pathes = getHost(QUrl(m_url), "/favicon."); + const QStringList prefixes = QStringList() << "http://" << "https://"; + const QStringList suffixes = QStringList() << "ico" << "png" << "gif" << "jpg"; + + Q_FOREACH (QString path, pathes) + Q_FOREACH (QString prefix, prefixes) + Q_FOREACH (QString suffix, suffixes) + m_networkOperations << m_networkAccessMngr->get(QNetworkRequest(prefix + path + suffix)); + //TODO: progress indication +} + +void EditWidgetIcons::abortFaviconDownload() +{ + Q_FOREACH (QNetworkReply *r, m_networkOperations) + r->abort(); +} + +void EditWidgetIcons::onRequestFinished(QNetworkReply *reply) +{ + if (m_networkOperations.contains(reply)) { + m_networkOperations.remove(reply); + + QImage image; + if (!reply->error() && image.loadFromData(reply->readAll()) && !image.isNull()) { + //Abort all other requests + abortFaviconDownload(); + + //Set the image + Uuid uuid = Uuid::random(); + m_database->metadata()->addCustomIcon(uuid, image.scaled(16, 16)); + m_customIconModel->setIcons(m_database->metadata()->customIcons(), + m_database->metadata()->customIconsOrder()); + QModelIndex index = m_customIconModel->indexFromUuid(uuid); + m_ui->customIconsView->setCurrentIndex(index); + m_ui->customIconsRadio->setChecked(true); + } + } + reply->deleteLater(); +} + void EditWidgetIcons::addCustomIcon() { if (m_database) { diff --git a/src/gui/EditWidgetIcons.h b/src/gui/EditWidgetIcons.h index 50eec6034..a59f640c9 100644 --- a/src/gui/EditWidgetIcons.h +++ b/src/gui/EditWidgetIcons.h @@ -18,8 +18,13 @@ #ifndef KEEPASSX_EDITWIDGETICONS_H #define KEEPASSX_EDITWIDGETICONS_H +#include + #include +#include +#include + #include "core/Global.h" #include "core/Uuid.h" @@ -48,9 +53,15 @@ public: ~EditWidgetIcons(); IconStruct save(); - void load(Uuid currentUuid, Database* database, IconStruct iconStruct); + void load(Uuid currentUuid, Database* database, IconStruct iconStruct, const QString &url = QString()); + +public Q_SLOTS: + void setUrl(const QString &url); private Q_SLOTS: + void downloadFavicon(); + void abortFaviconDownload(); + void onRequestFinished(QNetworkReply *reply); void addCustomIcon(); void removeCustomIcon(); void updateWidgetsDefaultIcons(bool checked); @@ -62,8 +73,11 @@ private: const QScopedPointer m_ui; Database* m_database; Uuid m_currentUuid; + QString m_url; DefaultIconModel* const m_defaultIconModel; CustomIconModel* const m_customIconModel; + QNetworkAccessManager* const m_networkAccessMngr; + QSet m_networkOperations; Q_DISABLE_COPY(EditWidgetIcons) }; diff --git a/src/gui/EditWidgetIcons.ui b/src/gui/EditWidgetIcons.ui index 4a0d39fc2..dd9e61852 100644 --- a/src/gui/EditWidgetIcons.ui +++ b/src/gui/EditWidgetIcons.ui @@ -91,6 +91,13 @@ + + + + Download favicon + + + diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index cbb572c77..3f0dc511d 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -328,7 +328,8 @@ void EditEntryWidget::setForms(const Entry* entry, bool restore) IconStruct iconStruct; iconStruct.uuid = entry->iconUuid(); iconStruct.number = entry->iconNumber(); - m_iconsWidget->load(entry->uuid(), m_database, iconStruct); + m_iconsWidget->load(entry->uuid(), m_database, iconStruct, entry->url()); + connect(m_mainUi->urlEdit, SIGNAL(textChanged(QString)), m_iconsWidget, SLOT(setUrl(QString))); m_autoTypeUi->enableButton->setChecked(entry->autoTypeEnabled()); if (entry->defaultAutoTypeSequence().isEmpty()) {