Summary: | Rekonq extremly slow when typing in addresses into the address field | ||
---|---|---|---|
Product: | [Unmaintained] rekonq | Reporter: | wuselwu <einmaladresse_2> |
Component: | general | Assignee: | Andrea Diamantini <adjam7> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | apaku, gtoth, k.hias, noinoin, prozac |
Priority: | NOR | ||
Version: | unspecified | ||
Target Milestone: | --- | ||
Platform: | openSUSE | ||
OS: | Unspecified | ||
Latest Commit: | Version Fixed In: | ||
Sentry Crash Report: | |||
Attachments: | bookmark file which slows rekonq down |
Description
wuselwu
2010-05-12 15:55:15 UTC
I just found out the reason for this behaviour: Rekonq seems per default to use all search engines as activated in the "web shortcuts" panel to look for the expression the user types into the address field. As "www" is rather generic, this seems to take some time and leads to delays for several seconds (looking like a dead lock to the user). This seems rather counter-intuitive to me. Rekonq should - not hang while querying search engines - start querying remote search engines only after several letters have been entered, not already after the first one - "web shortcuts" were associated with shortcuts like "gg" in the adress bar for me. I did not recognize that the search engines are used at once, as soon as letters are entered into the adress bar. This should be somehow clearer. After all, it is a privacy issue as well, as I might not want it that web queries are started at one. I'd like to add that this also hinders typing urls or doing web-shortcuts as rekonq eats keypresses. As I'm a rather quick typer, especially when searching stuff, I often end up with searching for "fo" on google instead of "foobar" even if I properly hit all keys. I always have to wait for the completion-popup to be shown to make sure the shortcut works (or url is fully taken by rekonq) which is rather tedious. Right now (0.4.68) the address bar seems completely unusable to me. Always using Google when typing in a valid www-URL, then sometime suddenly doubling the "http://"-part, very slow, hangs, etc :(. Ok, as we are working now about urlbar, let's see if we can fix also this problems. First, I really cannot reproduce the "www" hangs here and the issues in comment #3. Second, rekonq does not search on search engines for the word you type until you press enter, but it just list them. I cannot understand the problem with the "web shortcuts" in comment #1, sorry. I just can say that if you type "gg:kde", rekonq (and koqnueror) search google for kde. About Andreas's problem: in 0.4.68 we introduced a timer (200 ms) to not flash suggestions while user types. So, that's quite surely the issue. I'll work on the timer issue pushing 0.4.69 with the first fixes about this and CC'ing this bug, to know if things go smoother. Regards Thanks for taking care of this problem. For me the problem is that I really don't know what Rekonq does with the keys I enter into the URL bar. Sometimes the behaviour simply seems inconsistant. Maybe part of the problem is that keypresses are still lost or misinterpreted, as Andreas says in his comment. However, this has improved lately. Some strange things I had until a few days ago seem to work now, so I cannot reproduce them right now. I'll keep an eye an it. commit 6b4f4d69a3c599bc958ccddc5f7ac1c8648a7042 Author: Andrea Diamantini <adjam7@gmail.com> Date: Fri May 14 20:24:06 2010 +0200 This commit should fix a lot of troubles on fast urlbar typing so now situation is: - first list is shown immediately - timer decreases from 200 to 150 ms (less is pretty unuseful, I fear) - people who fast type & returnPress have KUriFilter help Hope this helps :) As promised, CCBUG:237390 diff --git a/src/urlbar/completionwidget.cpp b/src/urlbar/completionwidget.cpp index 1bb0178..b19b163 100644 --- a/src/urlbar/completionwidget.cpp +++ b/src/urlbar/completionwidget.cpp @@ -35,6 +35,7 @@ #include "application.h" #include "urlresolver.h" #include "searchengine.h" +#include "urlbar.h" // KDE Includes #include <KGlobalSettings> @@ -180,7 +181,8 @@ bool CompletionWidget::eventFilter(QObject *o, QEvent *e) if (wid && wid->isAncestorOf(_parent) && isVisible()) { ListItem *child; - + UrlBar *w; + if (type == QEvent::KeyPress) { QKeyEvent *ev = static_cast<QKeyEvent *>(e); @@ -214,12 +216,21 @@ bool CompletionWidget::eventFilter(QObject *o, QEvent *e) case Qt::Key_Enter: case Qt::Key_Return: - child = findChild<ListItem *>(QString::number(_currentIndex)); - emit chosenUrl(child->url(), Rekonq::CurrentTab); + w = qobject_cast<UrlBar *>(parent()); + if(w->text() == _typedString) + { + child = findChild<ListItem *>(QString::number(_currentIndex)); + emit chosenUrl(child->url(), Rekonq::CurrentTab); + } + else + { + // this will be used just on fast typing.. + emit chosenUrl(KUrl(w->text()), Rekonq::CurrentTab); + } ev->accept(); hide(); return true; - + case Qt::Key_Escape: hide(); return true; @@ -259,6 +270,8 @@ void CompletionWidget::itemChosen(ListItem *item, Qt::MouseButton button) void CompletionWidget::suggestUrls(const QString &text) { + _typedString = text; + QWidget *w = qobject_cast<QWidget *>(parent()); if (!w->hasFocus()) return; diff --git a/src/urlbar/completionwidget.h b/src/urlbar/completionwidget.h index 4ce8248..2d33b59 100644 --- a/src/urlbar/completionwidget.h +++ b/src/urlbar/completionwidget.h @@ -85,6 +85,8 @@ private: int _currentIndex; KService::Ptr _searchEngine; + + QString _typedString; }; #endif // COMPLETION_WIDGET_H diff --git a/src/urlbar/listitem.cpp b/src/urlbar/listitem.cpp index c6f7534..f91840d 100644 --- a/src/urlbar/listitem.cpp +++ b/src/urlbar/listitem.cpp @@ -296,6 +296,7 @@ QString SearchListItem::searchItemTitle(QString engine, QString text) return QString(i18nc("%1=search engine, e.g. Google, Wikipedia %2=text to search for", "Search %1 for <b>%2</b>", engine, text)); } + void SearchListItem::changeSearchEngine(KService::Ptr engine) { m_titleLabel->setText(searchItemTitle(engine->name(), m_text)); diff --git a/src/urlbar/urlbar.cpp b/src/urlbar/urlbar.cpp index fb98076..d2992c4 100644 --- a/src/urlbar/urlbar.cpp +++ b/src/urlbar/urlbar.cpp @@ -402,7 +402,7 @@ void UrlBar::detectTypedString(const QString &typed) if(_suggestionTimer->isActive()) _suggestionTimer->stop(); - _suggestionTimer->start(200); + _suggestionTimer->start(150); } diff --git a/src/urlbar/urlresolver.cpp b/src/urlbar/urlresolver.cpp index 12e2f76..840fd78 100644 --- a/src/urlbar/urlresolver.cpp +++ b/src/urlbar/urlresolver.cpp @@ -222,7 +222,7 @@ UrlSearchList UrlResolver::bookmarksResolution() UrlSearchList UrlResolver::placeTypedDomaineNameOnTop(UrlSearchList list) { - int i=0; + int i = 0; bool found = false; while(i<list.count() && !found) @@ -239,4 +239,3 @@ UrlSearchList UrlResolver::placeTypedDomaineNameOnTop(UrlSearchList list) return list; } - Cool, that works quite well already, key events are not eaten anymore. Only (minor) annoyance is that showing the popup still takes a second or so which makes the whole app unresponsive. Both Konqueror and Google-Chrome handle that better, there's no unresponsiveness while they show the popup... I'm using version 0.4.70. The patch in comment #6 was already commited. But I'm still having the same problem: after typing whatever character, I have to wait 10 seconds (maybe a little bit less). I've found out that this problem goes away when I delete my bookmark file (~/.kde4/share/apps/konqueror/bookmarks.xml)... this is off course not an acceptable solution. On Sunday 23 May 2010 14:02:25 eric wrote:
> https://bugs.kde.org/show_bug.cgi?id=237390
>
>
>
>
>
> --- Comment #8 from eric <prozac gmx net> 2010-05-23 14:02:19 ---
> I'm using version 0.4.70. The patch in comment #6 was already commited.
>
> But I'm still having the same problem: after typing whatever character, I
> have to wait 10 seconds (maybe a little bit less).
>
> I've found out that this problem goes away when I delete my bookmark file
> (~/.kde4/share/apps/konqueror/bookmarks.xml)... this is off course not an
> acceptable solution.
Beh, why not? We can try fixing this, forcing rekonq to delete bookmarks every
time :D
Kidding, of course. Thanks for noticing this important thing.
(In reply to comment #9) > Beh, why not? We can try fixing this, forcing rekonq to delete bookmarks every > time :D > > Kidding, of course. Thanks for noticing this important thing. I don't know if this is important, but I have a bookmark with normal western characters but also "foreign" characters like chinese. Created attachment 43883 [details]
bookmark file which slows rekonq down
above I added a bookmark file with several hundred items. just put it into ~/.kde/share/apps/konqueror, start rekonq and start typing "kde-look". it freezes rekonq for several seconds, at least at my laptop. I hope it helps. regards, mathias Using version 0.4.90 from git I can also confirm this problem. The first character I type is shown but then it hangs for about 4s after which it shows the popup with suggestions ... this also if I type only one char. I think the problem ist that there is no search index for the bookmarks. It's a plain xml-file so fulltext search will allways be slow. Couldn't the searching be done by nepomuk, which i think keeps an index of the bookmarks? I have many bookmarks (thousands), if i type a character into the address bar i have to wait like 30 seconds on a fairly fast computer. This should definitely be done in a thread and should use some sort of search index, otherwise it will allways be to slow for a large enough bookmark collection. Another solution would be to make configurable or to set a timelimit for the search. (In reply to comment #14) > I think the problem ist that there is no search index for the bookmarks. It's a > plain xml-file so fulltext search will allways be slow. Couldn't the searching > be done by nepomuk, which i think keeps an index of the bookmarks? > > I have many bookmarks (thousands), if i type a character into the address bar i > have to wait like 30 seconds on a fairly fast computer. This should definitely > be done in a thread and should use some sort of search index, otherwise it will > allways be to slow for a large enough bookmark collection. Even with thousands of bookmarks it shouldn't be _that_ slow ... just try grep and see how slow it really is :-) Well when using konqueror it works fine ... so maybe it would be worth to have a look at konqeuror's code > Another solution would be to make configurable or to set a timelimit for the > search. Ah IMHO not really a user friendly solution commit deab0dd37edbc4007a3c2cf32d31811aff0e7e2d Author: Andrea Diamantini <adjam7@gmail.com> Date: Fri Jun 4 23:21:46 2010 +0200 Awesome bar speed up This commit introduces notable changes and needs a lot of tests Courtesy patch from Mathias Kraus. Thanks :) BUG: 237390 diff --git a/src/bookmarks/bookmarksmanager.cpp b/src/bookmarks/bookmarksmanager.cpp index c430078..93bb538 100644 --- a/src/bookmarks/bookmarksmanager.cpp +++ b/src/bookmarks/bookmarksmanager.cpp @@ -203,7 +203,8 @@ QAction * BookmarkMenu::actionForBookmark(const KBookmark &bookmark) } else { - Application::bookmarkProvider()->completionObject()->addItem(bookmark.url().url()); + UrlSearchItem urlSearchItem(UrlSearchItem::Bookmark, bookmark.url().prettyUrl() , bookmark.fullText(), QDateTime(), 1, bookmark.description(), QString()); + Application::bookmarkProvider()->completionObject()->addItem(urlSearchItem); return new KBookmarkAction(bookmark, owner(), this); } } @@ -222,7 +223,6 @@ void BookmarkMenu::refill() addAddBookmarksList(); addNewFolder(); addEditBookmarks(); - } else { @@ -270,8 +270,9 @@ BookmarkProvider::BookmarkProvider(QObject *parent) , m_bookmarkMenu(0) , m_completion(0) { + kDebug() << "Loading Bookmarks Manager..."; // take care of the completion object - m_completion = new KCompletion; + m_completion = new AwesomeUrlCompletion; m_completion->setOrder(KCompletion::Weighted); KUrl bookfile = KUrl("~/.kde/share/apps/konqueror/bookmarks.xml"); // share konqueror bookmarks @@ -299,6 +300,8 @@ BookmarkProvider::BookmarkProvider(QObject *parent) // setup menu m_owner = new BookmarkOwner(this); connect(m_owner, SIGNAL(openUrl(const KUrl&, const Rekonq::OpenType &)), this, SIGNAL(openUrl(const KUrl&, const Rekonq::OpenType &))); + + kDebug() << "Loading Bookmarks Manager... DONE!"; } @@ -346,6 +349,7 @@ void BookmarkProvider::slotBookmarksChanged(const QString &group, const QString fillBookmarkBar(bookmarkToolBar); } } + //TODO: also change completion object } @@ -379,7 +383,9 @@ void BookmarkProvider::contextMenu(const QPoint &point) KActionMenu* BookmarkProvider::bookmarkActionMenu(QWidget *parent) { KMenu *menu = new KMenu(parent); + kDebug() << "new Bookmarks Menu..."; m_bookmarkMenu = new BookmarkMenu(m_manager, m_owner, menu, m_actionCollection); + kDebug() << "new Bookmarks Menu...DONE"; KActionMenu *bookmarkActionMenu = new KActionMenu(parent); bookmarkActionMenu->setMenu(menu); bookmarkActionMenu->setText(i18n("&Bookmarks")); @@ -425,7 +431,7 @@ KBookmarkGroup BookmarkProvider::rootGroup() } -KCompletion *BookmarkProvider::completionObject() const +AwesomeUrlCompletion *BookmarkProvider::completionObject() const { return m_completion; } diff --git a/src/bookmarks/bookmarksmanager.h b/src/bookmarks/bookmarksmanager.h index ae12280..dfebebd 100644 --- a/src/bookmarks/bookmarksmanager.h +++ b/src/bookmarks/bookmarksmanager.h @@ -36,13 +36,13 @@ // Local Includes #include "application.h" +#include "urlresolver.h" // Qt Includes #include <QWidget> // KDE Includes #include <KBookmarkOwner> -#include <KCompletion> // Forward Declarations class BookmarkProvider; @@ -226,19 +226,14 @@ public: */ KBookmarkGroup rootGroup(); - KBookmarkManager *bookmarkManager() - { - return m_manager; - } - BookmarkOwner *bookmarkOwner() - { - return m_owner; - } + inline KBookmarkManager *bookmarkManager() { return m_manager; } + + inline BookmarkOwner *bookmarkOwner() { return m_owner; } /** - * @returns the KCompletion object. + * @returns the AwesomeUrlCompletion object. */ - KCompletion *completionObject() const; + AwesomeUrlCompletion *completionObject() const; QString titleForBookmarkUrl(QString url); @@ -278,7 +273,7 @@ private: KActionCollection *m_actionCollection; BookmarkMenu *m_bookmarkMenu; QList<KToolBar*> m_bookmarkToolBars; - KCompletion *m_completion; + AwesomeUrlCompletion *m_completion; }; diff --git a/src/history/historymanager.cpp b/src/history/historymanager.cpp index c0f8793..d531c18 100644 --- a/src/history/historymanager.cpp +++ b/src/history/historymanager.cpp @@ -69,8 +69,9 @@ HistoryManager::HistoryManager(QObject *parent) , m_historyModel(0) , m_historyFilterModel(0) , m_historyTreeModel(0) - , m_completion(new KCompletion) + , m_completion(new AwesomeUrlCompletion) { + kDebug() << "Loading HistoryManager..."; // take care of the completion object m_completion->setOrder(KCompletion::Weighted); @@ -87,6 +88,7 @@ HistoryManager::HistoryManager(QObject *parent) // QWebHistoryInterface will delete the history manager QWebHistoryInterface::setDefaultInterface(this); + kDebug() << "Loading HistoryManager... DONE"; } @@ -131,7 +133,8 @@ void HistoryManager::addHistoryEntry(const QString &url) // Add item to completion object QString _url(url); _url.remove(QRegExp("^http://|/$")); - m_completion->addItem(_url); + UrlSearchItem urlSearchItem(UrlSearchItem::History, _url, QString(), item.dateTime, 1, QString(), QString()); + m_completion->addItem(urlSearchItem); } @@ -251,20 +254,21 @@ void HistoryManager::removeHistoryEntry(const HistoryItem &item) void HistoryManager::removeHistoryEntry(const KUrl &url, const QString &title) { + HistoryItem item; for (int i = 0; i < m_history.count(); ++i) { if (url == m_history.at(i).url && (title.isEmpty() || title == m_history.at(i).title)) { - removeHistoryEntry(m_history.at(i)); + item = m_history.at(i); + removeHistoryEntry(item); break; } } // Remove item from completion object - QString _url = url.path(); - _url.remove(QRegExp("^http://|/$")); - m_completion->removeItem(_url); + UrlSearchItem urlSearchItem(UrlSearchItem::History, item.url, item.title, item.dateTime, 0, QString(), QString()); + m_completion->removeItem(urlSearchItem); } @@ -367,9 +371,10 @@ void HistoryManager::load() lastInsertedItem = item; // Add item to completion object - QString _url = item.url; + //QString _url = item.url; //_url.remove(QRegExp("^http://|/$")); - m_completion->addItem(_url); + UrlSearchItem urlSearchItem(UrlSearchItem::History, item.url, item.title, item.dateTime, 1, QString(), QString()); + m_completion->addItem(urlSearchItem); } if (needToSort) qSort(list.begin(), list.end()); @@ -453,7 +458,7 @@ void HistoryManager::save() } -KCompletion * HistoryManager::completionObject() const +AwesomeUrlCompletion * HistoryManager::completionObject() const { return m_completion; } diff --git a/src/history/historymanager.h b/src/history/historymanager.h index 0f13178..7b82579 100644 --- a/src/history/historymanager.h +++ b/src/history/historymanager.h @@ -32,6 +32,7 @@ // Rekonq Includes #include "rekonq_defines.h" +#include "urlresolver.h" // KDE Includes #include <KUrl> @@ -113,9 +114,6 @@ class HistoryModel; class HistoryFilterModel; class HistoryTreeModel; -class KCompletion; - - /** * THE History Manager: * It manages rekonq history @@ -155,9 +153,9 @@ public: HistoryTreeModel *historyTreeModel() const; /** - * @returns the KCompletion object. + * @returns the AwesomeUrlCompletion object. */ - KCompletion *completionObject() const; + AwesomeUrlCompletion *completionObject() const; void addDownload(const QString &srcUrl, const QString &destUrl); DownloadList downloads(); @@ -189,7 +187,7 @@ private: HistoryTreeModel *m_historyTreeModel; // the completion object we sync with - KCompletion *m_completion; + AwesomeUrlCompletion *m_completion; }; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index dc1dc70..805f3d4 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -109,6 +109,7 @@ MainWindow::MainWindow() , m_hidePopup(new QTimer(this)) , m_ac(new KActionCollection(this)) { + kDebug() << "MainWindow ctor..."; // enable window size "auto-save" setAutoSaveSettings(); @@ -152,6 +153,8 @@ MainWindow::MainWindow() connect(m_hidePopup, SIGNAL(timeout()), m_popup, SLOT(hide())); QTimer::singleShot(0, this, SLOT(postLaunch())); + + kDebug() << "MainWindow ctor...DONE"; } @@ -185,6 +188,8 @@ MainWindow::~MainWindow() void MainWindow::setupToolbars() { + kDebug() << "setup toolbars..."; + // ============ Main ToolBar ================================ m_mainBar->addAction(actionByName(KStandardAction::name(KStandardAction::Back))); m_mainBar->addAction(actionByName(KStandardAction::name(KStandardAction::Forward))); @@ -267,6 +272,8 @@ QSize MainWindow::sizeHint() const void MainWindow::setupActions() { + kDebug() << "setup actions..."; + // this let shortcuts work.. actionCollection()->addAssociatedWidget(this); @@ -454,6 +461,7 @@ void MainWindow::setupActions() void MainWindow::setupTools() { + kDebug() << "setup tools..."; KActionMenu *toolsMenu = new KActionMenu(KIcon("configure"), i18n("&Tools"), this); toolsMenu->setDelayed(false); @@ -531,6 +539,7 @@ void MainWindow::setupTools() void MainWindow::setupPanels() { + kDebug() << "setup panels..."; KAction* a; // STEP 1 diff --git a/src/urlbar/listitem.cpp b/src/urlbar/listitem.cpp index a887841..c0d163c 100644 --- a/src/urlbar/listitem.cpp +++ b/src/urlbar/listitem.cpp @@ -212,8 +212,8 @@ PreviewListItem::PreviewListItem(const UrlSearchItem &item, const QString &text, QLabel *previewLabelIcon = new QLabel(this); previewLabelIcon->setFixedSize(45, 33); - new PreviewLabel(item.url.url(), 38, 29, previewLabelIcon); - IconLabel* icon = new IconLabel(item.url.url(), previewLabelIcon); + new PreviewLabel(item.url, 38, 29, previewLabelIcon); + IconLabel* icon = new IconLabel(item.url, previewLabelIcon); icon->move(27, 16); hLayout->addWidget(previewLabelIcon); @@ -223,13 +223,13 @@ PreviewListItem::PreviewListItem(const UrlSearchItem &item, const QString &text, QString title = item.title; if (title.isEmpty()) { - title = item.url.url(); + title = item.url; title = title.remove("http://"); - title.truncate(title.indexOf("/")); + title.truncate(title.indexOf("/")); } vLayout->addWidget(new TextLabel(title, text, this)); - vLayout->addWidget(new TextLabel("<i>" + item.url.url() + "</i>", text, this)); + vLayout->addWidget(new TextLabel("<i>" + item.url + "</i>", text, this)); hLayout->addLayout(vLayout); @@ -278,7 +278,7 @@ SearchListItem::SearchListItem(const UrlSearchItem &item, const QString &text, Q m_url = SearchEngine::buildQuery(engine, query); - m_iconLabel = new IconLabel("edit-find", this); //TODO: get the default engine icon + m_iconLabel = new IconLabel("edit-find", this); //TODO: get the default engine icon (will be easy in KDE SC 4.5) m_titleLabel = new TextLabel(searchItemTitle(engine->name(), query), QString(), this); m_engineBar = new EngineBar(engine, parent); @@ -397,8 +397,8 @@ BrowseListItem::BrowseListItem(const UrlSearchItem &item, const QString &text, Q QHBoxLayout *hLayout = new QHBoxLayout; hLayout->setSpacing(4); - hLayout->addWidget(new IconLabel(item.url.url(), this)); - hLayout->addWidget(new TextLabel(item.url.url(), text, this)); + hLayout->addWidget(new IconLabel(item.url, this)); + hLayout->addWidget(new TextLabel(item.url, text, this)); hLayout->addWidget(new TypeIconLabel(item.type, this)); setLayout(hLayout); diff --git a/src/urlbar/urlresolver.cpp b/src/urlbar/urlresolver.cpp index 7333e30..7131766 100644 --- a/src/urlbar/urlresolver.cpp +++ b/src/urlbar/urlresolver.cpp @@ -43,7 +43,7 @@ #include <QByteArray> // defines -#define MAX_ELEMENTS 9 +#define MAX_ELEMENTS 10 // NOTE @@ -55,12 +55,6 @@ // 5. "fixhosturifilter" -bool UrlSearchItem::operator==(const UrlSearchItem &i) const -{ - return url == i.url; -} - - // ------------------------------------------------------------------------ @@ -99,27 +93,31 @@ UrlResolver::UrlResolver(const QString &typedUrl) UrlSearchList UrlResolver::orderedSearchItems() { - // NOTE: the logic here is : "we wanna suggest (at least) 9 elements" - // so we have (more or less) 3 from first results (1 from QUrl Resolutions, 2 from - // default search engines). - // There are 6 remaining: if bookmarkResults + historyResults <= 6, catch all, else - // catch first 3 results from the two resulting lists :) - + // NOTE + // the logic here is : "we wanna suggest (at least) 10 elements" + // so we have (more or less) 2 from first results (1 from QUrl Resolutions, 1 from + // search engines). + // There are 8 remaining: if bookmarkResults + historyResults <= 8, catch all, else + // catch first 4 results from the two resulting lists :) + + QTime myTime; + myTime.start(); + UrlSearchList list; if( _typedString == QL1S("about:") ) { - UrlSearchItem home(UrlSearchItem::Browse, KUrl("about:home"), QL1S("home") ); + UrlSearchItem home(UrlSearchItem::Browse, QString("about:home"), QL1S("home") ); list << home; - UrlSearchItem favs(UrlSearchItem::Browse, KUrl("about:favorites"), QL1S("favorites") ); + UrlSearchItem favs(UrlSearchItem::Browse, QString("about:favorites"), QL1S("favorites") ); list << favs; - UrlSearchItem clos(UrlSearchItem::Browse, KUrl("about:closedTabs"), QL1S("closed tabs") ); + UrlSearchItem clos(UrlSearchItem::Browse, QString("about:closedTabs"), QL1S("closed tabs") ); list << clos; - UrlSearchItem book(UrlSearchItem::Browse, KUrl("about:bookmarks"), QL1S("bookmarks") ); + UrlSearchItem book(UrlSearchItem::Browse, QString("about:bookmarks"), QL1S("bookmarks") ); list << book; - UrlSearchItem hist(UrlSearchItem::Browse, KUrl("about:history"), QL1S("history") ); + UrlSearchItem hist(UrlSearchItem::Browse, QString("about:history"), QL1S("history") ); list << hist; - UrlSearchItem down(UrlSearchItem::Browse, KUrl("about:downloads"), QL1S("downloads") ); + UrlSearchItem down(UrlSearchItem::Browse, QString("about:downloads"), QL1S("downloads") ); list << down; return list; @@ -136,59 +134,135 @@ UrlSearchList UrlResolver::orderedSearchItems() list << qurlFromUserInputResolution(); } - - int firstResults = list.count(); - int checkPoint = 9 - firstResults; - + //find the history items that match the typed string UrlSearchList historyList = historyResolution(); UrlSearchItem privileged = privilegedItem(&historyList); int historyResults = historyList.count(); - UrlSearchList bookmarksList = bookmarksResolution(); + //find the bookmarks items that match the typed string + UrlSearchList bookmarksList = bookmarksResolution(); if (privileged.type == UrlSearchItem::Undefined) { privileged = privilegedItem(&bookmarksList); } - - if (privileged.type != UrlSearchItem::Undefined) + else if(privileged.type == UrlSearchItem::History && bookmarksList.removeOne(privileged)) { - list.insert(0,privileged); + privileged.type |= UrlSearchItem::Bookmark; } - int bookmarksResults = bookmarksList.count(); - - if (historyResults + bookmarksResults > checkPoint) + + if (privileged.type != UrlSearchItem::Undefined) { - historyList = historyList.mid(0, 3); - bookmarksList = bookmarksList.mid(0, 3); + list.prepend(privileged); } - - QList<UrlSearchItem> common; - - foreach(UrlSearchItem i, historyList) + + int availableEntries = MAX_ELEMENTS - list.count(); + + UrlSearchList commonList; + int commonResutls = 0; + + //prefer items which are history items als well bookmarks item + //if there are more than 1000 bookmark results, the performance impact is noticeable + if(bookmarksResults < 1000) { - if (!bookmarksList.contains(i)) + //add as many items to the common list as there are available entries in the dropdown list + UrlSearchItem urlSearchItem; + for(int i = 0; i < historyList.count(); i++) { - list << i; + if (bookmarksList.removeOne(historyList.at(i))) + { + urlSearchItem = historyList.takeAt(i); + urlSearchItem.type |= UrlSearchItem::Bookmark; + commonList << urlSearchItem; + commonResutls++; + if(commonResutls >= availableEntries) + { + break; + } + } } - else + + commonResutls = commonList.count(); + if(commonResutls >= availableEntries) + { + commonList = commonList.mid(0, availableEntries); + historyList = UrlSearchList(); + bookmarksList = UrlSearchList(); + availableEntries = 0; + } + else //remove all items from the history and bookmarks list up to the remaining entries in the dropdown list { - i.type |= UrlSearchItem::Bookmark; - common << i; + availableEntries -= commonResutls; + if(historyResults >= availableEntries) + { + historyList = historyList.mid(0, availableEntries); + } + if(bookmarksResults >= availableEntries) + { + bookmarksList = bookmarksList.mid(0, availableEntries); + } } } - - foreach(const UrlSearchItem &i, common) + else //if there are too many bookmarks items, remove all items up to the remaining entries in the dropdown list { - list << i; - } + + if(historyResults >= availableEntries) + { + historyList = historyList.mid(0, availableEntries); + } + if(bookmarksResults >= availableEntries) + { + bookmarksList = bookmarksList.mid(0, availableEntries); + } - foreach(const UrlSearchItem &i, bookmarksList) + UrlSearchItem urlSearchItem; + for(int i = 0; i < historyList.count(); i++) + { + if (bookmarksList.removeOne(historyList.at(i))) + { + urlSearchItem = historyList.takeAt(i); + urlSearchItem.type |= UrlSearchItem::Bookmark; + commonList << urlSearchItem; + } + } + + availableEntries -= commonList.count(); + } + + historyResults = historyList.count(); + bookmarksResults = bookmarksList.count(); + commonResutls = commonList.count(); + + //now fill the list to MAX_ELEMENTS + if(availableEntries > 0) { - if (!common.contains(i)) - list << i; + int historyEntries = ((int) (availableEntries / 2)) + availableEntries % 2; + int bookmarksEntries = availableEntries - historyEntries; + + if (historyResults >= historyEntries && bookmarksResults >= bookmarksEntries) + { + historyList = historyList.mid(0, historyEntries); + bookmarksList = bookmarksList.mid(0, bookmarksEntries); + } + else if (historyResults < historyEntries && bookmarksResults >= bookmarksEntries) + { + if(historyResults + bookmarksResults > availableEntries) + { + bookmarksList = bookmarksList.mid(0, availableEntries - historyResults); + } + } + else if (historyResults >= historyEntries && bookmarksResults < bookmarksEntries) + { + if(historyResults + bookmarksResults > availableEntries) + { + historyList = historyList.mid(0, availableEntries - bookmarksResults); + } + } } - + + list = list + historyList + commonList + bookmarksList; + qWarning() << "orderedSearchItems leave: " << " elapsed: " << myTime.elapsed(); + return list; } @@ -206,7 +280,7 @@ UrlSearchList UrlResolver::qurlFromUserInputResolution() if (urlFromUserInput.isValid()) { QString gTitle = i18nc("Browse a website", "Browse"); - UrlSearchItem gItem(UrlSearchItem::Browse, urlFromUserInput, gTitle); + UrlSearchItem gItem(UrlSearchItem::Browse, urlFromUserInput.toString(), gTitle); list << gItem; } @@ -217,57 +291,166 @@ UrlSearchList UrlResolver::qurlFromUserInputResolution() // STEP 2 = Web Searches UrlSearchList UrlResolver::webSearchesResolution() { - return UrlSearchList() << UrlSearchItem(UrlSearchItem::Search, KUrl(), QString()); + return UrlSearchList() << UrlSearchItem(UrlSearchItem::Search, QString(), QString()); } // STEP 3 = history completion UrlSearchList UrlResolver::historyResolution() { - UrlSearchList list; + AwesomeUrlCompletion *historyCompletion = Application::historyManager()->completionObject(); + return historyCompletion->substringCompletion(_typedString); +} + + +// STEP 4 = bookmarks completion +UrlSearchList UrlResolver::bookmarksResolution() +{ + AwesomeUrlCompletion *bookmarkCompletion = Application::bookmarkProvider()->completionObject(); + return bookmarkCompletion->substringCompletion(_typedString); +} + + +UrlSearchItem UrlResolver::privilegedItem(UrlSearchList* list) +{ + UrlSearchItem item; + QString dot; + if(!_typedString.endsWith(QL1C('.'))) + { + dot = QString(QL1C('.')); + } + + for(int i = 0; i<list->count(); i++) + { + item = list->at(i); + //kDebug() << item.url.host(); + //TODO: move this to AwesomeUrlCompletion::substringCompletion and add a priviledged flag to UrlSearchItem + if (item.url.contains(_typedString + dot)) + { + list->removeAt(i); + return item; + } + } + return UrlSearchItem(); +} + +// ------------------------------------------------------------------------------------------------------ + + +AwesomeUrlCompletion::AwesomeUrlCompletion() +{ + m_resetCompletion = true; +} + + +AwesomeUrlCompletion::~AwesomeUrlCompletion() +{ + +} + - KCompletion *historyCompletion = Application::historyManager()->completionObject(); - QStringList historyResults = historyCompletion->substringCompletion(_typedString); - Q_FOREACH(const QString &s, historyResults) +void AwesomeUrlCompletion::addItem(const UrlSearchItem& itemToAdd) +{ + bool match = false; + QTime myTime; + myTime.start(); + for(int i = 0; i < m_items.count(); i++) { - UrlSearchItem it(UrlSearchItem::History, KUrl(s), Application::historyManager()->titleForHistoryUrl(s)); - list << it; + //check if item is already in list; the items are equal if the url and the title are equal + if(m_items[i] == itemToAdd) + { + match = true; + //TODO: check what to do if comment or bookmarkPath are different + if(m_items[i] < itemToAdd) + { + m_items[i].visitDateTime = itemToAdd.visitDateTime; + } + m_items[i].visitCount += itemToAdd.visitCount; + } } + if(!match) + { + m_items.append(itemToAdd); + } + m_resetCompletion = true; +} - return list; + +void AwesomeUrlCompletion::removeItem(const UrlSearchItem& item) +{ + m_resetCompletion = m_items.removeOne(item); } -// STEP 4 = bookmarks completion -UrlSearchList UrlResolver::bookmarksResolution() +void AwesomeUrlCompletion::setOrder(KCompletion::CompOrder) { - UrlSearchList list; + //TODO +} - KCompletion *bookmarkCompletion = Application::bookmarkProvider()->completionObject(); - QStringList bookmarkResults = bookmarkCompletion->substringCompletion(_typedString); - Q_FOREACH(const QString &s, bookmarkResults) + +void AwesomeUrlCompletion::updateTitle(const UrlSearchItem& item, const QString& newTitle) +{ + foreach(UrlSearchItem i, m_items) { - UrlSearchItem it(UrlSearchItem::Bookmark, KUrl(s), Application::bookmarkProvider()->titleForBookmarkUrl(s)); - list << it; + if(i == item) + { + i.title = newTitle; + } } + m_resetCompletion = true; +} - return list; + +void AwesomeUrlCompletion::clear() +{ + m_items.clear(); + m_resetCompletion = true; } -UrlSearchItem UrlResolver::privilegedItem(UrlSearchList* list) +UrlSearchList AwesomeUrlCompletion::substringCompletion(const QString& completionString) { - int i=0; - while(i<list->count()) + UrlSearchList* searchList; + UrlSearchList tempList; + + if(!m_resetCompletion) { - UrlSearchItem item = list->at(i); - kDebug() << item.url.host(); - if (item.url.host().contains( _typedString + QL1C('.') ) ) + if(completionString.length() <= 1) { - list->removeAt(i); - return item; + m_resetCompletion = true; + } + if(!m_resetCompletion && completionString.length() < m_lastCompletionString.length()) + { + m_resetCompletion = true; + } + if(!m_resetCompletion && !completionString.startsWith(m_lastCompletionString, Qt::CaseInsensitive)) + { + m_resetCompletion = true; } - i++; } - return UrlSearchItem(); + + if(m_resetCompletion) + { + searchList = &m_items; + m_resetCompletion = false; + } + else + { + searchList = &m_filteredItems; + } + + Q_FOREACH(const UrlSearchItem &i, *searchList) + { + //TODO: split string and also search for each word if the are more than one word separated with space + if( i.url.contains(completionString, Qt::CaseInsensitive) + || i.title.contains(completionString, Qt::CaseInsensitive) + || i.description.contains(completionString, Qt::CaseInsensitive) + ) + { + tempList.append(i); + } + } + m_lastCompletionString = completionString; + m_filteredItems = tempList; + return m_filteredItems; } diff --git a/src/urlbar/urlresolver.h b/src/urlbar/urlresolver.h index 2249ea3..8322814 100644 --- a/src/urlbar/urlresolver.h +++ b/src/urlbar/urlresolver.h @@ -33,11 +33,14 @@ // KDE Includes #include <KUrl> +#include <KCompletion> // Qt Includes #include <QString> #include <QList> +#include <QDateTime> +class AwesomeUrlCompletion; class UrlSearchItem { @@ -53,22 +56,62 @@ public: }; int type; - KUrl url; + QString url; QString title; + QDateTime visitDateTime; + int visitCount; + QString description; + QString bookmarkPath; - UrlSearchItem(const UrlSearchItem &item) - : type(item.type), url(item.url), title(item.title) + UrlSearchItem(const UrlSearchItem &item) : type(item.type), + url(item.url), + title(item.title), + visitDateTime(item.visitDateTime), + visitCount(item.visitCount), + description(item.description), + bookmarkPath(item.bookmarkPath) {}; - UrlSearchItem() - : type(UrlSearchItem::Undefined), url(KUrl()), title("") + UrlSearchItem() : type(UrlSearchItem::Undefined), + url(QString()), + title(QString()), + visitDateTime(QDateTime()), + visitCount(0), + description(QString()), + bookmarkPath(QString()) {}; - UrlSearchItem(const int &_type, const KUrl &_url, const QString &_title = QString()) - : type(_type), url(_url), title(_title) + UrlSearchItem(const int &_type, + const QString &_url, + const QString &_title = QString(), + const QDateTime &visitDateTime = QDateTime(), + const int &visitCount = 0, + const QString &description = QString(), + const QString &bookmarkPath = QString() + ) + : type(_type), + url(_url), + title(_title), + visitDateTime(visitDateTime), + visitCount(visitCount), + description(description), + bookmarkPath(bookmarkPath) {}; - bool operator==(const UrlSearchItem &i) const; + inline bool operator==(const UrlSearchItem &i) const + { + return i.url == url;//TODO && i.title == title; + } + + inline bool operator <(const UrlSearchItem &i) const + { + return visitDateTime < i.visitDateTime; + } + + inline bool operator >(const UrlSearchItem &i) const + { + return visitDateTime > i.visitDateTime; + } }; typedef QList <UrlSearchItem> UrlSearchList; @@ -96,4 +139,29 @@ private: static QRegExp _browseRegexp; }; +// ------------------------------------------------------------------------------ + + +/** + * This class represents all searchable item for the awesomebar. + */ +class AwesomeUrlCompletion// : public KCompletion +{ +public: + AwesomeUrlCompletion(); + ~AwesomeUrlCompletion(); + void addItem(const UrlSearchItem& item); + void removeItem(const UrlSearchItem& item); + void setOrder(KCompletion::CompOrder); + void updateTitle(const UrlSearchItem& item, const QString& newTitle); + void clear(); + UrlSearchList substringCompletion(const QString& completionString); + +private: + UrlSearchList m_items; + UrlSearchList m_filteredItems; + bool m_resetCompletion; + QString m_lastCompletionString; +}; + #endif // URL_RESOLVER_H |