00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "bookmarksrunner.h"
00021
00022 #include <QDBusInterface>
00023 #include <QDBusReply>
00024 #include <QList>
00025 #include <QStack>
00026 #include <QSqlQuery>
00027 #include <QDir>
00028
00029 #include <KIcon>
00030 #include <KBookmarkManager>
00031 #include <KToolInvocation>
00032 #include <KUrl>
00033 #include <KStandardDirs>
00034 #include <KDebug>
00035 #include <KIO/Job>
00036
00037 BookmarksRunner::BookmarksRunner( QObject* parent, const QVariantList &args )
00038 : Plasma::AbstractRunner(parent, args)
00039 {
00040 Q_UNUSED(args)
00041 setObjectName("Bookmarks");
00042 m_icon = KIcon("bookmarks");
00043 m_bookmarkManager = KBookmarkManager::userBookmarksManager();
00044 m_browser = whichBrowser();
00045 m_dbCacheFile = KStandardDirs::locateLocal("cache", "") + "bookmarkrunnerfirefoxdbfile.sqlite";
00046 addSyntax(Plasma::RunnerSyntax(":q:", i18n("Finds web browser bookmarks matching :q:.")));
00047 addSyntax(Plasma::RunnerSyntax(i18nc("list of all web browser bookmarks", "bookmarks"),
00048 i18n("List all web browser bookmarks")));
00049
00050 connect(this, SIGNAL(prepare()), this, SLOT(prep()));
00051 connect(this, SIGNAL(teardown()), this, SLOT(down()));
00052
00053 reloadConfiguration();
00054 }
00055
00056 BookmarksRunner::~BookmarksRunner()
00057 {
00058 }
00059
00060 void BookmarksRunner::reloadConfiguration()
00061 {
00062 if (QSqlDatabase::isDriverAvailable("QSQLITE")) {
00063 KConfigGroup grp = config();
00064
00065 m_dbFile = grp.readEntry<QString>("dbfile", "");
00066 if (m_dbFile.isEmpty()) {
00067 KConfig firefoxProfile(QDir::homePath() + "/.mozilla/firefox/profiles.ini",
00068 KConfig::SimpleConfig);
00069 QStringList profilesList = firefoxProfile.groupList();
00070 profilesList = profilesList.filter(QRegExp("^Profile\\d+$"));
00071 int size = profilesList.size();
00072
00073 QString profilePath;
00074 if (size == 1) {
00075
00076 KConfigGroup fGrp = firefoxProfile.group(profilesList.first());
00077 profilePath = fGrp.readEntry("Path", "");
00078 } else {
00079
00080 foreach(const QString & profileName, profilesList) {
00081 KConfigGroup fGrp = firefoxProfile.group(profileName);
00082 if (fGrp.readEntry<int>("Default", 0)) {
00083 profilePath = fGrp.readEntry("Path", "");
00084 break;
00085 }
00086 }
00087 }
00088
00089 if (profilePath.isEmpty()) {
00090 kDebug() << "No default firefox profile found";
00091 m_db = QSqlDatabase();
00092 return;
00093 }
00094
00095 profilePath.prepend(QString("%1/.mozilla/firefox/").arg(QDir::homePath()));
00096 m_dbFile = profilePath + "/places.sqlite";
00097 grp.writeEntry("dbfile", m_dbFile);
00098 }
00099 m_db = QSqlDatabase::addDatabase("QSQLITE");
00100 m_db.setHostName("localhost");
00101 } else {
00102 kDebug() << "SQLITE driver isn't available";
00103 m_db = QSqlDatabase();
00104 }
00105 }
00106
00107 void BookmarksRunner::prep()
00108 {
00109 m_browser = whichBrowser();
00110 if (m_browser == Firefox) {
00111 if (m_db.isValid()) {
00112 kDebug() << "Cache file was removed: " << QFile(m_dbCacheFile).remove();
00113 kDebug() << "Database was copyed: " << QFile(m_dbFile).copy(m_dbCacheFile);
00114 m_db.setDatabaseName(m_dbCacheFile);
00115 m_dbOK = m_db.open();
00116 kDebug() << "Database was opened: " << m_dbOK;
00117 }
00118 }
00119 }
00120
00121 void BookmarksRunner::down()
00122 {
00123 if (m_db.isOpen()) {
00124 m_db.close();
00125 m_dbOK = false;
00126 QFile db_CacheFile(m_dbCacheFile);
00127 if (db_CacheFile.exists()) {
00128 kDebug() << "Cache file was removed: " << db_CacheFile.remove();
00129 }
00130 }
00131 }
00132
00133 void BookmarksRunner::match(Plasma::RunnerContext &context)
00134 {
00135 const QString term = context.query();
00136 if (term.length() < 3) {
00137 return;
00138 }
00139 bool allBookmarks = term.compare(i18nc("list of all konqueror bookmarks", "bookmarks"),
00140 Qt::CaseInsensitive) == 0;
00141 if (m_browser == Konqueror) {
00142 matchKonquerorBookmarks(context, allBookmarks, term);
00143 } else if (m_browser == Firefox) {
00144 matchFirefoxBookmarks(context, allBookmarks, term);
00145 }
00146 }
00147
00148 KIcon BookmarksRunner::favicon(const KUrl &url)
00149 {
00150
00151 QDBusInterface favicon("org.kde.kded", "/modules/favicons", "org.kde.FavIcon");
00152 QDBusReply<QString> reply = favicon.call("iconForUrl", url.url());
00153
00154 if (!reply.isValid()) {
00155 return KIcon();
00156 }
00157
00158
00159 const QString iconFile = KGlobal::dirs()->findResource("cache",reply.value()+".png");
00160 if(iconFile.isNull()) {
00161 return KIcon();
00162 }
00163
00164 KIcon icon = KIcon(iconFile);
00165
00166 return icon;
00167 }
00168
00169 void BookmarksRunner::matchKonquerorBookmarks(Plasma::RunnerContext& context, bool allBookmarks,
00170 const QString& term)
00171 {
00172 KBookmarkGroup bookmarkGroup = m_bookmarkManager->root();
00173
00174 QList<Plasma::QueryMatch> matches;
00175 QStack<KBookmarkGroup> groups;
00176
00177 KBookmark bookmark = bookmarkGroup.first();
00178 while (!bookmark.isNull()) {
00179 if (!context.isValid()) {
00180 return;
00181 }
00182
00183 if (bookmark.isGroup()) {
00184
00185 groups.push(bookmarkGroup);
00186 bookmarkGroup = bookmark.toGroup();
00187 bookmark = bookmarkGroup.first();
00188
00189 while (bookmark.isNull() && !groups.isEmpty()) {
00190 if (!context.isValid()) {
00191 return;
00192 }
00193
00194 bookmark = bookmarkGroup;
00195 bookmarkGroup = groups.pop();
00196 bookmark = bookmarkGroup.next(bookmark);
00197 }
00198
00199 continue;
00200 }
00201
00202 Plasma::QueryMatch::Type type = Plasma::QueryMatch::NoMatch;
00203 qreal relevance = 0;
00204
00205 const QString text = bookmark.text();
00206 const QString url = bookmark.url().prettyUrl();
00207 if (text.compare(term, Qt::CaseInsensitive) == 0) {
00208 type = Plasma::QueryMatch::ExactMatch;
00209 relevance = 1.0;
00210 } else if (text.contains(term, Qt::CaseInsensitive)) {
00211 type = Plasma::QueryMatch::PossibleMatch;
00212 relevance = 0.45;
00213 } else if (url.contains(term, Qt::CaseInsensitive)) {
00214 type = Plasma::QueryMatch::PossibleMatch;
00215 relevance = 0.2;
00216 } else if (allBookmarks) {
00217 type = Plasma::QueryMatch::PossibleMatch;
00218 relevance = 0.18;
00219 }
00220
00221 if (type != Plasma::QueryMatch::NoMatch) {
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233 Plasma::QueryMatch match(this);
00234 match.setType(type);
00235 match.setRelevance(relevance);
00236 match.setIcon(m_icon);
00237 match.setText(bookmark.text());
00238 match.setData(bookmark.url().url());
00239 matches << match;
00240 }
00241
00242 bookmark = bookmarkGroup.next(bookmark);
00243 while (bookmark.isNull() && !groups.isEmpty()) {
00244 if (!context.isValid()) {
00245 return;
00246 }
00247
00248 bookmark = bookmarkGroup;
00249 bookmarkGroup = groups.pop();
00250
00251 bookmark = bookmarkGroup.next(bookmark);
00252 }
00253 }
00254 context.addMatches(term, matches);
00255 }
00256
00257 void BookmarksRunner::matchFirefoxBookmarks(Plasma::RunnerContext& context, bool allBookmarks, const QString& term)
00258 {
00259 if (!m_dbOK) {
00260 return;
00261 }
00262
00263 QList<int> fks;
00264 QHash<int, QString> titles;
00265 QHash<int, QUrl> urls;
00266 QHash<int, KIcon> icons;
00267 QString tmpTerm = term;
00268 QSqlQuery query;
00269 if (allBookmarks) {
00270 query = QSqlQuery("SELECT moz_bookmarks.fk, moz_bookmarks.title, moz_places.url," \
00271 "moz_places.favicon_id FROM moz_bookmarks, moz_places WHERE " \
00272 "moz_bookmarks.type = 1 AND moz_bookmarks.fk = moz_places.id");
00273 } else {
00274 const QString escapedTerm = tmpTerm.replace("'", "\\'");
00275 query = QSqlQuery("SELECT moz_bookmarks.fk, moz_bookmarks.title, moz_places.url," \
00276 "moz_places.favicon_id FROM moz_bookmarks, moz_places WHERE " \
00277 "moz_bookmarks.type = 1 AND moz_bookmarks.fk = moz_places.id AND " \
00278 "(moz_bookmarks.title LIKE '%" + escapedTerm + "%' or moz_places.url LIKE '%"
00279 + escapedTerm + "%')");
00280 }
00281 while (query.next()) {
00282 const QString title = query.value(1).toString();
00283 const QUrl url = query.value(2).toString();
00284
00285
00286 int fk = query.value(0).toInt();
00287 fks << fk;
00288 titles.insert(fk, title);
00289 urls.insert(fk, url);
00290 icons.insert(fk, m_icon);
00291 }
00292
00293 if (!context.isValid()) {
00294 return;
00295 }
00296
00297 QList<Plasma::QueryMatch> matches;
00298 foreach (const int& fk, fks) {
00299 Plasma::QueryMatch match(this);
00300 match.setIcon(icons[fk]);
00301 match.setText(titles[fk]);
00302 match.setData(urls[fk]);
00303 matches << match;
00304 }
00305 context.addMatches(term, matches);
00306 }
00307
00308 BookmarksRunner::Browser BookmarksRunner::whichBrowser()
00309 {
00310 KConfigGroup config(KSharedConfig::openConfig("kdeglobals"), QLatin1String("General") );
00311 QString exec = config.readPathEntry( QLatin1String("BrowserApplication"), QString("") );
00312 kDebug() << exec;
00313 if (exec.contains("firefox", Qt::CaseInsensitive)) {
00314 return Firefox;
00315 } else if (exec.contains("konqueror", Qt::CaseInsensitive)) {
00316 return Konqueror;
00317 } else {
00318 return Default;
00319 }
00320 }
00321
00322 void BookmarksRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &action)
00323 {
00324 Q_UNUSED(context);
00325 KUrl url = (KUrl)action.data().toString();
00326
00327 KToolInvocation::invokeBrowser(url.url());
00328 }
00329
00330 #include "bookmarksrunner.moc"