diff --git a/runners/bookmarks/bookmarkmatch.cpp b/runners/bookmarks/bookmarkmatch.cpp index 31eb06374..26f8a56e6 100644 --- a/runners/bookmarks/bookmarkmatch.cpp +++ b/runners/bookmarks/bookmarkmatch.cpp @@ -1,94 +1,93 @@ /* * Copyright 2007 Glenn Ergeerts * Copyright 2012 Glenn Ergeerts * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, 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 Library 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. */ #include "bookmarkmatch.h" #include -#include "favicon.h" // TODO: test -BookmarkMatch::BookmarkMatch(Favicon *favicon, const QString& searchTerm, const QString& bookmarkTitle, const QString& bookmarkURL, const QString& description ) - : m_favicon(favicon), m_searchTerm(searchTerm), m_bookmarkTitle(bookmarkTitle), m_bookmarkURL(bookmarkURL), m_description(description) +BookmarkMatch::BookmarkMatch(const QIcon &icon, const QString& searchTerm, const QString& bookmarkTitle, const QString& bookmarkURL, const QString& description ) + : m_icon(icon), m_searchTerm(searchTerm), m_bookmarkTitle(bookmarkTitle), m_bookmarkURL(bookmarkURL), m_description(description) { } Plasma::QueryMatch BookmarkMatch::asQueryMatch( Plasma::AbstractRunner* runner ) { - Plasma::QueryMatch::Type type = Plasma::QueryMatch::NoMatch; + Plasma::QueryMatch::Type type; qreal relevance = 0; if (m_bookmarkTitle.compare(m_searchTerm, Qt::CaseInsensitive) == 0 || (!m_description.isEmpty() && m_description.compare(m_searchTerm, Qt::CaseInsensitive) == 0) ) { type = Plasma::QueryMatch::ExactMatch; relevance = 1.0; } else if (m_bookmarkTitle.contains(m_searchTerm, Qt::CaseInsensitive)) { type = Plasma::QueryMatch::PossibleMatch; relevance = 0.45; } else if (!m_description.isEmpty() && m_description.contains(m_searchTerm, Qt::CaseInsensitive)) { type = Plasma::QueryMatch::PossibleMatch; relevance = 0.3; } else if (m_bookmarkURL.contains(m_searchTerm, Qt::CaseInsensitive)) { type = Plasma::QueryMatch::PossibleMatch; relevance = 0.2; } else { type = Plasma::QueryMatch::PossibleMatch; relevance = 0.18; } bool isNameEmpty = m_bookmarkTitle.isEmpty(); bool isDescriptionEmpty = m_description.isEmpty(); Plasma::QueryMatch match(runner); match.setType(type); match.setRelevance(relevance); - match.setIcon(m_favicon->iconFor(m_bookmarkURL)); + match.setIcon(m_icon); match.setSubtext(m_bookmarkURL); // Try to set the following as text in this order: name, description, url match.setText( isNameEmpty ? (!isDescriptionEmpty ? m_description : m_bookmarkURL) : m_bookmarkTitle ); match.setData(m_bookmarkURL); return match; } void BookmarkMatch::addTo(QList< BookmarkMatch >& listOfResults, bool addEvenOnNoMatch) { if(!addEvenOnNoMatch && ! ( matches(m_searchTerm, m_bookmarkTitle) || matches(m_searchTerm, m_description) || matches(m_searchTerm, m_bookmarkURL) )) { return; } listOfResults << *this; } bool BookmarkMatch::matches(const QString &search, const QString &matchingField) { return !matchingField.simplified().isEmpty() && matchingField.contains(search, Qt::CaseInsensitive); } diff --git a/runners/bookmarks/bookmarkmatch.h b/runners/bookmarks/bookmarkmatch.h index 67c9c1dc3..1b6fc5289 100644 --- a/runners/bookmarks/bookmarkmatch.h +++ b/runners/bookmarks/bookmarkmatch.h @@ -1,46 +1,46 @@ /* * Copyright 2007 Glenn Ergeerts * Copyright 2012 Glenn Ergeerts * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, 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 Library 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. */ #ifndef BOOKMARKMATCH_H #define BOOKMARKMATCH_H #include #include -#include +#include +#include -class Favicon; class BookmarkMatch { public: - BookmarkMatch(Favicon *favicon, const QString &searchTerm, const QString &bookmarkTitle, const QString &bookmarkURL, const QString &description = QString()); + BookmarkMatch(const QIcon &icon, const QString &searchTerm, const QString &bookmarkTitle, const QString &bookmarkURL, const QString &description = QString()); void addTo(QList< BookmarkMatch >& listOfResults, bool addEvenOnNoMatch); Plasma::QueryMatch asQueryMatch(Plasma::AbstractRunner *runner); private: bool matches(const QString &search, const QString &matchingField); private: - Favicon * m_favicon; + QIcon m_icon; QString m_searchTerm; QString m_bookmarkTitle; QString m_bookmarkURL; QString m_description; }; #endif // BOOKMARKMATCH_H diff --git a/runners/bookmarks/browsers/chrome.cpp b/runners/bookmarks/browsers/chrome.cpp index 4abd3ecf3..bf6a33658 100644 --- a/runners/bookmarks/browsers/chrome.cpp +++ b/runners/bookmarks/browsers/chrome.cpp @@ -1,140 +1,139 @@ /* * Copyright 2007 Glenn Ergeerts * Copyright 2012 Glenn Ergeerts * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, 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 Library 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. */ #include "chrome.h" #include "faviconfromblob.h" #include "browsers/findprofile.h" #include #include #include #include #include #include #include "bookmarksrunner_defs.h" #include class ProfileBookmarks { public: ProfileBookmarks(const Profile &profile) : m_profile(profile) {} inline QJsonArray bookmarks() { return m_bookmarks; } inline Profile profile() { return m_profile; } void tearDown() { m_profile.favicon()->teardown(); clear(); } void add(const QJsonObject &bookmarkEntry) { m_bookmarks << bookmarkEntry; } void clear() { m_bookmarks = QJsonArray(); } private: Profile m_profile; QJsonArray m_bookmarks; }; Chrome::Chrome( FindProfile* findProfile, QObject* parent ) : QObject(parent), m_watcher(new KDirWatch(this)), m_dirty(false) { const auto profiles = findProfile->find(); for(const Profile &profile : profiles) { m_profileBookmarks << new ProfileBookmarks(profile); m_watcher->addFile(profile.path()); } connect(m_watcher, &KDirWatch::created, [=] { m_dirty = true; }); } Chrome::~Chrome() { for(ProfileBookmarks *profileBookmark : qAsConst(m_profileBookmarks)) { delete profileBookmark; } } QList Chrome::match(const QString &term, bool addEveryThing) { if (m_dirty) { prepare(); } QList results; for(ProfileBookmarks *profileBookmarks : qAsConst(m_profileBookmarks)) { results << match(term, addEveryThing, profileBookmarks); } return results; } QList Chrome::match(const QString &term, bool addEveryThing, ProfileBookmarks *profileBookmarks) { QList results; const auto bookmarks = profileBookmarks->bookmarks(); + Favicon *favicon = profileBookmarks->profile().favicon(); for (const QJsonValue &bookmarkValue : bookmarks) { const QJsonObject bookmark = bookmarkValue.toObject(); - - QString url = bookmark.value(QStringLiteral("url")).toString(); - - BookmarkMatch bookmarkMatch(profileBookmarks->profile().favicon(), term, bookmark.value(QStringLiteral("name")).toString(), url); + const QString url = bookmark.value(QStringLiteral("url")).toString(); + BookmarkMatch bookmarkMatch(favicon->iconFor(url), term, bookmark.value(QStringLiteral("name")).toString(), url); bookmarkMatch.addTo(results, addEveryThing); } return results; } void Chrome::prepare() { m_dirty = false; for(ProfileBookmarks *profileBookmarks : qAsConst(m_profileBookmarks)) { Profile profile = profileBookmarks->profile(); profileBookmarks->clear(); QFile bookmarksFile(profile.path()); if (!bookmarksFile.open(QIODevice::ReadOnly | QIODevice::Text)) { continue; } QJsonDocument jdoc = QJsonDocument::fromJson(bookmarksFile.readAll()); if (jdoc.isNull()) { continue; } const QJsonObject resultMap = jdoc.object(); if (!resultMap.contains(QLatin1String("roots"))) { return; } const QJsonObject entries = resultMap.value(QStringLiteral("roots")).toObject(); for (const QJsonValue &folder : entries) { parseFolder(folder.toObject(), profileBookmarks); } profile.favicon()->prepare(); } } void Chrome::teardown() { for(ProfileBookmarks *profileBookmarks : qAsConst(m_profileBookmarks)) { profileBookmarks->tearDown(); } } void Chrome::parseFolder(const QJsonObject &entry, ProfileBookmarks *profile) { const QJsonArray children = entry.value(QStringLiteral("children")).toArray(); for (const QJsonValue &child : children) { const QJsonObject entry = child.toObject(); if(entry.value(QStringLiteral("type")).toString() == QLatin1String("folder")) parseFolder(entry, profile); else { profile->add(entry); } } } diff --git a/runners/bookmarks/browsers/firefox.cpp b/runners/bookmarks/browsers/firefox.cpp index 7ee62eae1..8ee8c6bf5 100644 --- a/runners/bookmarks/browsers/firefox.cpp +++ b/runners/bookmarks/browsers/firefox.cpp @@ -1,216 +1,217 @@ /* * Copyright 2007 Glenn Ergeerts * Copyright 2012 Glenn Ergeerts * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, 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 Library 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. */ #include "firefox.h" #include #include #include "bookmarksrunner_defs.h" #include #include #include #include #include "bookmarkmatch.h" #include "favicon.h" #include "fetchsqlite.h" #include "faviconfromblob.h" Firefox::Firefox(QObject *parent) : QObject(parent), m_favicon(new FallbackFavicon(this)), m_fetchsqlite(nullptr), m_fetchsqlite_fav(nullptr) { reloadConfiguration(); //qDebug() << "Loading Firefox Bookmarks Browser"; } Firefox::~Firefox() { if (!m_dbCacheFile.isEmpty()) { QFile db_CacheFile(m_dbCacheFile); if (db_CacheFile.exists()) { //qDebug() << "Cache file was removed: " << db_CacheFile.remove(); } } //qDebug() << "Deleted Firefox Bookmarks Browser"; } void Firefox::prepare() { if (m_dbCacheFile.isEmpty()) { m_dbCacheFile = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QStringLiteral("/bookmarkrunnerfirefoxdbfile.sqlite"); } if (m_dbCacheFile_fav.isEmpty()) { m_dbCacheFile_fav = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QStringLiteral("/bookmarkrunnerfirefoxfavdbfile.sqlite"); } if (!m_dbFile.isEmpty()) { m_fetchsqlite = new FetchSqlite(m_dbFile, m_dbCacheFile); m_fetchsqlite->prepare(); } if (!m_dbFile_fav.isEmpty()) { m_fetchsqlite_fav = new FetchSqlite(m_dbFile_fav, m_dbCacheFile_fav); m_fetchsqlite_fav->prepare(); delete m_favicon; m_favicon = nullptr; m_favicon = FaviconFromBlob::firefox(m_fetchsqlite_fav, this); } } QList< BookmarkMatch > Firefox::match(const QString& term, bool addEverything) { QList< BookmarkMatch > matches; if (!m_fetchsqlite) { return matches; } //qDebug() << "Firefox bookmark: match " << term; QString query; if (addEverything) { query = QStringLiteral("SELECT moz_bookmarks.fk, moz_bookmarks.title, moz_places.url " \ "FROM moz_bookmarks, moz_places WHERE " \ "moz_bookmarks.type = 1 AND moz_bookmarks.fk = moz_places.id"); } else { query = QString("SELECT moz_bookmarks.fk, moz_bookmarks.title, moz_places.url " \ "FROM moz_bookmarks, moz_places WHERE " \ "moz_bookmarks.type = 1 AND moz_bookmarks.fk = moz_places.id AND " \ "(moz_bookmarks.title LIKE :term OR moz_places.url LIKE :term)"); } const QMap bindVariables { {QStringLiteral(":term"), QStringLiteral("%%%1%%").arg(term)}, }; const QList results = m_fetchsqlite->query(query, bindVariables); QMultiMap uniqueResults; for(const QVariantMap &result : results) { const QString title = result.value(QStringLiteral("title")).toString(); const QUrl url = result.value(QStringLiteral("url")).toUrl(); if (url.isEmpty() || url.scheme() == QLatin1String("place")) { // Don't use bookmarks with empty url or Firefox's "place:" scheme, // e.g. used for "Most Visited" or "Recent Tags" //qDebug() << "element " << url << " was not added"; continue; } auto urlString = url.toString(); // After joining we may have multiple results for each URL: // 1) one for each bookmark folder (same or different titles) // 2) one for each tag (no title for all but the first entry) auto keyRange = uniqueResults.equal_range(urlString); auto it = keyRange.first; if (!title.isEmpty()) { while (it != keyRange.second) { if (*it == title) { // same URL and title in multiple bookmark folders break; } if (it->isEmpty()) { // add a title if there was none for the URL *it = title; break; } ++it; } } if (it == keyRange.second) { // first or unique entry uniqueResults.insert(urlString, title); } } for (auto result = uniqueResults.constKeyValueBegin(); result != uniqueResults.constKeyValueEnd(); ++result) { - BookmarkMatch bookmarkMatch(m_favicon, term, (*result).second, (*result).first); + const QString url = (*result).first; + BookmarkMatch bookmarkMatch(m_favicon->iconFor(url), term, (*result).second, url); bookmarkMatch.addTo(matches, addEverything); } return matches; } void Firefox::teardown() { if(m_fetchsqlite) { m_fetchsqlite->teardown(); delete m_fetchsqlite; m_fetchsqlite = nullptr; } if(m_fetchsqlite_fav) { m_fetchsqlite_fav->teardown(); delete m_fetchsqlite_fav; m_fetchsqlite_fav = nullptr; delete m_favicon; m_favicon = nullptr; } } void Firefox::reloadConfiguration() { KConfigGroup config(KSharedConfig::openConfig(QStringLiteral("kdeglobals")), QStringLiteral("General") ); if (QSqlDatabase::isDriverAvailable(QStringLiteral("QSQLITE"))) { KConfigGroup grp = config; /* This allows the user to specify a profile database */ m_dbFile = grp.readEntry("dbfile", QLatin1String("")); if (m_dbFile.isEmpty() || !QFile::exists(m_dbFile)) { //Try to get the right database file, the default profile is used KConfig firefoxProfile(QDir::homePath() + "/.mozilla/firefox/profiles.ini", KConfig::SimpleConfig); QStringList profilesList = firefoxProfile.groupList(); profilesList = profilesList.filter(QRegExp(QStringLiteral("^Profile\\d+$"))); int size = profilesList.size(); QString profilePath; if (size == 1) { // There is only 1 profile so we select it KConfigGroup fGrp = firefoxProfile.group(profilesList.first()); profilePath = fGrp.readEntry("Path", ""); } else { // There are multiple profiles, find the default one foreach(const QString & profileName, profilesList) { KConfigGroup fGrp = firefoxProfile.group(profileName); if (fGrp.readEntry("Default", 0)) { profilePath = fGrp.readEntry("Path", ""); break; } } } if (profilePath.isEmpty()) { //qDebug() << "No default firefox profile found"; return; } //qDebug() << "Profile " << profilePath << " found"; profilePath.prepend(QStringLiteral("%1/.mozilla/firefox/").arg(QDir::homePath())); m_dbFile = profilePath + "/places.sqlite"; grp.writeEntry("dbfile", m_dbFile); m_dbFile_fav = profilePath + "/favicons.sqlite"; } else { auto dir = QDir(m_dbFile); if (dir.cdUp()) { QString profilePath = dir.absolutePath(); m_dbFile_fav = profilePath + "/favicons.sqlite"; } } } else { //qDebug() << "SQLITE driver isn't available"; } } diff --git a/runners/bookmarks/browsers/kdebrowser.cpp b/runners/bookmarks/browsers/kdebrowser.cpp index f4ddfe38e..7072d1652 100644 --- a/runners/bookmarks/browsers/kdebrowser.cpp +++ b/runners/bookmarks/browsers/kdebrowser.cpp @@ -1,105 +1,106 @@ /* * Copyright 2007 Glenn Ergeerts * Copyright 2012 Glenn Ergeerts * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, 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 Library 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. */ #include "kdebrowser.h" #include "bookmarkmatch.h" #include "favicon.h" #include #include #include #include #include QIcon KDEFavicon::iconFor(const QString &url) { const QString iconFile = KIO::favIconForUrl(QUrl(url)); if (iconFile.isEmpty()) { return defaultIcon(); } return QIcon::fromTheme(iconFile); } KDEFavicon::KDEFavicon(QObject *parent) : Favicon(parent) {} KDEBrowser::KDEBrowser(QObject *parent) : QObject(parent), m_bookmarkManager(KBookmarkManager::userBookmarksManager()), m_favicon(new KDEFavicon(this)) { } QList< BookmarkMatch > KDEBrowser::match(const QString& term, bool addEverything) { KBookmarkGroup bookmarkGroup = m_bookmarkManager->root(); QList< BookmarkMatch > matches; QStack groups; KBookmark bookmark = bookmarkGroup.first(); while (!bookmark.isNull()) { // if (!context.isValid()) { // return; // } TODO: restore? if (bookmark.isSeparator()) { bookmark = bookmarkGroup.next(bookmark); continue; } if (bookmark.isGroup()) { // descend //qDebug(kdbg_code) << "descending into" << bookmark.text(); groups.push(bookmarkGroup); bookmarkGroup = bookmark.toGroup(); bookmark = bookmarkGroup.first(); while (bookmark.isNull() && !groups.isEmpty()) { // if (!context.isValid()) { // return; // } TODO: restore? bookmark = bookmarkGroup; bookmarkGroup = groups.pop(); bookmark = bookmarkGroup.next(bookmark); } continue; } - - BookmarkMatch bookmarkMatch(m_favicon, term, bookmark.text(), bookmark.url().url() ); + + const QString url = bookmark.url().url(); + BookmarkMatch bookmarkMatch(m_favicon->iconFor(url), term, bookmark.text(), url); bookmarkMatch.addTo(matches, addEverything); bookmark = bookmarkGroup.next(bookmark); while (bookmark.isNull() && !groups.isEmpty()) { // if (!context.isValid()) { // return; // } // TODO: restore? bookmark = bookmarkGroup; bookmarkGroup = groups.pop(); ////qDebug() << "ascending from" << bookmark.text() << "to" << bookmarkGroup.text(); bookmark = bookmarkGroup.next(bookmark); } } return matches; } diff --git a/runners/bookmarks/browsers/opera.cpp b/runners/bookmarks/browsers/opera.cpp index 432371c85..ebbf7fad4 100644 --- a/runners/bookmarks/browsers/opera.cpp +++ b/runners/bookmarks/browsers/opera.cpp @@ -1,101 +1,101 @@ /* * Copyright 2007 Glenn Ergeerts * Copyright 2012 Glenn Ergeerts * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, 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 Library 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. */ #include "opera.h" #include #include "bookmarksrunner_defs.h" #include #include #include "favicon.h" Opera::Opera(QObject* parent): QObject(parent), m_favicon(new FallbackFavicon(this)) { } QList Opera::match( const QString& term, bool addEverything ) { QList matches; QLatin1String nameStart("\tNAME="); QLatin1String urlStart("\tURL="); QLatin1String descriptionStart("\tDESCRIPTION="); // search for (const QString & entry : qAsConst(m_operaBookmarkEntries)) { QStringList entryLines = entry.split(QStringLiteral("\n")); if (!entryLines.first().startsWith(QLatin1String("#URL"))) { continue; // skip folder entries } entryLines.pop_front(); QString name; QString url; QString description; for (const QString & line : qAsConst(entryLines)) { if (line.startsWith(nameStart)) { name = line.mid( QString(nameStart).length() ).simplified(); } else if (line.startsWith(urlStart)) { url = line.mid( QString(urlStart).length() ).simplified(); } else if (line.startsWith(descriptionStart)) { description = line.mid(QString(descriptionStart).length()) .simplified(); } } - BookmarkMatch bookmarkMatch(m_favicon, term, name, url, description); + BookmarkMatch bookmarkMatch(m_favicon->iconFor(url), term, name, url, description); bookmarkMatch.addTo(matches, addEverything); } return matches; } void Opera::prepare() { // open bookmarks file QString operaBookmarksFilePath = QDir::homePath() + "/.opera/bookmarks.adr"; QFile operaBookmarksFile(operaBookmarksFilePath); if (!operaBookmarksFile.open(QIODevice::ReadOnly | QIODevice::Text)) { //qDebug() << "Could not open Operas Bookmark File " + operaBookmarksFilePath; return; } // check format QString firstLine = operaBookmarksFile.readLine(); if (firstLine.compare(QLatin1String("Opera Hotlist version 2.0\n"))) { //qDebug() << "Format of Opera Bookmarks File might have changed."; } operaBookmarksFile.readLine(); // skip options line ("Options: encoding = utf8, version=3") operaBookmarksFile.readLine(); // skip empty line // load contents QString contents = operaBookmarksFile.readAll(); m_operaBookmarkEntries = contents.split(QStringLiteral("\n\n"), QString::SkipEmptyParts); // close file operaBookmarksFile.close(); } void Opera::teardown() { m_operaBookmarkEntries.clear(); }