From 7e57cb63f5c6aeac307b240faaacad5fb13baeeb Mon Sep 17 00:00:00 2001 From: nowrep Date: Sat, 15 Mar 2014 19:36:03 +0100 Subject: [PATCH] [LocationCompleter] Run completions search in separate thread Currently, there is one issue with inline domain completion. It is also searched from the separate thread, and thus it gets displayed after a small delay. Closes #1135 --- src/lib/app/mainapplication.cpp | 1 - src/lib/lib.pro | 6 +- .../completer/locationcompleter.cpp | 47 ++-- .../navigation/completer/locationcompleter.h | 9 +- .../completer/locationcompletermodel.cpp | 106 +-------- .../completer/locationcompletermodel.h | 12 +- .../completer/locationcompleterrefreshjob.cpp | 212 ++++++++++++++++++ .../completer/locationcompleterrefreshjob.h | 69 ++++++ src/lib/navigation/locationbar.cpp | 10 +- src/lib/navigation/locationbar.h | 3 +- src/lib/tools/iconprovider.cpp | 24 +- src/lib/tools/iconprovider.h | 3 + src/lib/tools/sqldatabase.cpp | 6 +- 13 files changed, 368 insertions(+), 140 deletions(-) create mode 100644 src/lib/navigation/completer/locationcompleterrefreshjob.cpp create mode 100644 src/lib/navigation/completer/locationcompleterrefreshjob.h diff --git a/src/lib/app/mainapplication.cpp b/src/lib/app/mainapplication.cpp index 3f41ea703..fe614bd42 100644 --- a/src/lib/app/mainapplication.cpp +++ b/src/lib/app/mainapplication.cpp @@ -272,7 +272,6 @@ MainApplication::~MainApplication() delete m_bookmarks; delete m_cookieJar; - SqlDatabase::destroy(); IconProvider::instance()->saveIconsToDatabase(); } diff --git a/src/lib/lib.pro b/src/lib/lib.pro index 8051ac626..f709a7e0b 100644 --- a/src/lib/lib.pro +++ b/src/lib/lib.pro @@ -260,7 +260,8 @@ SOURCES += \ app/datapaths.cpp \ app/profilemanager.cpp \ app/mainmenu.cpp \ - tools/sqldatabase.cpp + tools/sqldatabase.cpp \ + navigation/completer/locationcompleterrefreshjob.cpp HEADERS += \ @@ -461,7 +462,8 @@ HEADERS += \ app/datapaths.h \ app/profilemanager.h \ app/mainmenu.h \ - tools/sqldatabase.h + tools/sqldatabase.h \ + navigation/completer/locationcompleterrefreshjob.h FORMS += \ preferences/autofillmanager.ui \ diff --git a/src/lib/navigation/completer/locationcompleter.cpp b/src/lib/navigation/completer/locationcompleter.cpp index a9c002616..cbe2aecd9 100644 --- a/src/lib/navigation/completer/locationcompleter.cpp +++ b/src/lib/navigation/completer/locationcompleter.cpp @@ -18,6 +18,7 @@ #include "locationcompleter.h" #include "locationcompletermodel.h" #include "locationcompleterview.h" +#include "locationcompleterrefreshjob.h" #include "locationbar.h" #include "mainapplication.h" #include "browserwindow.h" @@ -35,6 +36,7 @@ LocationCompleter::LocationCompleter(QObject* parent) : QObject(parent) , m_window(0) , m_locationBar(0) + , m_lastRefreshTimestamp(0) , m_showingMostVisited(false) { if (!s_view) { @@ -56,7 +58,7 @@ void LocationCompleter::setLocationBar(LocationBar* locationBar) QString LocationCompleter::domainCompletion() const { - return qzSettings->useInlineCompletion ? m_completedDomain : QString(); + return qzSettings->useInlineCompletion ? m_domainCompletion : QString(); } bool LocationCompleter::isShowingMostVisited() const @@ -71,21 +73,20 @@ bool LocationCompleter::isPopupVisible() const void LocationCompleter::closePopup() { - m_completedDomain.clear(); + m_domainCompletion.clear(); m_showingMostVisited = false; s_view->close(); } void LocationCompleter::complete(const QString &string) { + m_domainCompletion.clear(); m_showingMostVisited = string.isEmpty(); - if (qzSettings->useInlineCompletion) { - m_completedDomain = createDomainCompletionString(string); - } + LocationCompleterRefreshJob* job = new LocationCompleterRefreshJob(string); + connect(job, SIGNAL(finished()), this, SLOT(refreshJobFinished())); - s_model->refreshCompletions(string); - showPopup(); + emit domainCompletionChanged(); } void LocationCompleter::showMostVisited() @@ -116,6 +117,23 @@ void LocationCompleter::slotPopupClosed() emit popupClosed(); } +void LocationCompleter::refreshJobFinished() +{ + LocationCompleterRefreshJob* job = qobject_cast(sender()); + Q_ASSERT(job); + + if (job->timestamp() > m_lastRefreshTimestamp) { + m_domainCompletion = job->domainCompletion(); + s_model->setCompletions(job->completions()); + m_lastRefreshTimestamp = job->timestamp(); + + showPopup(); + emit domainCompletionChanged(); + } + + job->deleteLater(); +} + void LocationCompleter::indexActivated(const QModelIndex &index) { Q_ASSERT(index.isValid()); @@ -206,21 +224,6 @@ void LocationCompleter::indexDeleteRequested(const QModelIndex &index) s_model->removeRow(index.row(), index.parent()); } -QString LocationCompleter::createDomainCompletionString(const QString &text) -{ - QString completion = s_model->completeDomain(text); - - if (text.startsWith(QLatin1String("www."))) { - return completion.mid(text.size()); - } - - if (completion.startsWith(QLatin1String("www."))) { - completion = completion.mid(4); - } - - return completion.mid(text.size()); -} - void LocationCompleter::switchToTab(BrowserWindow* window, int tab) { Q_ASSERT(window); diff --git a/src/lib/navigation/completer/locationcompleter.h b/src/lib/navigation/completer/locationcompleter.h index 112325231..6c3753ee4 100644 --- a/src/lib/navigation/completer/locationcompleter.h +++ b/src/lib/navigation/completer/locationcompleter.h @@ -49,6 +49,7 @@ signals: void showCompletion(const QString &completion); void loadCompletion(); void clearCompletion(); + void domainCompletionChanged(); void popupClosed(); @@ -57,8 +58,10 @@ public slots: void showMostVisited(); private slots: - void currentChanged(const QModelIndex &index); void slotPopupClosed(); + void refreshJobFinished(); + + void currentChanged(const QModelIndex &index); void indexActivated(const QModelIndex &index); void indexCtrlActivated(const QModelIndex &index); @@ -66,7 +69,6 @@ private slots: void indexDeleteRequested(const QModelIndex &index); private: - QString createDomainCompletionString(const QString &text); void switchToTab(BrowserWindow* window, int tab); void loadUrl(const QUrl &url); @@ -76,7 +78,8 @@ private: BrowserWindow* m_window; LocationBar* m_locationBar; QString m_originalText; - QString m_completedDomain; + QString m_domainCompletion; + qint64 m_lastRefreshTimestamp; bool m_showingMostVisited; static LocationCompleterView* s_view; diff --git a/src/lib/navigation/completer/locationcompletermodel.cpp b/src/lib/navigation/completer/locationcompletermodel.cpp index 36d0aada0..e18c76f60 100644 --- a/src/lib/navigation/completer/locationcompletermodel.cpp +++ b/src/lib/navigation/completer/locationcompletermodel.cpp @@ -28,98 +28,22 @@ LocationCompleterModel::LocationCompleterModel(QObject* parent) : QStandardItemModel(parent) - , m_lastCompletion(QChar(QChar::Nbsp)) { } -static bool countBiggerThan(const QStandardItem* i1, const QStandardItem* i2) +void LocationCompleterModel::setCompletions(const QList &items) { - // Move bookmarks up - bool i1Bookmark = i1->data(LocationCompleterModel::BookmarkRole).toBool(); - bool i2Bookmark = i2->data(LocationCompleterModel::BookmarkRole).toBool(); + foreach (QStandardItem* item, items) { + item->setIcon(QPixmap::fromImage(item->data(ImageRole).value())); + setTabPosition(item); - if (i1Bookmark && i2Bookmark) { - return i1->data(LocationCompleterModel::CountRole).toInt() > - i2->data(LocationCompleterModel::CountRole).toInt(); - } - return i1Bookmark; -} - -void LocationCompleterModel::refreshCompletions(const QString &string) -{ - if (m_lastCompletion == string) { - refreshTabPositions(); - return; - } - - m_lastCompletion = string; - - if (string.isEmpty()) { - showMostVisited(); - return; + if (item->icon().isNull()) { + item->setIcon(IconProvider::emptyWebIcon()); + } } clear(); - - QList urlList; - QList itemList; - Type showType = (Type) qzSettings->showLocationSuggestions; - - if (showType == HistoryAndBookmarks || showType == Bookmarks) { - const int bookmarksLimit = 10; - QList bookmarks = mApp->bookmarks()->searchBookmarks(string, bookmarksLimit); - - foreach (BookmarkItem* bookmark, bookmarks) { - Q_ASSERT(bookmark->isUrl()); - - QStandardItem* item = new QStandardItem(); - item->setIcon(bookmark->icon()); - item->setText(bookmark->url().toEncoded()); - item->setData(-1, IdRole); - item->setData(bookmark->title(), TitleRole); - item->setData(bookmark->url(), UrlRole); - item->setData(bookmark->visitCount(), CountRole); - item->setData(QVariant(true), BookmarkRole); - item->setData(QVariant::fromValue(static_cast(bookmark)), BookmarkItemRole); - item->setData(string, SearchStringRole); - setTabPosition(item); - - urlList.append(bookmark->url()); - itemList.append(item); - } - } - - if (showType == HistoryAndBookmarks || showType == History) { - const int historyLimit = 20; - QSqlQuery query = createQuery(string, historyLimit); - query.exec(); - - while (query.next()) { - const QUrl url = query.value(1).toUrl(); - - if (urlList.contains(url)) { - continue; - } - - QStandardItem* item = new QStandardItem(); - item->setIcon(IconProvider::iconForUrl(url)); - item->setText(url.toEncoded()); - item->setData(query.value(0), IdRole); - item->setData(query.value(2), TitleRole); - item->setData(url, UrlRole); - item->setData(query.value(3), CountRole); - item->setData(QVariant(false), BookmarkRole); - item->setData(string, SearchStringRole); - setTabPosition(item); - - itemList.append(item); - } - } - - // Sort by count - qSort(itemList.begin(), itemList.end(), countBiggerThan); - - appendColumn(itemList); + appendColumn(items); } void LocationCompleterModel::showMostVisited() @@ -145,10 +69,10 @@ void LocationCompleterModel::showMostVisited() } } -QString LocationCompleterModel::completeDomain(const QString &text) +QSqlQuery LocationCompleterModel::createDomainQuery(const QString &text) { if (text.isEmpty() || text == QLatin1String("www.")) { - return QString(); + return QSqlQuery(); } bool withoutWww = text.startsWith(QLatin1Char('w')) && !text.startsWith(QLatin1String("www.")); @@ -179,16 +103,10 @@ QString LocationCompleterModel::completeDomain(const QString &text) sqlQuery.addBindValue(QString("https://www.%1%").arg(text)); } - sqlQuery.exec(); - - if (!sqlQuery.next()) { - return QString(); - } - - return sqlQuery.value(0).toUrl().host(); + return sqlQuery; } -QSqlQuery LocationCompleterModel::createQuery(const QString &searchString, int limit, bool exactMatch) const +QSqlQuery LocationCompleterModel::createHistoryQuery(const QString &searchString, int limit, bool exactMatch) { QStringList searchList; QString query = QLatin1String("SELECT id, url, title, count FROM history WHERE "); diff --git a/src/lib/navigation/completer/locationcompletermodel.h b/src/lib/navigation/completer/locationcompletermodel.h index eedbb0e39..137eea7ae 100644 --- a/src/lib/navigation/completer/locationcompletermodel.h +++ b/src/lib/navigation/completer/locationcompletermodel.h @@ -37,15 +37,17 @@ public: BookmarkItemRole = Qt::UserRole + 6, SearchStringRole = Qt::UserRole + 7, TabPositionWindowRole = Qt::UserRole + 8, - TabPositionTabRole = Qt::UserRole + 9 + TabPositionTabRole = Qt::UserRole + 9, + ImageRole = Qt::UserRole + 10 }; explicit LocationCompleterModel(QObject* parent = 0); - void refreshCompletions(const QString &string); + void setCompletions(const QList &items); void showMostVisited(); - QString completeDomain(const QString &text); + static QSqlQuery createHistoryQuery(const QString &searchString, int limit, bool exactMatch = false); + static QSqlQuery createDomainQuery(const QString &text); private: enum Type { @@ -55,12 +57,8 @@ private: Nothing = 4 }; - QSqlQuery createQuery(const QString &searchString, int limit, bool exactMatch = false) const; - void setTabPosition(QStandardItem* item) const; void refreshTabPositions() const; - - QString m_lastCompletion; }; #endif // LOCATIONCOMPLETERMODEL_H diff --git a/src/lib/navigation/completer/locationcompleterrefreshjob.cpp b/src/lib/navigation/completer/locationcompleterrefreshjob.cpp new file mode 100644 index 000000000..64bcd2133 --- /dev/null +++ b/src/lib/navigation/completer/locationcompleterrefreshjob.cpp @@ -0,0 +1,212 @@ +/* ============================================================ +* QupZilla - WebKit based browser +* Copyright (C) 2014 David Rosca +* +* 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 3 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, see . +* ============================================================ */ +#include "locationcompleterrefreshjob.h" +#include "locationcompletermodel.h" +#include "mainapplication.h" +#include "bookmarkitem.h" +#include "sqldatabase.h" +#include "qzsettings.h" +#include "bookmarks.h" + +#include +#include + +LocationCompleterRefreshJob::LocationCompleterRefreshJob(const QString &searchString) + : QObject() + , m_timestamp(QDateTime::currentMSecsSinceEpoch()) + , m_searchString(searchString) +{ + m_watcher = new QFutureWatcher(this); + connect(m_watcher, SIGNAL(finished()), this, SLOT(slotFinished())); + + QFuture future = QtConcurrent::run(this, &LocationCompleterRefreshJob::runJob); + m_watcher->setFuture(future); +} + +qint64 LocationCompleterRefreshJob::timestamp() const +{ + return m_timestamp; +} + +QString LocationCompleterRefreshJob::searchString() const +{ + return m_searchString; +} + +QList LocationCompleterRefreshJob::completions() const +{ + return m_items; +} + +QString LocationCompleterRefreshJob::domainCompletion() const +{ + return m_domainCompletion; +} + +void LocationCompleterRefreshJob::slotFinished() +{ + emit finished(); +} + +static bool countBiggerThan(const QStandardItem* i1, const QStandardItem* i2) +{ + // Move bookmarks up + bool i1Bookmark = i1->data(LocationCompleterModel::BookmarkRole).toBool(); + bool i2Bookmark = i2->data(LocationCompleterModel::BookmarkRole).toBool(); + + if (i1Bookmark && i2Bookmark) { + return i1->data(LocationCompleterModel::CountRole).toInt() > + i2->data(LocationCompleterModel::CountRole).toInt(); + } + return i1Bookmark; +} + +void LocationCompleterRefreshJob::runJob() +{ + if (mApp->isClosing() || !mApp) { + return; + } + + if (m_searchString.isEmpty()) { + completeMostVisited(); + } + else { + completeFromHistory(); + } + + // Load all icons into QImage + foreach (QStandardItem* item, m_items) { + const QUrl url = item->data(LocationCompleterModel::UrlRole).toUrl(); + + QSqlQuery query; + query.prepare(QSL("SELECT icon FROM icons WHERE url LIKE ? LIMIT 1")); + query.addBindValue(QString(QL1S("%1%")).arg(QString::fromUtf8(url.toEncoded(QUrl::RemoveFragment)))); + QSqlQuery res = SqlDatabase::instance()->exec(query); + + if (res.next()) { + item->setData(QImage::fromData(res.value(0).toByteArray()), LocationCompleterModel::ImageRole); + } + } + + // Sort by count + qSort(m_items.begin(), m_items.end(), countBiggerThan); + + // Get domain completion + if (!m_searchString.isEmpty() && qzSettings->useInlineCompletion) { + QSqlQuery domainQuery = LocationCompleterModel::createDomainQuery(m_searchString); + if (domainQuery.lastQuery().isEmpty()) { + return; + } + + QSqlQuery res = SqlDatabase::instance()->exec(domainQuery); + res.exec(); + if (res.next()) { + m_domainCompletion = createDomainCompletion(res.value(0).toUrl().host()); + } + } +} + +void LocationCompleterRefreshJob::completeFromHistory() +{ + QList urlList; + Type showType = (Type) qzSettings->showLocationSuggestions; + + // Search in bookmarks + if (showType == HistoryAndBookmarks || showType == Bookmarks) { + const int bookmarksLimit = 10; + QList bookmarks = mApp->bookmarks()->searchBookmarks(m_searchString, bookmarksLimit); + + foreach (BookmarkItem* bookmark, bookmarks) { + Q_ASSERT(bookmark->isUrl()); + + QStandardItem* item = new QStandardItem(); + item->setText(bookmark->url().toEncoded()); + item->setData(-1, LocationCompleterModel::IdRole); + item->setData(bookmark->title(), LocationCompleterModel::TitleRole); + item->setData(bookmark->url(), LocationCompleterModel::UrlRole); + item->setData(bookmark->visitCount(), LocationCompleterModel::CountRole); + item->setData(QVariant(true), LocationCompleterModel::BookmarkRole); + item->setData(QVariant::fromValue(static_cast(bookmark)), LocationCompleterModel::BookmarkItemRole); + item->setData(m_searchString, LocationCompleterModel::SearchStringRole); + + urlList.append(bookmark->url()); + m_items.append(item); + } + } + + // Search in history + if (showType == HistoryAndBookmarks || showType == History) { + const int historyLimit = 20; + QSqlQuery query = LocationCompleterModel::createHistoryQuery(m_searchString, historyLimit); + QSqlQuery res = SqlDatabase::instance()->exec(query); + + while (res.next()) { + const QUrl url = res.value(1).toUrl(); + + if (urlList.contains(url)) { + continue; + } + + QStandardItem* item = new QStandardItem(); + item->setText(url.toEncoded()); + item->setData(res.value(0), LocationCompleterModel::IdRole); + item->setData(res.value(2), LocationCompleterModel::TitleRole); + item->setData(url, LocationCompleterModel::UrlRole); + item->setData(res.value(3), LocationCompleterModel::CountRole); + item->setData(QVariant(false), LocationCompleterModel::BookmarkRole); + item->setData(m_searchString, LocationCompleterModel::SearchStringRole); + + m_items.append(item); + } + } +} + +void LocationCompleterRefreshJob::completeMostVisited() +{ + QSqlQuery query(QSL("SELECT id, url, title FROM history ORDER BY count DESC LIMIT 15")); + QSqlQuery res = SqlDatabase::instance()->exec(query); + + while (res.next()) { + QStandardItem* item = new QStandardItem(); + const QUrl url = res.value(1).toUrl(); + + item->setText(url.toEncoded()); + item->setData(res.value(0), LocationCompleterModel::IdRole); + item->setData(res.value(2), LocationCompleterModel::TitleRole); + item->setData(url, LocationCompleterModel::UrlRole); + item->setData(QVariant(false), LocationCompleterModel::BookmarkRole); + + m_items.append(item); + } +} + +QString LocationCompleterRefreshJob::createDomainCompletion(const QString &completion) const +{ + QString str = completion; + + if (m_searchString.startsWith(QLatin1String("www."))) { + return str.mid(m_searchString.size()); + } + + if (str.startsWith(QLatin1String("www."))) { + str = str.mid(4); + } + + return str.mid(m_searchString.size()); +} + diff --git a/src/lib/navigation/completer/locationcompleterrefreshjob.h b/src/lib/navigation/completer/locationcompleterrefreshjob.h new file mode 100644 index 000000000..06165ec96 --- /dev/null +++ b/src/lib/navigation/completer/locationcompleterrefreshjob.h @@ -0,0 +1,69 @@ +/* ============================================================ +* QupZilla - WebKit based browser +* Copyright (C) 2014 David Rosca +* +* 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 3 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, see . +* ============================================================ */ +#ifndef LOCATIONCOMPLETERREFRESHJOB_H +#define LOCATIONCOMPLETERREFRESHJOB_H + +#include + +#include "qzcommon.h" + +class QStandardItem; + +class QUPZILLA_EXPORT LocationCompleterRefreshJob : public QObject +{ + Q_OBJECT + +public: + explicit LocationCompleterRefreshJob(const QString &searchString); + + // Timestamp when the job was created + qint64 timestamp() const; + QString searchString() const; + + QList completions() const; + QString domainCompletion() const; + +signals: + void finished(); + +private slots: + void slotFinished(); + +private: + enum Type { + HistoryAndBookmarks = 0, + History = 1, + Bookmarks = 2, + Nothing = 4 + }; + + void runJob(); + void completeFromHistory(); + void completeMostVisited(); + + QString createDomainCompletion(const QString &completion) const; + + + qint64 m_timestamp; + QString m_searchString; + QString m_domainCompletion; + QList m_items; + QFutureWatcher* m_watcher; +}; + +#endif // LOCATIONCOMPLETERREFRESHJOB_H diff --git a/src/lib/navigation/locationbar.cpp b/src/lib/navigation/locationbar.cpp index 3a51cd85d..e77743194 100644 --- a/src/lib/navigation/locationbar.cpp +++ b/src/lib/navigation/locationbar.cpp @@ -89,6 +89,7 @@ LocationBar::LocationBar(BrowserWindow* window) connect(m_completer, SIGNAL(showCompletion(QString)), this, SLOT(showCompletion(QString))); connect(m_completer, SIGNAL(loadCompletion()), this, SLOT(urlEnter())); connect(m_completer, SIGNAL(clearCompletion()), this, SLOT(clearCompletion())); + connect(m_completer, SIGNAL(domainCompletionChanged()), this, SLOT(inlineCompletionChanged())); connect(m_completer, SIGNAL(popupClosed()), this, SLOT(completionPopupClosed())); connect(this, SIGNAL(textEdited(QString)), this, SLOT(textEdit())); @@ -137,11 +138,11 @@ void LocationBar::updatePlaceHolderText() setPlaceholderText(tr("Enter URL address or search on %1").arg(engineName)); } -void LocationBar::showCompletion(const QString &newText) +void LocationBar::showCompletion(const QString &completion) { m_inlineCompletionVisible = false; - LineEdit::setText(newText); + LineEdit::setText(completion); // Move cursor to the end end(false); @@ -159,6 +160,11 @@ void LocationBar::completionPopupClosed() m_popupClosed = true; } +void LocationBar::inlineCompletionChanged() +{ + repaint(); +} + QUrl LocationBar::createUrl() { QUrl urlToLoad; diff --git a/src/lib/navigation/locationbar.h b/src/lib/navigation/locationbar.h index fdc4405c2..e4c1475fe 100644 --- a/src/lib/navigation/locationbar.h +++ b/src/lib/navigation/locationbar.h @@ -69,9 +69,10 @@ private slots: void showRSSIcon(bool state); void updatePlaceHolderText(); - void showCompletion(const QString &newText); + void showCompletion(const QString &completion); void clearCompletion(); void completionPopupClosed(); + void inlineCompletionChanged(); void onLoadStarted(); void onLoadProgress(int progress); diff --git a/src/lib/tools/iconprovider.cpp b/src/lib/tools/iconprovider.cpp index 935f872b7..1009938f9 100644 --- a/src/lib/tools/iconprovider.cpp +++ b/src/lib/tools/iconprovider.cpp @@ -165,14 +165,19 @@ QImage IconProvider::emptyWebImage() } QIcon IconProvider::iconForUrl(const QUrl &url) +{ + return instance()->iconFromImage(imageForUrl(url)); +} + +QImage IconProvider::imageForUrl(const QUrl &url) { if (url.path().isEmpty()) { - return IconProvider::emptyWebIcon(); + return IconProvider::emptyWebImage(); } foreach (const BufferedIcon &ic, instance()->m_iconBuffer) { if (ic.first.toString().startsWith(url.toString())) { - return instance()->iconFromImage(ic.second); + return ic.second; } } @@ -182,17 +187,22 @@ QIcon IconProvider::iconForUrl(const QUrl &url) query.exec(); if (query.next()) { - return instance()->iconFromImage(QImage::fromData(query.value(0).toByteArray())); + return QImage::fromData(query.value(0).toByteArray()); } - return IconProvider::emptyWebIcon(); + return IconProvider::emptyWebImage(); } QIcon IconProvider::iconForDomain(const QUrl &url) +{ + return instance()->iconFromImage(imageForDomain(url)); +} + +QImage IconProvider::imageForDomain(const QUrl &url) { foreach (const BufferedIcon &ic, instance()->m_iconBuffer) { if (ic.first.host() == url.host()) { - return instance()->iconFromImage(ic.second); + return ic.second; } } @@ -202,10 +212,10 @@ QIcon IconProvider::iconForDomain(const QUrl &url) query.exec(); if (query.next()) { - return instance()->iconFromImage(QImage::fromData(query.value(0).toByteArray())); + return QImage::fromData(query.value(0).toByteArray()); } - return QIcon(); + return QImage(); } IconProvider* IconProvider::instance() diff --git a/src/lib/tools/iconprovider.h b/src/lib/tools/iconprovider.h index 7689cbe35..73bccf3eb 100644 --- a/src/lib/tools/iconprovider.h +++ b/src/lib/tools/iconprovider.h @@ -55,8 +55,11 @@ public: // Icon for url (only available for urls in history) static QIcon iconForUrl(const QUrl &url); + static QImage imageForUrl(const QUrl &url); + // Icon for domain (only available for urls in history) static QIcon iconForDomain(const QUrl &url); + static QImage imageForDomain(const QUrl &url); static IconProvider* instance(); diff --git a/src/lib/tools/sqldatabase.cpp b/src/lib/tools/sqldatabase.cpp index 4f9456242..c13ff4e06 100644 --- a/src/lib/tools/sqldatabase.cpp +++ b/src/lib/tools/sqldatabase.cpp @@ -31,7 +31,11 @@ SqlDatabase::SqlDatabase(QObject* parent) SqlDatabase::~SqlDatabase() { - // Close all databases + QMutableHashIterator i(m_databases); + while (i.hasNext()) { + i.next(); + i.value().close(); + } } QSqlDatabase SqlDatabase::databaseForThread(QThread* thread)