diff options
Diffstat (limited to 'src/urlbar')
-rw-r--r-- | src/urlbar/completionwidget.cpp | 314 | ||||
-rw-r--r-- | src/urlbar/completionwidget.h | 82 | ||||
-rw-r--r-- | src/urlbar/lineedit.cpp | 130 | ||||
-rw-r--r-- | src/urlbar/lineedit.h | 44 | ||||
-rw-r--r-- | src/urlbar/listitem.cpp | 437 | ||||
-rw-r--r-- | src/urlbar/listitem.h | 221 | ||||
-rw-r--r-- | src/urlbar/urlbar.cpp | 366 | ||||
-rw-r--r-- | src/urlbar/urlbar.h | 53 | ||||
-rw-r--r-- | src/urlbar/urlresolver.cpp | 230 | ||||
-rw-r--r-- | src/urlbar/urlresolver.h | 85 |
10 files changed, 1703 insertions, 259 deletions
diff --git a/src/urlbar/completionwidget.cpp b/src/urlbar/completionwidget.cpp new file mode 100644 index 00000000..8307940b --- /dev/null +++ b/src/urlbar/completionwidget.cpp @@ -0,0 +1,314 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com> +* +* +* 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 <http://www.gnu.org/licenses/>. +* +* ============================================================ */ + + +// Self Includes +#include "completionwidget.h" +#include "completionwidget.moc" + +// Auto Includes +#include "rekonq.h" + +// Local Includes +#include "application.h" +#include "urlresolver.h" + +// KDE Includes +#include <KGlobalSettings> +#include <KDebug> +#include <KUrl> + +// Qt Includes +#include <QPoint> +#include <QSize> +#include <QVBoxLayout> +#include <QString> +#include <QEvent> +#include <QKeyEvent> + +// Defines +#define QL1S(x) QLatin1String(x) + + +CompletionWidget::CompletionWidget(QWidget *parent) + : QFrame(parent, Qt::ToolTip) + , _parent(parent) + , _currentIndex(-1) + , _searchEngine( defaultSearchEngine() ) +{ + setFrameStyle(QFrame::Panel); + setLayoutDirection(Qt::LeftToRight); + QVBoxLayout *layout = new QVBoxLayout; + layout->setMargin(0); + layout->setSpacing(0); + setLayout(layout); +} + + +void CompletionWidget::insertSearchList(const UrlSearchList &list, const QString& text) +{ + _list = list; + int i = 0; + foreach(UrlSearchItem item, _list) + { + ListItem *suggestion = ListItemFactory::create(item, text, this); + suggestion->setBackgroundRole(i%2 ? QPalette::AlternateBase : QPalette::Base); + connect(suggestion, SIGNAL(itemClicked(ListItem *, Qt::MouseButton)), this, SLOT(itemChosen(ListItem *, Qt::MouseButton))); + connect(this, SIGNAL(nextItemSubChoice()), suggestion, SLOT(nextItemSubChoice())); + suggestion->setObjectName( QString::number(i++) ); + layout()->addWidget( suggestion ); + } +} + + +void CompletionWidget::sizeAndPosition() +{ + setFixedWidth( _parent->width() ); + adjustSize(); + + // 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<ListItem *>( QString::number(_currentIndex) ); + widget->deactivate(); + } + + if(_currentIndex > 0) + _currentIndex--; + else + _currentIndex=layout()->count()-1; + + // activate "new" current + ListItem *widget = findChild<ListItem *>( QString::number(_currentIndex) ); + widget->activate(); +} + + +void CompletionWidget::down() +{ + // deactivate previous + if(_currentIndex != -1) + { + ListItem *widget = findChild<ListItem *>( QString::number(_currentIndex) ); + widget->deactivate(); + } + + if(_currentIndex < _list.count() -1) + _currentIndex++; + else + _currentIndex=0; + + // activate "new" current + ListItem *widget = findChild<ListItem *>( 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<QWidget*>(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()) + { + ListItem *child; + + if ( type == QEvent::KeyPress ) + { + QKeyEvent *ev = static_cast<QKeyEvent *>( 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; + } + if (ev->modifiers() & Qt::ControlModifier) + { + emit nextItemSubChoice(); + ev->accept(); + return true; + } + break; + + case Qt::Key_Enter: + case Qt::Key_Return: + child = findChild<ListItem *>( QString::number(_currentIndex) ); + emit chosenUrl( child->url(), Rekonq::CurrentTab); + ev->accept(); + hide(); + return true; + + case Qt::Key_Escape: + hide(); + return true; + } + } + } + + 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, Qt::MouseButton button) +{ + if(button == Qt::MidButton) + emit chosenUrl( item->url(), Rekonq::NewCurrentTab); + else + emit chosenUrl( item->url(), Rekonq::CurrentTab); + hide(); +} + + + + +void CompletionWidget::suggestUrls(const QString &text) +{ + QWidget *w = qobject_cast<QWidget *>(parent()); + if(!w->hasFocus()) + return; + + if(text.isEmpty()) + { + hide(); + return; + } + + UrlResolver res(text); + UrlSearchList list = res.orderedSearchItems(); + if(list.count() > 0) + { + clear(); + insertSearchList(list, text); + popup(); + } +} + + +QString CompletionWidget::defaultSearchEngine() +{ + int n = ReKonfig::searchEngine(); + QString engine; + switch(n) + { + case 0: + engine = QL1S("google"); + break; + case 1: + engine = QL1S("altavista"); + break; + case 2: + engine = QL1S("lycos"); + break; + case 3: + engine = QL1S("wikipedia"); + break; + case 4: + engine = QL1S("wolfram"); + break; + default: + engine = QL1S("google"); + break; + } + + return engine; +} diff --git a/src/urlbar/completionwidget.h b/src/urlbar/completionwidget.h new file mode 100644 index 00000000..e9851484 --- /dev/null +++ b/src/urlbar/completionwidget.h @@ -0,0 +1,82 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com> +* +* +* 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 <http://www.gnu.org/licenses/>. +* +* ============================================================ */ + + +#ifndef COMPLETION_WIDGET_H +#define COMPLETION_WIDGET_H + + +// Local Includes +#include "application.h" +#include "listitem.h" + +// KDE Includes +#include <KLineEdit> + +// Qt Includes +#include <QFrame> + + +class CompletionWidget : public QFrame +{ + Q_OBJECT + +public: + CompletionWidget(QWidget *parent); + + virtual bool eventFilter(QObject *obj, QEvent *ev); + void setVisible(bool visible); + + QString searchEngine() { return _searchEngine; }; + void setCurrentEngine(const QString &engine) { _searchEngine = engine; }; + +private slots: + void itemChosen(ListItem *item, Qt::MouseButton = Qt::LeftButton); + void suggestUrls(const QString &text); + +signals: + void chosenUrl(const KUrl &, Rekonq::OpenType); + void nextItemSubChoice(); + +private: + QString defaultSearchEngine(); + + void insertSearchList(const UrlSearchList &list, const QString& text); + void popup(); + void clear(); + + void sizeAndPosition(); + void up(); + void down(); + + QWidget *_parent; + + UrlSearchList _list; + int _currentIndex; + + QString _searchEngine; +}; + +#endif // COMPLETION_WIDGET_H diff --git a/src/urlbar/lineedit.cpp b/src/urlbar/lineedit.cpp index f3c93e8e..6236512f 100644 --- a/src/urlbar/lineedit.cpp +++ b/src/urlbar/lineedit.cpp @@ -30,24 +30,64 @@ #include "lineedit.h" #include "lineedit.moc" +// KDE Includes +#include <klocalizedstring.h> +#include <KDebug> +#include <KStandardDirs> +#include <KIconLoader> + // Qt Includes #include <QtGui/QContextMenuEvent> #include <QtGui/QFocusEvent> #include <QtGui/QKeyEvent> +#include <QStyleOptionFrameV2> +#include <QPainter> + + +IconButton::IconButton(QWidget *parent) + : QToolButton(parent) +{ + setToolButtonStyle(Qt::ToolButtonIconOnly); + setStyleSheet("IconButton { background-color:transparent; border: none; padding: 0px}"); + setCursor(Qt::ArrowCursor); +} + + +// ----------------------------------------------------------------------------------------------------------- LineEdit::LineEdit(QWidget* parent) - : KLineEdit(parent) + : KLineEdit(parent) + , _icon( new IconButton(this) ) { + // cosmetic + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); setMinimumWidth(200); + setMinimumHeight(26); + + // initial style + setStyleSheet( QString("LineEdit { padding: 0 0 0 %1px;} ").arg(_icon->sizeHint().width()) ); + + // doesn't show the clear button + setClearButtonShown(false); + + // trap Key_Enter & Key_Return events, while emitting the returnPressed signal + setTrapReturnKey(true); + + // insert decoded URLs + setUrlDropsEnabled(true); + + // accept focus, via tabbing, clicking & wheeling setFocusPolicy(Qt::WheelFocus); - setHandleSignals(true); - setClearButtonShown(true); + + // disable completion object (we have our own :) ) + setCompletionObject(0); } LineEdit::~LineEdit() { + delete _icon; } @@ -67,3 +107,87 @@ void LineEdit::mouseDoubleClickEvent(QMouseEvent *) { selectAll(); } + + +IconButton *LineEdit::iconButton() const +{ + return _icon; +} + + +void LineEdit::paintEvent(QPaintEvent *event) +{ + // you need this before our code to draw inside the line edit.. + KLineEdit::paintEvent(event); + + if (text().isEmpty()) + { + QStyleOptionFrame option; + initStyleOption(&option); + QRect textRect = style()->subElementRect(QStyle::SE_LineEditContents, &option, this); + QPainter painter(this); + painter.setPen(Qt::gray); + painter.drawText( textRect, + Qt::AlignCenter, + i18n("Search Bookmarks, History, Web.. just start typing here!") + ); + } +} + + +IconButton *LineEdit::addRightIcon(LineEdit::icon ic) +{ + IconButton *rightIcon = new IconButton(this); + + switch(ic) + { + case LineEdit::KGet: + rightIcon->setIcon( KIcon("download") ); + rightIcon->setToolTip( i18n("List all links with KGet") ); + break; + case LineEdit::RSS: + rightIcon->setIcon( KIcon("application-rss+xml") ); + rightIcon->setToolTip( i18n("List all available RSS feeds") ); + break; + case LineEdit::SSL: + rightIcon->setIcon( KIcon("object-locked") ); + rightIcon->setToolTip( i18n("Show SSL Infos") ); + break; + default: + kDebug() << "ERROR.. default non extant case!!"; + break; + } + + _rightIconsList << rightIcon; + int iconsCount = _rightIconsList.count(); + rightIcon->move( width() - 23*iconsCount, 6); + rightIcon->show(); + + return rightIcon; +} + + +void LineEdit::clearRightIcons() +{ + qDeleteAll(_rightIconsList); + _rightIconsList.clear(); +} + + +void LineEdit::resizeEvent(QResizeEvent *event) +{ + int newHeight = ( height() - 19 )/2; + _icon->move(4, newHeight ); + + int iconsCount = _rightIconsList.count(); + int w = width(); + + for(int i = 0; i < iconsCount; ++i) + { + IconButton *bt = _rightIconsList.at(i); + bt->move( w - 25*(i+1), newHeight ); + } + + KLineEdit::resizeEvent(event); + +} diff --git a/src/urlbar/lineedit.h b/src/urlbar/lineedit.h index 67ded052..68cdc7d1 100644 --- a/src/urlbar/lineedit.h +++ b/src/urlbar/lineedit.h @@ -32,11 +32,32 @@ // KDE Includes #include <KLineEdit> +#include <KIcon> + +// Qt Includes +#include <QToolButton> // Forward Declarations class QContextMenuEvent; class QFocusEvent; class QKeyEvent; +class QStyleOptionFrameV2; + + +class IconButton : public QToolButton +{ + Q_OBJECT + +public: + IconButton(QWidget *parent = 0); +}; + + +// ------------------------------------------------------------------------------------ + + +// Definitions +typedef QList<IconButton *> IconButtonPointerList; class LineEdit : public KLineEdit @@ -44,12 +65,33 @@ class LineEdit : public KLineEdit Q_OBJECT public: + + enum icon + { + KGet = 0x00000001, + RSS = 0x00000010, + SSL = 0x00000100, + }; + explicit LineEdit(QWidget *parent = 0); virtual ~LineEdit(); + + IconButton *iconButton() const; protected: - virtual void keyPressEvent(QKeyEvent*); + virtual void keyPressEvent(QKeyEvent *); virtual void mouseDoubleClickEvent(QMouseEvent *); + virtual void paintEvent(QPaintEvent *); + virtual void resizeEvent(QResizeEvent *); + + IconButton *addRightIcon(LineEdit::icon ); + +private slots: + void clearRightIcons(); + +private: + IconButton *_icon; + IconButtonPointerList _rightIconsList; }; #endif // LINEEDIT_H diff --git a/src/urlbar/listitem.cpp b/src/urlbar/listitem.cpp new file mode 100644 index 00000000..a182c1a2 --- /dev/null +++ b/src/urlbar/listitem.cpp @@ -0,0 +1,437 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com> +* +* +* 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 <http://www.gnu.org/licenses/>. +* +* ============================================================ */ + + +// Self Includes +#include "listitem.h" +#include "listitem.moc" + +// Auto Includes +#include "rekonq.h" + +// Local Includes +#include "urlresolver.h" +#include "application.h" +#include "websnap.h" +#include "completionwidget.h" + +// KDE Includes +#include <KIcon> +#include <KStandardDirs> +#include <KDebug> +#include <QActionGroup> +#include <KConfigGroup> +#include <KIcon> + +// Qt Includes +#include <QHBoxLayout> +#include <QVBoxLayout> +#include <QLabel> +#include <QSizePolicy> +#include <QPixmap> +#include <QStylePainter> +#include <QMouseEvent> +#include <QWebSettings> +#include <QFile> + +// Defines +#define QL1S(x) QLatin1String(x) + + +ListItem::ListItem(const UrlSearchItem &item, QWidget *parent) + : QWidget(parent) + , m_option() + , m_url(item.url) +{ + setAutoFillBackground(true); + + m_option.initFrom(this); + m_option.direction = Qt::LeftToRight; + + QPalette p(palette()); + p.setColor(QPalette::Base, Qt::white); // TODO: choose the correct color + + p.setColor(QPalette::AlternateBase, QColor(247,247,247)); // TODO: choose the correct color + setPalette(p); + + QHBoxLayout *hLayout = new QHBoxLayout(this); + hLayout->setSpacing(4); + setLayout(hLayout); + + deactivate(); +} + + +ListItem::~ListItem() +{ + disconnect(); +} + + + +void ListItem::activate() +{ + m_option.state |= QStyle::State_Selected; + update(); +} + + +void ListItem::deactivate() +{ + m_option.state &= ~QStyle::State_Selected; + update(); +} + + +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); + } + + QWidget::paintEvent(event); +} + + +void ListItem::enterEvent(QEvent *e) +{ + m_option.state |= QStyle::State_MouseOver; + update(); + QWidget::enterEvent(e); +} + + +void ListItem::leaveEvent(QEvent *e) +{ + m_option.state &= ~QStyle::State_MouseOver; + update(); + QWidget::enterEvent(e); +} + + +void ListItem::mousePressEvent(QMouseEvent *e) +{ + emit itemClicked(this, e->button()); + QWidget::mousePressEvent(e); +} + + +KUrl ListItem::url() +{ + return m_url; +} + +void ListItem::nextItemSubChoice() +{ + //will be override +} + + +// --------------------------------------------------------------- + + +TypeIconLabel::TypeIconLabel(int type, QWidget *parent) + : QLabel(parent) +{ + setMinimumWidth(40); + QHBoxLayout *hLayout = new QHBoxLayout(this); + hLayout->setMargin(0); + hLayout->setAlignment(Qt::AlignRight); + setLayout(hLayout); + + if (type & UrlSearchItem::Search) hLayout->addWidget(getIcon("edit-find")); + if (type & UrlSearchItem::Browse) hLayout->addWidget(getIcon("applications-internet")); + if (type & UrlSearchItem::Bookmark) hLayout->addWidget(getIcon("rating")); + if (type & UrlSearchItem::History) hLayout->addWidget(getIcon("view-history")); +} + + +QLabel *TypeIconLabel::getIcon(QString icon) +{ + QLabel *iconLabel = new QLabel(this); + iconLabel->setFixedSize(16,16); + QPixmap pixmap = KIcon(icon).pixmap(16); + iconLabel->setPixmap(pixmap); + return iconLabel; +} + + +// --------------------------------------------------------------- + + +IconLabel::IconLabel(const QString &icon, QWidget *parent) + : QLabel(parent) +{ + QPixmap pixmapIcon = Application::icon( KUrl(icon) ).pixmap(16); + setFixedSize(16,16); + setPixmap(pixmapIcon); +} + + +// --------------------------------------------------------------- + + +TextLabel::TextLabel(const QString &text, const QString &textToPointOut, QWidget *parent) + : QLabel(parent) +{ + QString t = text; + if (!textToPointOut.isEmpty()) + t = t.replace(QRegExp("(" + textToPointOut + ")", Qt::CaseInsensitive), "<b>\\1</b>"); + + setText(t); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); +} + + +//-------------------------------------------------------------------------------------------- + + +PreviewListItem::PreviewListItem(const UrlSearchItem &item, const QString &text, QWidget *parent) + : ListItem(item, parent) +{ + 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); + icon->move(27, 16); + layout()->addWidget(previewLabelIcon); + + QVBoxLayout *vLayout = new QVBoxLayout(this); + vLayout->setMargin(0); + vLayout->addWidget( new TextLabel(item.title, text, this) ); + vLayout->addWidget( new TextLabel("<i>" + item.url.url() + "</i>", text, this) ); + ((QHBoxLayout *)layout())->addLayout(vLayout); + + layout()->addWidget( new TypeIconLabel(item.type, this) ); +} + + +// --------------------------------------------------------------- + + +PreviewLabel::PreviewLabel(const QString &url, int width, int height, QWidget *parent) + : QLabel(parent) +{ + setFixedSize(width, height); + setFrameStyle(QFrame::StyledPanel | QFrame::Raised); + + KUrl u = WebSnap::fileForUrl( QUrl(url) ); + QString path = u.pathOrUrl(); + if(QFile::exists(path)) + { + QPixmap preview; + preview.load(path); + setPixmap(preview.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + } +} + + +// --------------------------------------------------------------- + + +SearchListItem::SearchListItem(const UrlSearchItem &item, const QString &text, QWidget *parent) + : ListItem(item, parent) + , m_text(text) +{ + CompletionWidget *w = qobject_cast<CompletionWidget *>(parent); + QString currentEngine = w->searchEngine(); + kDebug() << currentEngine; + + m_iconLabel = new IconLabel("edit-find", this); //TODO: get the default engine icon + m_titleLabel = new TextLabel( searchItemTitle(currentEngine, text), QString(), this); + m_engineBar = new EngineBar(text, currentEngine, parent); + + // without this it will not work :) + m_url = m_engineBar->url(); + + layout()->addWidget( m_iconLabel ); + layout()->addWidget( m_titleLabel ); + layout()->addWidget( new QLabel( i18n("Engines: "), this ) ); + layout()->addWidget( m_engineBar ); + layout()->addWidget( new TypeIconLabel(item.type, this) ); + + connect(m_engineBar, SIGNAL(searchEngineChanged(QString, QString)), this, SLOT(changeSearchEngine(QString, QString))); +} + + +QString SearchListItem::searchItemTitle(QString engine, QString text) +{ + return QString("Search "+ engine +" for <b>"+text+"</b>"); +} + + +void SearchListItem::changeSearchEngine(QString url, QString engine) +{ + m_titleLabel->setText(searchItemTitle(engine,m_text)); + m_iconLabel->setPixmap(Application::icon( KUrl(url) ).pixmap(16)); + QString url2 = url.replace( QL1S("\\{@}"), m_text); + m_url = KUrl(url2); + + CompletionWidget *w = qobject_cast<CompletionWidget *>(parent()); + w->setCurrentEngine( engine ); +} + + +void SearchListItem::nextItemSubChoice() +{ + m_engineBar->selectNextEngine(); +} + + +// ----------------------------------------------------------------------------------------------- + + +EngineBar::EngineBar(const QString &text, const QString &selectedEngine, QWidget *parent) + : KToolBar(parent) +{ + setIconSize(QSize(16,16)); + setToolButtonStyle(Qt::ToolButtonIconOnly); + + m_engineGroup = new QActionGroup(this); + m_engineGroup->setExclusive(true); + + KConfig config("kuriikwsfilterrc"); //Share with konqueror + KConfigGroup cg = config.group("General"); + QStringList favoriteEngines; + favoriteEngines << "wikipedia" << "google"; //defaults + favoriteEngines = cg.readEntry("FavoriteSearchEngines", favoriteEngines); + + // default engine + CompletionWidget *w = qobject_cast<CompletionWidget *>(parent); + QString defaultEngine = w->searchEngine(); + KService::Ptr service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(defaultEngine)); + + m_engineGroup->addAction(newEngineAction(service, selectedEngine)); + + // set url; + QString url = service->property("Query").toString(); + url = url.replace("\\{@}",text); + m_url = KUrl(url); + + Q_FOREACH(const QString &engine, favoriteEngines) + { + if(!engine.isEmpty()) + { + service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(engine)); + if(service && service->desktopEntryName() != defaultEngine) + { + m_engineGroup->addAction(newEngineAction(service, selectedEngine)); + } + } + } + + addActions(m_engineGroup->actions()); +} + + +KAction *EngineBar::newEngineAction(KService::Ptr service, QString selectedEngine) +{ + KAction *a = new KAction(Application::icon(m_url), service->name(), this); + a->setCheckable(true); + if (service->name()==selectedEngine) + a->setChecked(true); + + QString url = service->property("Query").toString(); + + a->setData( QStringList() << url << service->desktopEntryName() ); + connect(a, SIGNAL(triggered(bool)), this, SLOT(changeSearchEngine())); + + return a; +} + + +void EngineBar::changeSearchEngine() +{ + KAction *a = qobject_cast<KAction*>(sender()); + QStringList list = a->data().toStringList(); + emit searchEngineChanged(list.first(), list.last()); +} + + +void EngineBar::selectNextEngine() +{ + QList<QAction *> e = m_engineGroup->actions(); + int i = 0; + while(i<e.count() && !e.at(i)->isChecked()) + { + i++; + } + + if (i+1 == e.count()) + { + e.at(0)->setChecked(true); + e.at(0)->trigger(); + } + else + { + e.at(i+1)->setChecked(true); + e.at(i+1)->trigger(); + } +} + + +// --------------------------------------------------------------- + + +BrowseListItem::BrowseListItem(const UrlSearchItem &item, const QString &text, QWidget *parent) + : ListItem(item, parent) +{ + QString url = text; + layout()->addWidget( new IconLabel(item.url.url(), this) ); + layout()->addWidget( new TextLabel( QL1S("Browse <i>http://<b>") + url.remove("http://") + QL1S("</b></i>"), QString(), this) ); + layout()->addWidget( new TypeIconLabel(item.type, this) ); +} + + +// --------------------------------------------------------------- + + +ListItem *ListItemFactory::create(const UrlSearchItem &item, const QString &text, QWidget *parent) +{ + ListItem *newItem; + + if(item.type & UrlSearchItem::Browse) + { + newItem = new BrowseListItem(item, text, parent); + } + else + { + if(item.type & UrlSearchItem::Search) + { + newItem = new SearchListItem(item, text, parent); + } + else + { + newItem = new PreviewListItem(item, text, parent); + } + } + + return newItem; +} diff --git a/src/urlbar/listitem.h b/src/urlbar/listitem.h new file mode 100644 index 00000000..de42fd03 --- /dev/null +++ b/src/urlbar/listitem.h @@ -0,0 +1,221 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com> +* +* +* 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 <http://www.gnu.org/licenses/>. +* +* ============================================================ */ + + +#ifndef LISTITEM_H +#define LISTITEM_H + + +// Local Includes +#include "urlresolver.h" + +// KDE Includes +#include <KToolBar> +#include <KAction> +#include <KService> + +// Qt Includes +#include <QWidget> +#include <QLayout> +#include <QStyleOptionViewItemV4> +#include <QLabel> + +// Forward Declarations +class UrlSearchItem; + + +class ListItem : public QWidget +{ + Q_OBJECT + +public: + ListItem(const UrlSearchItem &item, QWidget *parent = 0); + virtual ~ListItem(); + + void activate(); + void deactivate(); + + KUrl url(); + +public slots: + virtual void nextItemSubChoice(); + +signals: + void itemClicked(ListItem *item, Qt::MouseButton); + +protected: + virtual void paintEvent(QPaintEvent *event); + virtual void enterEvent(QEvent *); + virtual void leaveEvent(QEvent *); + virtual void mousePressEvent(QMouseEvent *e); + +private: + QStyleOptionViewItemV4 m_option; + +protected: + KUrl m_url; +}; + + +// ------------------------------------------------------------------------- + + +class TypeIconLabel : public QLabel +{ + Q_OBJECT + +public: + TypeIconLabel(int type, QWidget *parent = 0); + +private: + QLabel *getIcon(QString icon); +}; + + +// ------------------------------------------------------------------------- + + +class IconLabel : public QLabel +{ + Q_OBJECT + +public: + IconLabel(const QString &icon, QWidget *parent = 0); +}; + + +// ------------------------------------------------------------------------- + + +class TextLabel : public QLabel +{ + Q_OBJECT + +public: + TextLabel(const QString &text, const QString &textToPointOut = QString(), QWidget *parent = 0); +}; + + +// ------------------------------------------------------------------------- + + +class EngineBar : public KToolBar +{ + Q_OBJECT + +public: + EngineBar(const QString &text, const QString &selectedEngine, QWidget *parent = 0); + + void selectNextEngine(); + KUrl url() { return m_url; }; + +signals: + void searchEngineChanged(QString url, QString engine); + +private slots: + void changeSearchEngine(); + +private: + KAction *newEngineAction(KService::Ptr service, QString selectedEngine); + + QActionGroup *m_engineGroup; + KUrl m_url; +}; + + +// ------------------------------------------------------------------------- + + +class SearchListItem : public ListItem +{ + Q_OBJECT + +public: + SearchListItem(const UrlSearchItem &item, const QString &text, QWidget *parent = 0); + +public slots: + virtual void nextItemSubChoice(); + +private slots: + void changeSearchEngine(QString url, QString engine); + +private: + QString searchItemTitle(QString engine, QString text); + + TextLabel* m_titleLabel; + IconLabel* m_iconLabel; + EngineBar* m_engineBar; + + QString m_text; +}; + + +// ------------------------------------------------------------------------- + + +class PreviewListItem : public ListItem +{ + Q_OBJECT + +public: + PreviewListItem(const UrlSearchItem &item, const QString &text, QWidget *parent = 0); +}; + + +// ------------------------------------------------------------------------- + + +class PreviewLabel : public QLabel +{ + Q_OBJECT + +public: + PreviewLabel(const QString &url, int width, int height, QWidget *parent = 0); +}; + + +// ------------------------------------------------------------------------- + + +class BrowseListItem : public ListItem +{ + Q_OBJECT + +public: + BrowseListItem(const UrlSearchItem &item, const QString &text, QWidget *parent = 0); +}; + + +//------------------------------------------------------------------------------------------------- + + +class ListItemFactory +{ +public: + static ListItem *create(const UrlSearchItem &item, const QString &text, QWidget *parent); +}; + + +#endif diff --git a/src/urlbar/urlbar.cpp b/src/urlbar/urlbar.cpp index adeba6ae..6d1b19c9 100644 --- a/src/urlbar/urlbar.cpp +++ b/src/urlbar/urlbar.cpp @@ -31,12 +31,16 @@ #include "urlbar.h" #include "urlbar.moc" +// Auto Includes +#include "rekonq.h" + // Local Includes #include "application.h" #include "lineedit.h" #include "mainwindow.h" +#include "webtab.h" #include "webview.h" -#include "historymanager.h" +#include "completionwidget.h" // KDE Includes #include <KDebug> @@ -48,299 +52,219 @@ #include <QPaintEvent> #include <QPalette> #include <QTimer> +#include <QVBoxLayout> - -QColor UrlBar::s_defaultBaseColor; +// Defines +#define QL1S(x) QLatin1String(x) UrlBar::UrlBar(QWidget *parent) - : KHistoryComboBox(true, parent) - , m_lineEdit(new LineEdit) - , m_progress(0) + : LineEdit(parent) + , _tab(0) + , _privateMode(false) { - setUrlDropsEnabled(true); - setAutoDeleteCompletionObject(true); - - //cosmetic - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - setMinimumWidth(180); + _tab = qobject_cast<WebTab *>(parent); - 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&))); - - connect(this, SIGNAL(cleared()), SLOT(cleared())); - - // setup completion box - setCompletionObject( Application::historyManager()->completionObject() ); + connect(_tab->view(), SIGNAL(urlChanged(const QUrl &)), this, SLOT(setQUrl(const QUrl &))); + connect(_tab->view(), SIGNAL(loadFinished(bool)), this, SLOT(loadFinished())); + connect(_tab->view(), SIGNAL(loadStarted()), this, SLOT(clearRightIcons())); - // set dropdown list background - QPalette p = view()->palette(); - p.setColor(QPalette::Base, palette().color(QPalette::Base)); - view()->setPalette(p); + // load typed urls + connect(this, SIGNAL(returnPressed(const QString &)), this, SLOT(loadTyped(const QString &))); - // load urls on activated urlbar signal - connect(this, SIGNAL(activated(const KUrl&)), Application::instance(), SLOT(loadUrl(const KUrl&))); + activateSuggestions(true); } UrlBar::~UrlBar() { + activateSuggestions(false); + _box.clear(); } -void UrlBar::selectAll() const -{ - lineEdit()->selectAll(); -} - - -KUrl UrlBar::url() const -{ - return m_currentUrl; -} - - -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) +void UrlBar::setQUrl(const QUrl& url) { - if(url.scheme() == "about") + if(url.scheme() == QL1S("about") ) { - m_currentUrl = KUrl(); - updateUrl(); // updateUrl before setFocus + iconButton()->setIcon( KIcon("arrow-right") ); + clear(); setFocus(); } else { - m_currentUrl = KUrl(url); - updateUrl(); + clearFocus(); + LineEdit::setUrl(url); + setCursorPosition(0); + iconButton()->setIcon( Application::icon(url) ); } - } -void UrlBar::setProgress(int progress) +void UrlBar::activated(const KUrl& url, Rekonq::OpenType type) { - m_progress = progress; - repaint(); + activateSuggestions(false); + + clearFocus(); + setUrl(url); + Application::instance()->loadUrl(url, type); } -void UrlBar::updateUrl() +void UrlBar::paintEvent(QPaintEvent *event) { - // Don't change my typed url... - // FIXME this is not a proper solution (also if it works...) - if(hasFocus()) - { - kDebug() << "Don't change my typed url..."; - return; - } - - KIcon icon; - if(m_currentUrl.isEmpty()) - { - icon = KIcon("arrow-right"); - } - else - { - icon = Application::icon(m_currentUrl); - } - - if (count()) + QColor backgroundColor; + if( _privateMode ) { - changeUrl(0, icon, m_currentUrl); + backgroundColor = QColor(220, 220, 220); // light gray } else { - insertUrl(0, icon, m_currentUrl); + backgroundColor = Application::palette().color(QPalette::Base); } + + // set background color of UrlBar + QPalette p = palette(); - setCurrentIndex(0); - - // important security consideration: always display the beginning - // of the url rather than its end to prevent spoofing attempts. - // Must be AFTER setCurrentIndex - if (!hasFocus()) + int progr = _tab->progress(); + if (progr == 0) + { + if( _tab->url().scheme() == QL1S("https") ) + { + backgroundColor = QColor(255, 255, 171); // light yellow + } + p.setBrush(QPalette::Base, backgroundColor); + } + else { - lineEdit()->setCursorPosition(0); + QColor loadingColor = QColor(116, 192, 250); + + QLinearGradient gradient(0, 0, width(), 0); + gradient.setColorAt(0, loadingColor); + gradient.setColorAt(((double)progr)/100, backgroundColor); + p.setBrush(QPalette::Base, gradient); } + setPalette(p); + + LineEdit::paintEvent(event); } -void UrlBar::activated(const QString& urlString) -{ - if (urlString.isEmpty()) - return; - - setUrl(urlString); - emit activated(m_currentUrl); -} - - -void UrlBar::cleared() -{ - // clear the history on user's request from context menu - clear(); -} - - -void UrlBar::loadFinished(bool) -{ - // reset progress bar after small delay - m_progress = 0; - QTimer::singleShot(200, this, SLOT(repaint())); -} - - -void UrlBar::updateProgress(int progress) -{ - m_progress = progress; - repaint(); -} - - -void UrlBar::paintEvent(QPaintEvent *event) +void UrlBar::keyPressEvent(QKeyEvent *event) { - // set background color of UrlBar - QPalette p = palette(); - p.setColor(QPalette::Base, s_defaultBaseColor); - setPalette(p); - - KHistoryComboBox::paintEvent(event); - - if (!hasFocus()) + // this handles the Modifiers + Return key combinations + QString currentText = text().trimmed(); + if ((event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) + && !currentText.startsWith(QLatin1String("http://"), Qt::CaseInsensitive)) { - QPainter painter(this); - - QColor loadingColor; - if (m_currentUrl.scheme() == QLatin1String("https")) + QString append; + if (event->modifiers() == Qt::ControlModifier) + { + append = QLatin1String(".com"); + } + else if (event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) { - loadingColor = QColor(248, 248, 100); + append = QLatin1String(".org"); } - else + 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)) { - loadingColor = QColor(116, 192, 250); + host += append; + url.setHost(host); + setText(url.toString()); } - painter.setBrush(generateGradient(loadingColor, height())); - painter.setPen(Qt::transparent); - - QRect backgroundRect = lineEdit()->frameGeometry(); - int mid = backgroundRect.width() * m_progress / 100; - QRect progressRect(backgroundRect.x(), backgroundRect.y(), mid, backgroundRect.height()); - painter.drawRect(progressRect); - painter.end(); } + + LineEdit::keyPressEvent(event); } -QSize UrlBar::sizeHint() const +void UrlBar::focusInEvent(QFocusEvent *event) { - return lineEdit()->sizeHint(); + activateSuggestions(true); + + LineEdit::focusInEvent(event); } -QLinearGradient UrlBar::generateGradient(const QColor &color, int height) +void UrlBar::setPrivateMode(bool on) { - QColor base = s_defaultBaseColor; - base.setAlpha(0); - QColor barColor = color; - barColor.setAlpha(200); - QLinearGradient gradient(0, 0, 0, height); - gradient.setColorAt(0, base); - gradient.setColorAt(0.25, barColor.lighter(120)); - gradient.setColorAt(0.5, barColor); - gradient.setColorAt(0.75, barColor.lighter(120)); - gradient.setColorAt(1, base); - return gradient; + _privateMode = on; } -void UrlBar::setBackgroundColor(QColor c) +void UrlBar::dropEvent(QDropEvent *event) { - s_defaultBaseColor = c; - repaint(); + LineEdit::dropEvent(event); + activated(text()); } -bool UrlBar::isLoading() +void UrlBar::loadFinished() { - if(m_progress == 0) + if(_tab->progress() != 0) + return; + + if(_tab->url().scheme() == QL1S("about") ) + { + update(); + return; + } + + // show KGet downloads?? + if(ReKonfig::kgetList()) + { + IconButton *bt = addRightIcon(LineEdit::KGet); + connect(bt, SIGNAL(clicked()), _tab->page(), SLOT(downloadAllContentsWithKGet())); + } + + // show RSS + if(_tab->hasRSSInfo()) + { + IconButton *bt = addRightIcon(LineEdit::RSS); + connect(bt, SIGNAL(clicked()), _tab, SLOT(showRSSInfo())); + } + + // show SSL + if(_tab->url().scheme() == QL1S("https") ) { - return false; + IconButton *bt = addRightIcon(LineEdit::SSL); + connect(bt, SIGNAL(clicked()), _tab->page(), SLOT(showSSLInfo())); } - return true; + + update(); } -void UrlBar::keyPressEvent(QKeyEvent *event) +void UrlBar::loadTyped(const QString &text) { - QString currentText = m_lineEdit->text().trimmed(); - if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) + activated(KUrl(text)); +} + + +void UrlBar::activateSuggestions(bool b) +{ + if(b) { - if( !currentText.startsWith(QLatin1String("http://"), Qt::CaseInsensitive) ) + if(_box.isNull()) { - 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()); - } - } - else - { - // fill lineEdit with its stripped contents to remove trailing spaces - m_lineEdit->setText(currentText); + _box = new CompletionWidget(this); + installEventFilter(_box.data()); + connect(_box.data(), SIGNAL(chosenUrl(const KUrl &, Rekonq::OpenType)), this, SLOT(activated(const KUrl &, Rekonq::OpenType))); + + // activate suggestions on edit text + connect(this, SIGNAL(textChanged(const QString &)), _box.data(), SLOT(suggestUrls(const QString &))); } } - - KHistoryComboBox::keyPressEvent(event); + else + { + removeEventFilter(_box.data()); + _box.data()->deleteLater(); + } } diff --git a/src/urlbar/urlbar.h b/src/urlbar/urlbar.h index 8d267b2c..28afc21e 100644 --- a/src/urlbar/urlbar.h +++ b/src/urlbar/urlbar.h @@ -32,22 +32,24 @@ // Local Includes +#include "rekonqprivate_export.h" #include "lineedit.h" +#include "application.h" // KDE Includes #include <KUrl> -#include <KHistoryComboBox> // Qt Includes -#include <QUrl> +#include <QWeakPointer> // Forward Declarations class QLinearGradient; class QWidget; -class KCompletion; +class CompletionWidget; +class WebTab; -class UrlBar : public KHistoryComboBox +class REKONQ_TESTS_EXPORT UrlBar : public LineEdit { Q_OBJECT @@ -55,44 +57,27 @@ public: UrlBar(QWidget *parent = 0); ~UrlBar(); - void selectAll() const; - KUrl url() const; - QSize sizeHint() const; - void setBackgroundColor(QColor); - bool isLoading(); - - void setProgress(int progress); - -signals: - void activated(const KUrl&); + void setPrivateMode(bool on); -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 activated(const KUrl& url, Rekonq::OpenType = Rekonq::CurrentTab); + void setQUrl(const QUrl &url); + void loadFinished(); + void loadTyped(const QString &); + protected: virtual void paintEvent(QPaintEvent *event); virtual void keyPressEvent(QKeyEvent *event); + virtual void focusInEvent(QFocusEvent *event); + virtual void dropEvent(QDropEvent *event); private: - void setupLineEdit(); - - KLineEdit *lineEdit() const; - - static QLinearGradient generateGradient(const QColor &color, int height); - - static QColor s_defaultBaseColor; - - LineEdit *m_lineEdit; - - KUrl m_currentUrl; - int m_progress; + void activateSuggestions(bool); + + QWeakPointer<CompletionWidget> _box; + WebTab *_tab; + bool _privateMode; }; #endif diff --git a/src/urlbar/urlresolver.cpp b/src/urlbar/urlresolver.cpp new file mode 100644 index 00000000..5b4b1625 --- /dev/null +++ b/src/urlbar/urlresolver.cpp @@ -0,0 +1,230 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com> +* +* +* 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 <http://www.gnu.org/licenses/>. +* +* ============================================================ */ + + +// Self Includes +#include "urlresolver.h" + +// Local Includes +#include "application.h" +#include "historymanager.h" +#include "bookmarksmanager.h" + +// KDE Includes +#include <KUriFilter> +#include <KCompletion> +#include <KDebug> +#include <KService> +#include <KConfig> +#include <KConfigGroup> + +// Qt Includes +#include <QString> +#include <QByteArray> +#include <QUrl> + +// defines +#define MAX_ELEMENTS 9 + + +// NOTE default kurifilter plugin list (at least in my box) +// 1. "kshorturifilter" +// 2. "kurisearchfilter" +// 3. "localdomainurifilter" +// 4 ."kuriikwsfilter" +// 5. "fixhosturifilter" + + +bool UrlSearchItem::operator==(UrlSearchItem i) +{ + return url==i.url; +} + + +UrlResolver::UrlResolver(const QString &typedUrl) + : _typedString(typedUrl.trimmed()) +{ +} + + +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; + +// if(isHttp()) +// { +// list << qurlFromUserInputResolution(); +// } + + list << webSearchesResolution(); + + if (_typedString.length() >= 2) + { + list << qurlFromUserInputResolution(); + + 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); + } + + QList<UrlSearchItem> common; + + foreach (UrlSearchItem i, historyList) + { + if (!bookmarksList.contains(i)) + { + list << i; + } + else + { + i.type |= UrlSearchItem::Bookmark; + common << i; + } + } + + foreach (UrlSearchItem i, common) + { + list << i; + } + + foreach (UrlSearchItem i, bookmarksList) + { + if (!common.contains(i)) + list << i; + } + } + + return list; +} + + +bool UrlResolver::isHttp() +{ + QString ipv4 = "^0*([1-9]?\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.0*([1-9]?\\d|1\\d\\d|2[0-4]\\d|25[0-5])"\ + "\\.0*([1-9]?\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.0*([1-9]?\\d|1\\d\\d|2[0-4]\\d|25[0-5])"; + + QString ipv6 = "^([0-9a-fA-F]{4}|0)(\\:([0-9a-fA-F]{4}|0)){7}"; + + QString address = "[\\d\\w-.]+\\.(a[cdefgilmnoqrstuwz]|b[abdefghijmnorstvwyz]|"\ + "c[acdfghiklmnoruvxyz]|d[ejkmnoz]|e[ceghrst]|f[ijkmnor]|g[abdefghilmnpqrstuwy]|"\ + "h[kmnrtu]|i[delmnoqrst]|j[emop]|k[eghimnprwyz]|l[abcikrstuvy]|"\ + "m[acdghklmnopqrstuvwxyz]|n[acefgilopruz]|om|p[aefghklmnrstwy]|qa|r[eouw]|"\ + "s[abcdeghijklmnortuvyz]|t[cdfghjkmnoprtvwz]|u[augkmsyz]|v[aceginu]|w[fs]|"\ + "y[etu]|z[amw]|aero|arpa|biz|com|coop|edu|info|int|gov|mil|museum|name|net|org|"\ + "pro)"; + + return _typedString.startsWith("http://") + || _typedString.startsWith("https://") + || (QRegExp(address, Qt::CaseInsensitive).indexIn(_typedString) != -1) + || (QRegExp(ipv4, Qt::CaseInsensitive).indexIn(_typedString) != -1) + || (QRegExp(ipv6, Qt::CaseInsensitive).indexIn(_typedString) != -1); +} + + +////////////////////////////////////////////////////////////////////////// +// PRIVATE ENGINES + + +// STEP 1 = QUrl from User Input (easily the best solution... ) +UrlSearchList UrlResolver::qurlFromUserInputResolution() +{ + UrlSearchList list; + QString url2 = _typedString; + QUrl urlFromUserInput = QUrl::fromUserInput(url2); + if(urlFromUserInput.isValid()) + { + KUrl gUrl(urlFromUserInput); + QString gTitle = i18n("Browse"); + UrlSearchItem gItem(UrlSearchItem::Browse, gUrl, gTitle); + list << gItem; + } + + return list; +} + + +// STEP 2 = Web Searches +UrlSearchList UrlResolver::webSearchesResolution() +{ + UrlSearchList list; + + if(KUrl(_typedString).isRelative()) + { + UrlSearchItem gItem(UrlSearchItem::Search, KUrl(), QString() ); // others will find this url.. + list << gItem; + } + + return list; +} + + +// STEP 3 = history completion +UrlSearchList UrlResolver::historyResolution() +{ + UrlSearchList list; + + KCompletion *historyCompletion = Application::historyManager()->completionObject(); + QStringList historyResults = historyCompletion->substringCompletion(_typedString); + Q_FOREACH(const QString &s, historyResults) + { + UrlSearchItem it(UrlSearchItem::History, KUrl(s), Application::historyManager()->titleForHistoryUrl(s)); + list << it; + } + + return list; +} + + +// STEP 4 = bookmarks completion +UrlSearchList UrlResolver::bookmarksResolution() +{ + UrlSearchList list; + + KCompletion *bookmarkCompletion = Application::bookmarkProvider()->completionObject(); + QStringList bookmarkResults = bookmarkCompletion->substringCompletion(_typedString); + Q_FOREACH(const QString &s, bookmarkResults) + { + UrlSearchItem it(UrlSearchItem::Bookmark, KUrl(s), Application::bookmarkProvider()->titleForBookmarkUrl(s)); + list << it; + } + + return list; +} diff --git a/src/urlbar/urlresolver.h b/src/urlbar/urlresolver.h new file mode 100644 index 00000000..22a9de4f --- /dev/null +++ b/src/urlbar/urlresolver.h @@ -0,0 +1,85 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com> +* +* +* 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 <http://www.gnu.org/licenses/>. +* +* ============================================================ */ + + +#ifndef URL_RESOLVER_H +#define URL_RESOLVER_H + +// KDE Includes +#include <KUrl> + +// Qt Includes +#include <QString> +#include <QList> + + +class UrlSearchItem +{ + + public: + + enum types + { + Search = 0x00000001, + Browse = 0x00000010, + History = 0x00000100, + Bookmark = 0x00001000, + }; + + int type; + KUrl url; + QString title; + + UrlSearchItem(const int &_type, const KUrl &_url, const QString &_title = QString()) + : type(_type), url(_url), title(_title) + {}; + + bool operator==(UrlSearchItem i); +}; + +typedef QList <UrlSearchItem> UrlSearchList; + + +// ---------------------------------------------------------------------- + + +class UrlResolver +{ +public: + UrlResolver(const QString &typedUrl); + + UrlSearchList orderedSearchItems(); + +private: + QString _typedString; + + UrlSearchList webSearchesResolution(); + UrlSearchList historyResolution(); + UrlSearchList qurlFromUserInputResolution(); + UrlSearchList bookmarksResolution(); + bool isHttp(); +}; + +#endif // URL_RESOLVER_H |