From 942c55b945443a2e6dd9a2d3660347fc2176630a Mon Sep 17 00:00:00 2001 From: Andrea Diamantini Date: Mon, 29 Mar 2010 11:47:42 +0200 Subject: This commit merge all our work about new UrlBar. DISCLAIMER: this is far from perfect, but we finally have a good starting point to work on.. :) Jonas Gastal started working on it in the 0.3 times, startin from CompletionBase code .. .. I did some work on another idea, proposing (in code) a new "suggest engine" created from scratch... Lionel Chauvin finally merged our ideas and implemented what you are seeing (and improved it, too!).. - New suggestion items (Firefox style) - a mockup on the known urls (rekonq style) - for now, automatic Google and Wikipedia searches (more coming).. - a beautiful animation :) - quite all rough edges smoothed -------------------------------------------------------- Squashed commit of the following: commit d9cf43da421c7f6c71f78444ff1935c414468b98 commit 9dcb6e18f8a3e9ae8ef1cd1299d47d37393aa6e5 commit 6c4bf2b2040ea20c78c5703f20c6bc88b7e40169 commit 8488df67115d186489f34210b638c150c66f62d3 commit 066ab907661282b1ffa4cf640739c20b4c7b6556 commit c23e23cbca7ab3197c570651a95d3f8fea270d78 commit 60655b0a8685a76e2b8b7a457bfded974bc98b4c commit 9a8817db124b55f501c9e5d3415a975ee6f92d68 commit 61312b6b577a535a4d56758b3bd3ea38812d5139 commit b6a3f4ea12423a063eafa641cedd13b890b9d392 commit 5e8e2f851edb42bc2deed296c26c58c3d7570381 commit 2904d828f71ac8ff46a53e58da8f45b5aa16e7ef --------------------------------------------------------- --- src/CMakeLists.txt | 3 + src/bookmarks/bookmarksmanager.cpp | 14 ++- src/bookmarks/bookmarksmanager.h | 7 ++ src/mainview.cpp | 3 +- src/urlbar/completionwidget.cpp | 242 +++++++++++++++++++++++++++++++++++++ src/urlbar/completionwidget.h | 77 ++++++++++++ src/urlbar/lineedit.cpp | 4 +- src/urlbar/lineedit.h | 12 +- src/urlbar/listitem.cpp | 173 ++++++++++++++++++++++++++ src/urlbar/listitem.h | 59 +++++++++ src/urlbar/urlbar.cpp | 200 +++++++++++++++--------------- src/urlbar/urlbar.h | 28 ++--- src/urlbar/urlresolver.cpp | 177 +++++++++++++++++++++++++++ src/urlbar/urlresolver.h | 72 +++++++++++ 14 files changed, 939 insertions(+), 132 deletions(-) create mode 100644 src/urlbar/completionwidget.cpp create mode 100644 src/urlbar/completionwidget.h create mode 100644 src/urlbar/listitem.cpp create mode 100644 src/urlbar/listitem.h create mode 100644 src/urlbar/urlresolver.cpp create mode 100644 src/urlbar/urlresolver.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0cab993c..a68faa59 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -49,6 +49,9 @@ SET( rekonq_KDEINIT_SRCS #---------------------------------------- urlbar/urlbar.cpp urlbar/lineedit.cpp + urlbar/completionwidget.cpp + urlbar/urlresolver.cpp + urlbar/listitem.cpp ) diff --git a/src/bookmarks/bookmarksmanager.cpp b/src/bookmarks/bookmarksmanager.cpp index 9feed63a..89e39ef8 100644 --- a/src/bookmarks/bookmarksmanager.cpp +++ b/src/bookmarks/bookmarksmanager.cpp @@ -161,7 +161,12 @@ BookmarkProvider::BookmarkProvider(QObject *parent) , m_actionCollection(new KActionCollection(this)) , m_bookmarkMenu(0) , m_bookmarkToolBar(0) + , m_completion(0) { + // take care of the completion object + m_completion = new KCompletion; + m_completion->setOrder( KCompletion::Weighted ); + KUrl bookfile = KUrl("~/.kde/share/apps/konqueror/bookmarks.xml"); // share konqueror bookmarks if (!QFile::exists(bookfile.path())) @@ -222,6 +227,7 @@ void BookmarkProvider::slotBookmarksChanged(const QString &group, const QString return; m_bookmarkToolBar->clear(); // FIXME CRASH + m_completion->clear(); KBookmark bookmark = toolBarGroup.first(); while (!bookmark.isNull()) @@ -287,7 +293,8 @@ KAction *BookmarkProvider::fillBookmarkBar(const KBookmark &bookmark) return a; } else - { + { + m_completion->addItem(bookmark.url().path()); return new KBookmarkAction(bookmark, m_owner, this); } } @@ -297,3 +304,8 @@ KBookmarkGroup BookmarkProvider::rootGroup() { return m_manager->root(); } + +KCompletion *BookmarkProvider::completionObject() const +{ + return m_completion; +} diff --git a/src/bookmarks/bookmarksmanager.h b/src/bookmarks/bookmarksmanager.h index e50148e4..18ff3ef0 100644 --- a/src/bookmarks/bookmarksmanager.h +++ b/src/bookmarks/bookmarksmanager.h @@ -39,6 +39,7 @@ // KDE Includes #include +#include // Forward Declarations class BookmarkProvider; @@ -213,6 +214,11 @@ public: KBookmarkManager *bookmarkManager() { return m_manager; } BookmarkOwner *bookmarkOwner() { return m_owner; } + /** + * @returns the KCompletion object. + */ + KCompletion *completionObject() const; + signals: /** * @short This signal is emitted when an url has to be loaded @@ -247,6 +253,7 @@ private: KActionCollection *m_actionCollection; BookmarkMenu *m_bookmarkMenu; KToolBar *m_bookmarkToolBar; + KCompletion *m_completion; }; #endif diff --git a/src/mainview.cpp b/src/mainview.cpp index f2152364..6643becb 100644 --- a/src/mainview.cpp +++ b/src/mainview.cpp @@ -242,8 +242,7 @@ void MainView::clear() { // FIXME (the programmer, not the code) // What exactly do we need to clear here? - m_urlBar->clearHistory(); - m_urlBar->clear(); + m_urlBar->clear(); m_recentlyClosedTabs.clear(); } diff --git a/src/urlbar/completionwidget.cpp b/src/urlbar/completionwidget.cpp new file mode 100644 index 00000000..42abcb73 --- /dev/null +++ b/src/urlbar/completionwidget.cpp @@ -0,0 +1,242 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Andrea Diamantini +* +* +* 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 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* 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 . +* +* ============================================================ */ + + +// Self Includes +#include "completionwidget.h" +#include "completionwidget.moc" + +// KDE Includes +#include +#include +#include + +// Qt Includes +#include +#include +#include +#include +#include +#include + +#define MAX_ELEMENTS 9 +#include "application.h" + +CompletionWidget::CompletionWidget( QWidget *parent) +:QFrame( parent, Qt::ToolTip) + , _parent(parent) + , _currentIndex(-1) +{ + QPalette p(palette()); + p.setColor(QPalette::Background, Qt::white); //todo: choose the correct color + setPalette(p); + setFrameStyle(QFrame::Panel); + setLayoutDirection(Qt::LeftToRight); + QVBoxLayout *layout = new QVBoxLayout; + layout->setMargin(0); + setLayout(layout); + +} + + +void CompletionWidget::insertSearchList(const UrlSearchList &list) +{ + _list = list; + int min = MAX_ELEMENTS; + if(list.count() < min) + min = list.count(); + + for(int i = 0; isetObjectName( QString::number(i) ); + layout()->addWidget( suggestion ); + } +} + + +void CompletionWidget::sizeAndPosition() +{ + // size + setFixedHeight(layout()->count() * 44 ); + setFixedWidth( _parent->width() ); + + // position + QPoint p = _parent->mapToGlobal( QPoint(0,0) ); + move(p.x(), p.y() + _parent->height()); +} + + +void CompletionWidget::popup() +{ + down(); + sizeAndPosition(); + if (!isVisible()) + show(); +} + + +void CompletionWidget::up() +{ + // deactivate previous + if(_currentIndex != -1) + { + ListItem *widget = findChild( QString::number(_currentIndex) ); + widget->deactivate(); + } + + if(_currentIndex > 0) + _currentIndex--; + else + _currentIndex=layout()->count()-1; + + // activate "new" current + ListItem *widget = findChild( QString::number(_currentIndex) ); + widget->activate(); +} + +KUrl CompletionWidget::currentUrl() +{ + return _list.at(_currentIndex).url; +} + +void CompletionWidget::down() +{ + // deactivate previous + if(_currentIndex != -1) + { + ListItem *widget = findChild( QString::number(_currentIndex) ); + widget->deactivate(); + } + + if(_currentIndex < _list.count() -1) + _currentIndex++; + else + _currentIndex=0; + + // activate "new" current + ListItem *widget = findChild( QString::number(_currentIndex) ); + widget->activate(); +} + +void CompletionWidget::clear() +{ + QLayoutItem *child; + while ((child = layout()->takeAt(0)) != 0) + { + delete child->widget(); + delete child; + } + _currentIndex = -1; +} + + +bool CompletionWidget::eventFilter( QObject *o, QEvent *e ) +{ + int type = e->type(); + QWidget *wid = qobject_cast(o); + + if (o == this) + { + return false; + } + + //hide conditions of the CompletionWidget + if (wid + && ((wid == _parent && (type == QEvent::Move || type == QEvent::Resize)) + || ((wid->windowFlags() & Qt::Window) + && (type == QEvent::Move || type == QEvent::Hide || type == QEvent::WindowDeactivate) + && wid == _parent->window()) + || (type == QEvent::MouseButtonPress && !isAncestorOf(wid))) + ) + { + hide(); + return false; + } + + //actions on the CompletionWidget + if (wid && wid->isAncestorOf(_parent) && isVisible()) + { + if ( type == QEvent::KeyPress ) + { + QKeyEvent *ev = static_cast( e ); + switch ( ev->key() ) + { + case Qt::Key_Up: + case Qt::Key_Backtab: + if (ev->modifiers() == Qt::NoButton || (ev->modifiers() & Qt::ShiftModifier)) + { + up(); + ev->accept(); + return true; + } + break; + + case Qt::Key_Down: + case Qt::Key_Tab: + if (ev->modifiers() == Qt::NoButton) + { + down(); + ev->accept(); + return true; + } + break; + + case Qt::Key_Return: + hide(); + emit chosenUrl(currentUrl().url()); + ev->accept(); + return true; + break; + } + } + } + + return QFrame::eventFilter(o,e); +} + + +void CompletionWidget::setVisible( bool visible ) +{ + if (visible) + { + Application::instance()->installEventFilter(this); + } + else + { + Application::instance()->removeEventFilter(this); + } + + QFrame::setVisible(visible); +} + + +void CompletionWidget::itemChosen(ListItem *item) +{ + emit chosenUrl(_list.at(layout()->indexOf(item)).url); + hide(); +} \ No newline at end of file diff --git a/src/urlbar/completionwidget.h b/src/urlbar/completionwidget.h new file mode 100644 index 00000000..7b474bd8 --- /dev/null +++ b/src/urlbar/completionwidget.h @@ -0,0 +1,77 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Andrea Diamantini +* +* +* 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 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* 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 COMPLETION_WIDGET_H +#define COMPLETION_WIDGET_H + + +// Local Includes +#include "urlresolver.h" +#include "listitem.h" + +// Qt Includes +#include + +// KDE Includes +#include + +// Forward Declarations +class KUrl; + + +class CompletionWidget : public QFrame +{ +Q_OBJECT + +public: + CompletionWidget(QWidget *parent); + + void insertSearchList(const UrlSearchList &list); + void popup(); + + void up(); + void down(); + void clear(); + virtual bool eventFilter(QObject *obj, QEvent *ev); + void setVisible(bool visible); + KUrl currentUrl(); + +private slots: + void itemChosen(ListItem *item); + +signals: + void chosenUrl(const QString&); + +private: + void sizeAndPosition(); + + QWidget *_parent; + + UrlSearchList _list; + int _currentIndex; +}; + +#endif // COMPLETION_WIDGET_H diff --git a/src/urlbar/lineedit.cpp b/src/urlbar/lineedit.cpp index db36bd0c..f3c93e8e 100644 --- a/src/urlbar/lineedit.cpp +++ b/src/urlbar/lineedit.cpp @@ -2,9 +2,9 @@ * * This file is a part of the rekonq project * -* Copyright (C) 2009-2010 by Andrea Diamantini +* Copyright (C) 2009 by Andrea Diamantini * Copyright (C) 2009 by Paweł Prażak -* Copyright (C) 2009-2010 by Lionel Chauvin +* Copyright (C) 2009 by Lionel Chauvin * * * This program is free software; you can redistribute it and/or diff --git a/src/urlbar/lineedit.h b/src/urlbar/lineedit.h index 1ac3af2e..d76a5fcb 100644 --- a/src/urlbar/lineedit.h +++ b/src/urlbar/lineedit.h @@ -2,9 +2,9 @@ * * This file is a part of the rekonq project * -* Copyright (C) 2009-2010 by Andrea Diamantini +* Copyright (C) 2009 by Andrea Diamantini * Copyright (C) 2009 by Paweł Prażak -* Copyright (C) 2009-2010 by Lionel Chauvin +* Copyright (C) 2009 by Lionel Chauvin * * * This program is free software; you can redistribute it and/or @@ -30,9 +30,6 @@ #define LINEEDIT_H -// Local Includes -#include "rekonqprivate_export.h" - // KDE Includes #include @@ -42,7 +39,7 @@ class QFocusEvent; class QKeyEvent; -class REKONQ_TESTS_EXPORT LineEdit : public KLineEdit +class LineEdit : public KLineEdit { Q_OBJECT @@ -50,9 +47,12 @@ public: explicit LineEdit(QWidget *parent = 0); virtual ~LineEdit(); + protected: virtual void keyPressEvent(QKeyEvent*); virtual void mouseDoubleClickEvent(QMouseEvent *); + + }; #endif // LINEEDIT_H diff --git a/src/urlbar/listitem.cpp b/src/urlbar/listitem.cpp new file mode 100644 index 00000000..92951cb7 --- /dev/null +++ b/src/urlbar/listitem.cpp @@ -0,0 +1,173 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Andrea Diamantini +* +* +* 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 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* 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 . +* +* ============================================================ */ + + +// Self Includes +#include "listitem.h" + +// Local Includes +#include "urlresolver.h" +#include "application.h" + +// KDE Includes +#include +#include +#include + +// Qt Includes +#include +#include +#include +#include +#include +#include +#include + +ListItem::ListItem(const UrlSearchItem &item, QWidget *parent) + : QWidget(parent), + m_option() +{ + QHBoxLayout *hLayout = new QHBoxLayout; + QVBoxLayout *vLayout = new QVBoxLayout; + + QLabel *previewLabel = new QLabel; + previewLabel->setFixedSize(40,30); + QPixmap preview; + QString path = KStandardDirs::locateLocal("cache", QString("thumbs/") + guessNameFromUrl(item.url) + ".png", true); + if(QFile::exists(path)) + { + preview.load(path); + previewLabel->setPixmap(preview.scaled(40,30)); + } + else + { + if(item.icon.startsWith( QLatin1String("http://") ) ) + preview = Application::icon( item.icon ).pixmap(22); + } + previewLabel->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); + + hLayout->addWidget(previewLabel); + hLayout->addLayout(vLayout); + + QLabel *titleLabel = new QLabel("" + item.title + ""); + titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + QLabel *urlLabel = new QLabel("" + item.url + ""); + urlLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + vLayout->addWidget(titleLabel); + vLayout->addWidget(urlLabel); + + + QLabel *iconLabel = new QLabel; + QPixmap pixmap; + if(item.icon.startsWith( QLatin1String("http://") ) ) + pixmap = Application::icon( item.icon ).pixmap(18); + else + pixmap = KIcon(item.icon).pixmap(18); + + iconLabel->setPixmap(pixmap); + iconLabel->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); + hLayout->addWidget(iconLabel); + + setLayout(hLayout); + + m_option.initFrom(this); + m_option.direction = Qt::LeftToRight; + + deactivate(); +} + +ListItem::~ListItem() +{ + disconnect(); +} + + +//TODO: REMOVE DUPLICATE CODE WITH PREVIEWIMAGE +QString ListItem::guessNameFromUrl(QUrl url) +{ + QString name = url.toString( QUrl::RemoveScheme | QUrl::RemoveUserInfo | QUrl::StripTrailingSlash ); + + // TODO learn Regular Expressions :) + // and implement something better here.. + name.remove('/'); + name.remove('&'); + name.remove('.'); + name.remove('-'); + name.remove('_'); + name.remove('?'); + name.remove('='); + name.remove('+'); + + return name; +} + + +void ListItem::activate() +{ + m_option.state |= QStyle::State_Selected; + repaint(); +} + + +void ListItem::deactivate() +{ + m_option.state &= ~QStyle::State_Selected; + repaint(); +} + +void ListItem::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + + if( m_option.state.testFlag(QStyle::State_Selected) || m_option.state.testFlag(QStyle::State_MouseOver)) + { + QPainter painter(this); + m_option.rect=QRect(QPoint(),size()); + style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &m_option, &painter, this); + } +} + +void ListItem::enterEvent(QEvent *e) +{ + m_option.state |= QStyle::State_MouseOver; + repaint(); + QWidget::enterEvent(e); +} + +void ListItem::leaveEvent(QEvent *e) +{ + m_option.state &= ~QStyle::State_MouseOver; + repaint(); + QWidget::enterEvent(e); +} + +void ListItem::mousePressEvent(QMouseEvent *e) +{ + emit itemClicked(this); + QWidget::mousePressEvent(e); +} + diff --git a/src/urlbar/listitem.h b/src/urlbar/listitem.h new file mode 100644 index 00000000..6aa3f1e9 --- /dev/null +++ b/src/urlbar/listitem.h @@ -0,0 +1,59 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Andrea Diamantini +* +* +* 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 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* 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 . +* +* ============================================================ */ + + +// Qt Includes +#include +#include + +// Forward Declarations +class UrlSearchItem; + + +class ListItem : public QWidget +{ +Q_OBJECT + +public: + ListItem(const UrlSearchItem &item, QWidget *parent = 0); + ~ListItem(); + + void activate(); + void deactivate(); + +signals: + void itemClicked(ListItem *item); + +protected: + virtual void paintEvent(QPaintEvent *event); + virtual void enterEvent(QEvent *); + virtual void leaveEvent(QEvent *); + virtual void mousePressEvent(QMouseEvent *e); + +private: + QStyleOptionViewItemV4 m_option; + QString guessNameFromUrl(QUrl url); + +}; diff --git a/src/urlbar/urlbar.cpp b/src/urlbar/urlbar.cpp index 189d19fe..54a0a02d 100644 --- a/src/urlbar/urlbar.cpp +++ b/src/urlbar/urlbar.cpp @@ -2,10 +2,10 @@ * * This file is a part of the rekonq project * -* Copyright (C) 2008-2010 by Andrea Diamantini +* Copyright (C) 2008-2009 by Andrea Diamantini * Copyright (C) 2009 by Domrachev Alexandr * Copyright (C) 2009 by Paweł Prażak -* Copyright (C) 2009-2010 by Lionel Chauvin +* Copyright (C) 2009 by Lionel Chauvin * * * This program is free software; you can redistribute it and/or @@ -36,8 +36,7 @@ #include "lineedit.h" #include "mainwindow.h" #include "webview.h" -#include "historymanager.h" -#include "webtab.h" +#include "urlresolver.h" // KDE Includes #include @@ -49,43 +48,44 @@ #include #include #include - +#include QColor UrlBar::s_defaultBaseColor; UrlBar::UrlBar(QWidget *parent) - : KHistoryComboBox(true, parent) - , m_lineEdit(new LineEdit) - , m_progress(0) + : KComboBox(true, parent) + , m_lineEdit(new LineEdit) + , m_progress(0) + , m_box(new CompletionWidget(this)) { - setUrlDropsEnabled(true); - setAutoDeleteCompletionObject(true); - //cosmetic setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); setMinimumWidth(180); - - setTrapReturnKey(true); - - setupLineEdit(); - // add every item to history - connect(this, SIGNAL(returnPressed(const QString&)), SLOT(activated(const QString&))); - connect(completionBox(), SIGNAL(activated(const QString&)), SLOT(activated(const QString&))); + // signal handlings + setTrapReturnKey(true); + setUrlDropsEnabled(true); + + // Make m_lineEdit background transparent + QPalette p = m_lineEdit->palette(); + p.setColor(QPalette::Base, Qt::transparent); + m_lineEdit->setPalette(p); - connect(this, SIGNAL(cleared()), SLOT(cleared())); + if (!s_defaultBaseColor.isValid()) + { + s_defaultBaseColor = palette().color(QPalette::Base); + } - // setup completion box - setCompletionObject( Application::historyManager()->completionObject() ); - - // set dropdown list background - QPalette p = view()->palette(); - p.setColor(QPalette::Base, palette().color(QPalette::Base)); - view()->setPalette(p); + setLineEdit(m_lineEdit); + // clear the URL bar + m_lineEdit->clear(); // load urls on activated urlbar signal - connect(this, SIGNAL(activated(const KUrl&)), Application::instance(), SLOT(loadUrl(const KUrl&))); + connect(this, SIGNAL(returnPressed(const QString&)), SLOT(activated(const QString&))); + + installEventFilter(m_box); + connect(m_box, SIGNAL(chosenUrl(const QString&)), SLOT(activated(const QString&))); } @@ -96,7 +96,7 @@ UrlBar::~UrlBar() void UrlBar::selectAll() const { - lineEdit()->selectAll(); + m_lineEdit->selectAll(); } @@ -106,42 +106,12 @@ KUrl UrlBar::url() const } -KLineEdit *UrlBar::lineEdit() const -{ - return m_lineEdit; -} - - -void UrlBar::setupLineEdit() -{ - // Make m_lineEdit background transparent - QPalette p = m_lineEdit->palette(); - p.setColor(QPalette::Base, Qt::transparent); - m_lineEdit->setPalette(p); - - if (!s_defaultBaseColor.isValid()) - { - s_defaultBaseColor = palette().color(QPalette::Base); - } - - setLineEdit(m_lineEdit); - - // Make the lineedit consume the Qt::Key_Enter event... - lineEdit()->setTrapReturnKey(true); - - lineEdit()->setHandleSignals(true); - - // clear the URL bar - lineEdit()->clear(); -} - - void UrlBar::setUrl(const QUrl& url) { if(url.scheme() == "about") { m_currentUrl = KUrl(); - updateUrl(); // updateUrl before setFocus + updateUrl(); setFocus(); } else @@ -149,6 +119,7 @@ void UrlBar::setUrl(const QUrl& url) m_currentUrl = KUrl(url); updateUrl(); } + } @@ -195,29 +166,21 @@ void UrlBar::updateUrl() // Must be AFTER setCurrentIndex if (!hasFocus()) { - lineEdit()->setCursorPosition(0); + m_lineEdit->setCursorPosition(0); } } void UrlBar::activated(const QString& urlString) { + disconnect(this, SIGNAL(editTextChanged(const QString &)), this, SLOT(suggestUrls(const QString &))); + if (urlString.isEmpty()) return; - // this fix urlbar behaviour, removing focus from there and enabling - // loading animation. Temporary fix?? - Application::instance()->mainWindow()->currentTab()->setFocus(); - - setUrl( KUrl(urlString) ); - emit activated( KUrl(urlString) ); -} - - -void UrlBar::cleared() -{ - // clear the history on user's request from context menu - clear(); + clearFocus(); + setUrl(urlString); + Application::instance()->loadUrl(m_currentUrl); } @@ -243,7 +206,7 @@ void UrlBar::paintEvent(QPaintEvent *event) p.setColor(QPalette::Base, s_defaultBaseColor); setPalette(p); - KHistoryComboBox::paintEvent(event); + KComboBox::paintEvent(event); if (!hasFocus()) { @@ -261,7 +224,7 @@ void UrlBar::paintEvent(QPaintEvent *event) painter.setBrush(generateGradient(loadingColor, height())); painter.setPen(Qt::transparent); - QRect backgroundRect = lineEdit()->frameGeometry(); + QRect backgroundRect = m_lineEdit->frameGeometry(); int mid = backgroundRect.width() * m_progress / 100; QRect progressRect(backgroundRect.x(), backgroundRect.y(), mid, backgroundRect.height()); painter.drawRect(progressRect); @@ -272,7 +235,7 @@ void UrlBar::paintEvent(QPaintEvent *event) QSize UrlBar::sizeHint() const { - return lineEdit()->sizeHint(); + return m_lineEdit->sizeHint(); } @@ -308,43 +271,70 @@ bool UrlBar::isLoading() return true; } - void UrlBar::keyPressEvent(QKeyEvent *event) { + + // this handles the Modifiers + Return key combinations QString currentText = m_lineEdit->text().trimmed(); - if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) + if ((event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) + && !currentText.startsWith(QLatin1String("http://"), Qt::CaseInsensitive)) { - if( !currentText.startsWith(QLatin1String("http://"), Qt::CaseInsensitive) ) + QString append; + if (event->modifiers() == Qt::ControlModifier) { - QString append; - if (event->modifiers() == Qt::ControlModifier) - { - append = QLatin1String(".com"); - } - else if (event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) - { - append = QLatin1String(".org"); - } - else if (event->modifiers() == Qt::ShiftModifier) - { - append = QLatin1String(".net"); - } - - QUrl url(QLatin1String("http://www.") + currentText); - QString host = url.host(); - if (!host.endsWith(append, Qt::CaseInsensitive)) - { - host += append; - url.setHost(host); - m_lineEdit->setText(url.toString()); - } + append = QLatin1String(".com"); } - else + else if (event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) + { + append = QLatin1String(".org"); + } + else if (event->modifiers() == Qt::ShiftModifier) + { + append = QLatin1String(".net"); + } + + QUrl url(QLatin1String("http://www.") + currentText); + QString host = url.host(); + if (!host.endsWith(append, Qt::CaseInsensitive)) { - // fill lineEdit with its stripped contents to remove trailing spaces - m_lineEdit->setText(currentText); + host += append; + url.setHost(host); + m_lineEdit->setText(url.toString()); } } + + KComboBox::keyPressEvent(event); +} + + +void UrlBar::suggestUrls(const QString &text) +{ + if (!hasFocus()) + { + return; + } + + if(text.isEmpty()) + { + m_box->hide(); + return; + } + + UrlResolver res(text); + UrlSearchList list = res.orderedSearchItems(); + + if(list.count() > 0) + { + m_box->clear(); + m_box->insertSearchList(list); + m_box->popup(); + } +} - KHistoryComboBox::keyPressEvent(event); +void UrlBar::focusInEvent(QFocusEvent *event) +{ + // activate suggestions on edit text + connect(this, SIGNAL(editTextChanged(const QString &)), this, SLOT(suggestUrls(const QString &))); + + KComboBox::focusInEvent(event); } diff --git a/src/urlbar/urlbar.h b/src/urlbar/urlbar.h index 39911bb2..ef53d63a 100644 --- a/src/urlbar/urlbar.h +++ b/src/urlbar/urlbar.h @@ -2,10 +2,10 @@ * * This file is a part of the rekonq project * -* Copyright (C) 2008-2010 by Andrea Diamantini +* Copyright (C) 2008-2009 by Andrea Diamantini * Copyright (C) 2009 by Domrachev Alexandr * Copyright (C) 2009 by Paweł Prażak -* Copyright (C) 2009-2010 by Lionel Chauvin +* Copyright (C) 2009 by Lionel Chauvin * * * This program is free software; you can redistribute it and/or @@ -32,23 +32,23 @@ // Local Includes -#include "rekonqprivate_export.h" #include "lineedit.h" +#include "completionwidget.h" // KDE Includes #include -#include +#include // Qt Includes #include +#include // Forward Declarations class QLinearGradient; class QWidget; -class KCompletion; -class REKONQ_TESTS_EXPORT UrlBar : public KHistoryComboBox +class UrlBar : public KComboBox { Q_OBJECT @@ -61,31 +61,24 @@ public: QSize sizeHint() const; void setBackgroundColor(QColor); bool isLoading(); - void setProgress(int progress); -signals: - void activated(const KUrl&); - public slots: void setUrl(const QUrl &url); void updateProgress(int progress); void updateUrl(); - + private slots: void activated(const QString& url); void loadFinished(bool); - void cleared(); + void suggestUrls(const QString &editedText); protected: virtual void paintEvent(QPaintEvent *event); virtual void keyPressEvent(QKeyEvent *event); + virtual void focusInEvent(QFocusEvent *event); private: - void setupLineEdit(); - - KLineEdit *lineEdit() const; - static QLinearGradient generateGradient(const QColor &color, int height); static QColor s_defaultBaseColor; @@ -94,6 +87,9 @@ private: KUrl m_currentUrl; int m_progress; + + CompletionWidget *m_box; + KUrl m_suggestedUrl; }; #endif diff --git a/src/urlbar/urlresolver.cpp b/src/urlbar/urlresolver.cpp new file mode 100644 index 00000000..b2bf50af --- /dev/null +++ b/src/urlbar/urlresolver.cpp @@ -0,0 +1,177 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Andrea Diamantini +* +* +* 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 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* 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 . +* +* ============================================================ */ + + +// Self Includes +#include "urlresolver.h" + +// Local Includes +#include "application.h" +#include "historymanager.h" +#include "bookmarksmanager.h" + +// KDE Includes +#include +#include +#include +#include +#include +#include + +// Qt Includes +#include +#include +#include + + +// NOTE default kurifilter plugin list (at least in my box) +// 1. "kshorturifilter" +// 2. "kurisearchfilter" +// 3. "localdomainurifilter" +// 4 ."kuriikwsfilter" +// 5. "fixhosturifilter" + + +UrlResolver::UrlResolver(const QString &typedUrl) + : _urlString(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 :) + + UrlSearchList list; + + list << qurlFromUserInputResolution(); + list << webSearchesResolution(); + int firstResults = list.count(); + int checkPoint = 9 - firstResults; + + UrlSearchList historyList = historyResolution(); + int historyResults = historyList.count(); + + UrlSearchList bookmarksList = bookmarksResolution(); + int bookmarkResults = bookmarksList.count(); + + if(historyResults + bookmarkResults > checkPoint) + { + historyList = historyList.mid(0,3); + bookmarksList = bookmarksList.mid(0,3); + } + list << historyList; + list << bookmarksList; + + return list; +} + + +////////////////////////////////////////////////////////////////////////// +// PRIVATE ENGINES + + +// STEP 1 = QUrl from User Input (easily the best solution... ) +UrlSearchList UrlResolver::qurlFromUserInputResolution() +{ + UrlSearchList list; + + QString url2 = _urlString; + QUrl urlFromUserInput = QUrl::fromUserInput(url2); + if(urlFromUserInput.isValid()) + { + QByteArray ba = urlFromUserInput.toEncoded(); + if(!ba.isEmpty()) + { + QString str(ba); + UrlSearchItem it(str); + list << it; + } + } + + return list; +} + + +// STEP 2 = Web Searches +UrlSearchList UrlResolver::webSearchesResolution() +{ + UrlSearchList list; + + QString url1 = _urlString; + if(KUrl(url1).isRelative() && !url1.contains('.')) + { + // KUriFilter has the worst performance possible here and let this trick unusable + QString gUrl = QString("http://www.google.com/search?q=%1&ie=UTF-8&oe=UTF-8").arg(url1); + QString gTitle = i18n("Search Google for ") + url1; + UrlSearchItem gItem(gUrl, gTitle, QString("http://www.google.com") ); + list << gItem; + + QString wUrl = QString("http://en.wikipedia.org/wiki/Special:Search?search=%1&go=Go").arg(url1); + QString wTitle = i18n("Search Wikipedia for ") + url1; + UrlSearchItem wItem(wUrl, wTitle, QString("http://wikipedia.org") ); + list << wItem; + } + + return list; +} + + +// STEP 3 = history completion +UrlSearchList UrlResolver::historyResolution() +{ + UrlSearchList list; + + KCompletion *historyCompletion = Application::historyManager()->completionObject(); + QStringList historyResults = historyCompletion->substringCompletion(_urlString); + Q_FOREACH(const QString &s, historyResults) + { + UrlSearchItem it(s, s, QString("view-history")); + list << it; + } + + return list; +} + + +// STEP 4 = bookmarks completion +UrlSearchList UrlResolver::bookmarksResolution() +{ + UrlSearchList list; + + KCompletion *bookmarkCompletion = Application::bookmarkProvider()->completionObject(); + QStringList bookmarkResults = bookmarkCompletion->substringCompletion(_urlString); + Q_FOREACH(const QString &s, bookmarkResults) + { + UrlSearchItem it( s, QString(), QString("rating") ); + list << it; + } + + return list; +} diff --git a/src/urlbar/urlresolver.h b/src/urlbar/urlresolver.h new file mode 100644 index 00000000..0a880150 --- /dev/null +++ b/src/urlbar/urlresolver.h @@ -0,0 +1,72 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Andrea Diamantini +* +* +* 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 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* 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 URL_RESOLVER_H +#define URL_RESOLVER_H + + +// Qt Includes +#include +#include + +// Forward Declarations +class KUrl; + +class UrlSearchItem +{ +public: + QString url; + QString title; + QString icon; + + UrlSearchItem(const QString &_url, const QString &_title = QString(), const QString &_icon = QString()) + : url(_url), title(_title), icon(_icon) + {}; +}; + +typedef QList UrlSearchList; + + +// ---------------------------------------------------------------------- + + +class UrlResolver +{ +public: + UrlResolver(const QString &typedUrl); + + UrlSearchList orderedSearchItems(); + +private: + QString _urlString; + + UrlSearchList webSearchesResolution(); + UrlSearchList historyResolution(); + UrlSearchList qurlFromUserInputResolution(); + UrlSearchList bookmarksResolution(); +}; + +#endif // URL_RESOLVER_H -- cgit v1.2.1