diff options
Diffstat (limited to 'src/urlbar')
-rw-r--r-- | src/urlbar/completionwidget.cpp | 282 | ||||
-rw-r--r-- | src/urlbar/completionwidget.h | 89 | ||||
-rw-r--r-- | src/urlbar/lineedit.cpp | 69 | ||||
-rw-r--r-- | src/urlbar/listitem.cpp | 427 | ||||
-rw-r--r-- | src/urlbar/listitem.h | 220 | ||||
-rw-r--r-- | src/urlbar/rsswidget.cpp | 154 | ||||
-rw-r--r-- | src/urlbar/rsswidget.h (renamed from src/urlbar/lineedit.h) | 49 | ||||
-rw-r--r-- | src/urlbar/urlbar.cpp | 436 | ||||
-rw-r--r-- | src/urlbar/urlbar.h | 104 | ||||
-rw-r--r-- | src/urlbar/urlresolver.cpp | 217 | ||||
-rw-r--r-- | src/urlbar/urlresolver.h | 88 |
11 files changed, 1816 insertions, 319 deletions
diff --git a/src/urlbar/completionwidget.cpp b/src/urlbar/completionwidget.cpp new file mode 100644 index 00000000..6dae6285 --- /dev/null +++ b/src/urlbar/completionwidget.cpp @@ -0,0 +1,282 @@ +/* ============================================================ +* +* 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" +#include "searchengine.h" + +// KDE Includes +#include <KGlobalSettings> +#include <KUrl> + +// Qt Includes +#include <QtCore/QPoint> +#include <QtCore/QSize> +#include <QtCore/QEvent> + +#include <QtGui/QVBoxLayout> +#include <QtGui/QKeyEvent> + + + +CompletionWidget::CompletionWidget(QWidget *parent) + : QFrame(parent, Qt::ToolTip) + , _parent(parent) + , _currentIndex(-1) + , _searchEngine(SearchEngine::defaultEngine()) +{ + 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(const 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(); + } +} + + diff --git a/src/urlbar/completionwidget.h b/src/urlbar/completionwidget.h new file mode 100644 index 00000000..fc0798e7 --- /dev/null +++ b/src/urlbar/completionwidget.h @@ -0,0 +1,89 @@ +/* ============================================================ +* +* 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 + + +// Rekonq Includes +#include "rekonq_defines.h" + +// Local Includes +#include "listitem.h" + +// KDE Includes +#include <KService> + +// 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); + + KService::Ptr searchEngine() + { + return _searchEngine; + }; + + void setCurrentEngine(KService::Ptr 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: + void insertSearchList(const UrlSearchList &list, const QString& text); + void popup(); + void clear(); + + void sizeAndPosition(); + void up(); + void down(); + + QWidget *_parent; + + UrlSearchList _list; + int _currentIndex; + + KService::Ptr _searchEngine; +}; + +#endif // COMPLETION_WIDGET_H diff --git a/src/urlbar/lineedit.cpp b/src/urlbar/lineedit.cpp deleted file mode 100644 index f3c93e8e..00000000 --- a/src/urlbar/lineedit.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* ============================================================ -* -* This file is a part of the rekonq project -* -* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com> -* Copyright (C) 2009 by Paweł Prażak <pawelprazak at gmail dot com> -* Copyright (C) 2009 by Lionel Chauvin <megabigbug@yahoo.fr> -* -* -* 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 "lineedit.h" -#include "lineedit.moc" - -// Qt Includes -#include <QtGui/QContextMenuEvent> -#include <QtGui/QFocusEvent> -#include <QtGui/QKeyEvent> - - -LineEdit::LineEdit(QWidget* parent) - : KLineEdit(parent) -{ - setMinimumWidth(200); - setFocusPolicy(Qt::WheelFocus); - setHandleSignals(true); - setClearButtonShown(true); -} - - -LineEdit::~LineEdit() -{ -} - - -void LineEdit::keyPressEvent(QKeyEvent *event) -{ - if (event->key() == Qt::Key_Escape) - { - clearFocus(); - event->accept(); - } - - KLineEdit::keyPressEvent(event); -} - - -void LineEdit::mouseDoubleClickEvent(QMouseEvent *) -{ - selectAll(); -} diff --git a/src/urlbar/listitem.cpp b/src/urlbar/listitem.cpp new file mode 100644 index 00000000..c6f75348 --- /dev/null +++ b/src/urlbar/listitem.cpp @@ -0,0 +1,427 @@ +/* ============================================================ +* +* 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" +#include "searchengine.h" + +// KDE Includes +#include <KIcon> +#include <KAction> + +// Qt Includes +#include <QActionGroup> +#include <QHBoxLayout> +#include <QVBoxLayout> +#include <QLabel> +#include <QSizePolicy> +#include <QPixmap> +#include <QStylePainter> +#include <QMouseEvent> +#include <QWebSettings> +#include <QFile> + + +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); + + 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; + 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) +{ + QHBoxLayout *hLayout = new QHBoxLayout; + hLayout->setSpacing(4); + + 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); + hLayout->addWidget(previewLabelIcon); + + QVBoxLayout *vLayout = new QVBoxLayout; + vLayout->setMargin(0); + vLayout->addWidget(new TextLabel(item.title, text, this)); + vLayout->addWidget(new TextLabel("<i>" + item.url.url() + "</i>", text, this)); + + hLayout->addLayout(vLayout); + + hLayout->addWidget(new TypeIconLabel(item.type, this)); + + setLayout(hLayout); +} + + +// --------------------------------------------------------------- + + +PreviewLabel::PreviewLabel(const QString &url, int width, int height, QWidget *parent) + : QLabel(parent) +{ + setFixedSize(width, height); + setFrameStyle(QFrame::StyledPanel | QFrame::Raised); + + KUrl u = KUrl(url); + if (WebSnap::existsImage(KUrl(u))) + { + QPixmap preview; + preview.load(WebSnap::imagePathFromUrl(u)); + 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) +{ + KService::Ptr currentEngine = SearchEngine::defaultEngine(); + + QString query = text; + KService::Ptr engine = SearchEngine::fromString(text); + if (engine) + { + query = query.remove(0, text.indexOf(SearchEngine::delimiter()) + 1); + } + else + { + engine = currentEngine; + } + + m_url = SearchEngine::buildQuery(engine, query); + + m_iconLabel = new IconLabel("edit-find", this); //TODO: get the default engine icon + m_titleLabel = new TextLabel(searchItemTitle(engine->name(), query), QString(), this); + m_engineBar = new EngineBar(currentEngine, parent); + + QHBoxLayout *hLayout = new QHBoxLayout; + hLayout->setSpacing(4); + + hLayout->addWidget(m_iconLabel); + hLayout->addWidget(m_titleLabel); + hLayout->addWidget(new QLabel(i18n("Engines: "), this)); + hLayout->addWidget(m_engineBar); + hLayout->addWidget(new TypeIconLabel(item.type, this)); + + setLayout(hLayout); + + connect(m_engineBar, SIGNAL(searchEngineChanged(KService::Ptr)), this, SLOT(changeSearchEngine(KService::Ptr))); +} + + +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)); + m_iconLabel->setPixmap(Application::icon(KUrl(engine->property("Query").toString())).pixmap(16)); + m_url = SearchEngine::buildQuery(engine, m_text); + + CompletionWidget *w = qobject_cast<CompletionWidget *>(parent()); + w->setCurrentEngine(engine); +} + + +void SearchListItem::nextItemSubChoice() +{ + m_engineBar->selectNextEngine(); +} + + +// ----------------------------------------------------------------------------------------------- + + +EngineBar::EngineBar(KService::Ptr selectedEngine, QWidget *parent) + : KToolBar(parent) +{ + setIconSize(QSize(16, 16)); + setToolButtonStyle(Qt::ToolButtonIconOnly); + + m_engineGroup = new QActionGroup(this); + m_engineGroup->setExclusive(true); + + m_engineGroup->addAction(newEngineAction(SearchEngine::defaultEngine(), selectedEngine)); + foreach(KService::Ptr engine, SearchEngine::favorites()) + { + if (engine->desktopEntryName() != SearchEngine::defaultEngine()->desktopEntryName()) + { + m_engineGroup->addAction(newEngineAction(engine, selectedEngine)); + } + } + + addActions(m_engineGroup->actions()); +} + + +KAction *EngineBar::newEngineAction(KService::Ptr engine, KService::Ptr selectedEngine) +{ + QString url = engine->property("Query").toString(); + KAction *a = new KAction(Application::icon(url), engine->name(), this); + a->setCheckable(true); + if (engine->desktopEntryName() == selectedEngine->desktopEntryName()) a->setChecked(true); + a->setData(engine->entryPath()); + connect(a, SIGNAL(triggered(bool)), this, SLOT(changeSearchEngine())); + return a; +} + + +void EngineBar::changeSearchEngine() +{ + KAction *a = qobject_cast<KAction*>(sender()); + emit searchEngineChanged(KService::serviceByDesktopPath(a->data().toString())); +} + + +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; + + kDebug() << text; + + 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 TypeIconLabel(item.type, this)); + + setLayout(hLayout); +} + + +// --------------------------------------------------------------- + + +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..6737ed70 --- /dev/null +++ b/src/urlbar/listitem.h @@ -0,0 +1,220 @@ +/* ============================================================ +* +* 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 + + +// Rekonq Includes +#include "rekonq_defines.h" + +// Local Includes +#include "urlresolver.h" + +// KDE Includes +#include <KToolBar> +#include <KService> + +// Qt Includes +#include <QWidget> +#include <QStyleOptionViewItemV4> +#include <QLabel> + +// Forward Declarations +class UrlSearchItem; +class KAction; +class QActionGroup; + + +class ListItem : public QWidget +{ + Q_OBJECT + +public: + explicit 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: + explicit 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: + explicit EngineBar(KService::Ptr selectedEngine, QWidget *parent = 0); + void selectNextEngine(); + +signals: + void searchEngineChanged(KService::Ptr engine); + +private slots: + void changeSearchEngine(); + +private: + KAction *newEngineAction(KService::Ptr engine, KService::Ptr selectedEngine); + QActionGroup *m_engineGroup; +}; + + +// ------------------------------------------------------------------------- + + +class SearchListItem : public ListItem +{ + Q_OBJECT + +public: + explicit SearchListItem(const UrlSearchItem &item, const QString &text, QWidget *parent = 0); + +public slots: + virtual void nextItemSubChoice(); + +private slots: + void changeSearchEngine(KService::Ptr engine); + +private: + QString searchItemTitle(QString engine, QString text); + + TextLabel* m_titleLabel; + IconLabel* m_iconLabel; + EngineBar* m_engineBar; + QString m_text; + KService::Ptr m_currentEngine; +}; + + +// ------------------------------------------------------------------------- + + +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/rsswidget.cpp b/src/urlbar/rsswidget.cpp new file mode 100644 index 00000000..1cce6e8c --- /dev/null +++ b/src/urlbar/rsswidget.cpp @@ -0,0 +1,154 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2010 by Matthieu Gicquel <matgic78 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/>. +* +* ============================================================ */ + + +// Auto Includes +#include "rsswidget.h" +#include "rsswidget.moc" + +// Local includes +#include "application.h" +#include "mainwindow.h" +#include "webtab.h" +#include "webview.h" + +// KDE Includes +#include <KLocalizedString> +#include <KIcon> +#include <KProcess> +#include <KMessageBox> + +// Qt Includes +#include <QtGui/QFormLayout> +#include <QtGui/QDialogButtonBox> +#include <QtGui/QLabel> +#include <QtGui/QPushButton> + +#include <QtDBus/QDBusInterface> +#include <QtDBus/QDBusConnectionInterface> + + + +RSSWidget::RSSWidget(QMap< KUrl, QString > map, QWidget *parent) + : QFrame(parent, Qt::Popup) + , m_map(map) +{ + setAttribute(Qt::WA_DeleteOnClose); + setFixedWidth(250); + setFrameStyle(Panel); + + QFormLayout *layout = new QFormLayout(this); + setLayout(layout); + + QLabel *agregator = new QLabel(this); + agregator->setText(i18n("Aggregator:")); + + m_agregators = new KComboBox(this); + m_agregators->addItem(KIcon("application-rss+xml"), QString("Akregator")); + m_agregators->addItem(Application::icon(KUrl("http://google.com/reader")), i18n("Google Reader")); + + layout->addRow(agregator, m_agregators); + + + QLabel *feed = new QLabel(this); + feed->setText(i18n("Feed:")); + + m_feeds = new KComboBox(this); + + foreach(const QString &title, m_map) + { + m_feeds->addItem(title); + } + + layout->addRow(feed, m_feeds); + + + QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this); + buttonBox->button(QDialogButtonBox::Ok)->setText(i18n("Add Feed")); + connect(buttonBox, SIGNAL(accepted()), this, SLOT(accepted())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(close())); + + layout->addWidget(buttonBox); +} + + +void RSSWidget::showAt(QPoint pos) +{ + pos.setX(pos.x() - 200); + pos.setY(pos.y() + 10); + move(pos); + show(); +} + + +void RSSWidget::accepted() +{ + QString url = m_map.key(m_feeds->currentText()).toMimeDataString(); + + if (m_agregators->currentIndex() == 0) + addWithAkregator(url); + else + addWithGoogleReader(url); + + close(); +} + + +void RSSWidget::addWithGoogleReader(QString url) +{ + KUrl toLoad = KUrl("http://www.google.com/ig/add?feedurl=" + url); + Application::instance()->mainWindow()->currentTab()->view()->load(toLoad); +} + + +void RSSWidget::addWithAkregator(QString url) +{ + // Akregator is running + if (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.akregator")) + { + QDBusInterface akregator("org.kde.akregator", "/Akregator", "org.kde.akregator.part"); + QDBusReply<void> reply = akregator.call("addFeedsToGroup", QStringList(url) , i18n("Imported Feeds")); + + if (!reply.isValid()) + { + KMessageBox::error(0, QString(i18n("Could not add stream to akregator, Please add it manually :") + + "<br /><br /> <a href=\"" + url + "\">" + url + "</a>")); + } + } + // Akregator is not running + else + { + KProcess proc; + proc << "akregator" << "-g" << i18n("Imported Feeds"); + proc << "-a" << url; + if (proc.startDetached() == 0) + { + KMessageBox::error(0, QString(i18n("There was an error. Please verify Akregator is installed on your system.") + + "<br /><br /> <a href=\"" + url + "\">" + url + "</a>")); + } + + } +} + diff --git a/src/urlbar/lineedit.h b/src/urlbar/rsswidget.h index 67ded052..258107eb 100644 --- a/src/urlbar/lineedit.h +++ b/src/urlbar/rsswidget.h @@ -2,9 +2,7 @@ * * This file is a part of the rekonq project * -* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com> -* Copyright (C) 2009 by Paweł Prażak <pawelprazak at gmail dot com> -* Copyright (C) 2009 by Lionel Chauvin <megabigbug@yahoo.fr> +* Copyright (C) 2010 by Matthieu Gicquel <matgic78 at gmail dot com> * * * This program is free software; you can redistribute it and/or @@ -12,9 +10,9 @@ * 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 +* 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 @@ -26,30 +24,43 @@ * ============================================================ */ -#ifndef LINEEDIT_H -#define LINEEDIT_H +#ifndef RSSWIDGET_H +#define RSSWIDGET_H +// Rekonq Includes +#include "rekonq_defines.h" // KDE Includes -#include <KLineEdit> +#include <KComboBox> +#include <KUrl> + +// Qt Includes +#include <QtCore/QMap> -// Forward Declarations -class QContextMenuEvent; -class QFocusEvent; -class QKeyEvent; +#include <QtGui/QFrame> -class LineEdit : public KLineEdit +class RSSWidget : public QFrame { Q_OBJECT public: - explicit LineEdit(QWidget *parent = 0); - virtual ~LineEdit(); + // QMap< feedUrl, feedTitle> + RSSWidget(QMap<KUrl, QString> map, QWidget *parent); + + void showAt(QPoint pos); + +public slots: + void accepted(); + +private: + void addWithAkregator(QString url); + void addWithGoogleReader(QString url); + + QMap<KUrl, QString> m_map; -protected: - virtual void keyPressEvent(QKeyEvent*); - virtual void mouseDoubleClickEvent(QMouseEvent *); + KComboBox *m_agregators; + KComboBox *m_feeds; }; -#endif // LINEEDIT_H +#endif // RSSWIDGET_H diff --git a/src/urlbar/urlbar.cpp b/src/urlbar/urlbar.cpp index be19dae4..ad0f34a1 100644 --- a/src/urlbar/urlbar.cpp +++ b/src/urlbar/urlbar.cpp @@ -13,9 +13,9 @@ * 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 +* 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 @@ -31,307 +31,361 @@ #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 "webpage.h" #include "webview.h" -#include "historymanager.h" +#include "completionwidget.h" // KDE Includes -#include <KDebug> #include <KCompletionBox> -#include <KUrl> // Qt Includes -#include <QPainter> -#include <QPaintEvent> -#include <QPalette> -#include <QTimer> +#include <QtGui/QPainter> +#include <QtGui/QPaintEvent> +#include <QtGui/QPalette> +#include <QtGui/QVBoxLayout> -QColor UrlBar::s_defaultBaseColor; +IconButton::IconButton(QWidget *parent) + : QToolButton(parent) +{ + setToolButtonStyle(Qt::ToolButtonIconOnly); + setStyleSheet("IconButton { background-color:transparent; border: none; padding: 0px}"); + setCursor(Qt::ArrowCursor); +} -UrlBar::UrlBar(QWidget *parent) - : KHistoryComboBox(true, parent) - , m_lineEdit(new LineEdit) - , m_progress(0) +void IconButton::mouseReleaseEvent(QMouseEvent* event) { - setUrlDropsEnabled(true); - setAutoDeleteCompletionObject(true); + emit clicked(event->globalPos()); +} - //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&))); - connect(this, SIGNAL(cleared()), SLOT(cleared())); +UrlBar::UrlBar(QWidget *parent) + : KLineEdit(parent) + , _tab(0) + , _privateMode(false) + , _icon(new IconButton(this)) +{ + // initial style + setStyleSheet(QString("UrlBar { padding: 0 0 0 %1px;} ").arg(_icon->sizeHint().width())); - // 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); + // cosmetic + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + setMinimumWidth(200); + setMinimumHeight(26); - // load urls on activated urlbar signal - connect(this, SIGNAL(activated(const KUrl&)), Application::instance(), SLOT(loadUrl(const KUrl&))); -} + // doesn't show the clear button + setClearButtonShown(false); + // trap Key_Enter & Key_Return events, while emitting the returnPressed signal + setTrapReturnKey(true); -UrlBar::~UrlBar() -{ -} + // insert decoded URLs + setUrlDropsEnabled(true); + // accept focus, via tabbing, clicking & wheeling + setFocusPolicy(Qt::WheelFocus); -void UrlBar::selectAll() const -{ - lineEdit()->selectAll(); -} + // disable completion object (we have our own :) ) + setCompletionObject(0); + _tab = qobject_cast<WebTab *>(parent); -KUrl UrlBar::url() const -{ - return m_currentUrl; -} + 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())); + // load typed urls + connect(this, SIGNAL(returnPressed(const QString &)), this, SLOT(loadTyped(const QString &))); -KLineEdit *UrlBar::lineEdit() const -{ - return m_lineEdit; + activateSuggestions(true); } -void UrlBar::setupLineEdit() +UrlBar::~UrlBar() { - // 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(); + activateSuggestions(false); + delete _icon; + _box.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(); + _icon->setIcon(KIcon("arrow-right")); + clear(); setFocus(); } else { - m_currentUrl = KUrl(url); + clearFocus(); + KLineEdit::setUrl(url); + setCursorPosition(0); + _icon->setIcon(Application::icon(url)); } - updateUrl(); } -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()) + QColor backgroundColor; + if (_privateMode) { - kDebug() << "Don't change my typed url..."; - return; - } - - KIcon icon; - if(m_currentUrl.isEmpty()) - { - icon = KIcon("arrow-right"); + backgroundColor = QColor(220, 220, 220); // light gray } - else + else { - icon = Application::icon(m_currentUrl); + backgroundColor = Application::palette().color(QPalette::Base); } - if (count()) + // set background color of UrlBar + QPalette p = palette(); + + int progr = _tab->progress(); + if (progr == 0) { - changeUrl(0, icon, m_currentUrl); + if (_tab->url().scheme() == QL1S("https")) + { + backgroundColor = QColor(255, 255, 171); // light yellow + } + p.setBrush(QPalette::Base, backgroundColor); } else { - insertUrl(0, icon, m_currentUrl); + 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); - setCurrentIndex(0); + // you need this before our code to draw inside the line edit.. + KLineEdit::paintEvent(event); - // important security consideration: always display the beginning - // of the url rather than its end to prevent spoofing attempts. - // Must be AFTER setCurrentIndex - if (!hasFocus()) + if (text().isEmpty()) { - lineEdit()->setCursorPosition(0); + 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("Start typing here to search your bookmarks, history and the web...") + ); } } -void UrlBar::activated(const QString& urlString) +void UrlBar::keyPressEvent(QKeyEvent *event) { - if (urlString.isEmpty()) - return; + // this handles the Modifiers + Return key combinations + QString currentText = text().trimmed(); + if ((event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) + && !currentText.startsWith(QL1S("http://"), Qt::CaseInsensitive)) + { + QString append; + if (event->modifiers() == Qt::ControlModifier) + { + append = QL1S(".com"); + } + else if (event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) + { + append = QL1S(".org"); + } + else if (event->modifiers() == Qt::ShiftModifier) + { + append = QL1S(".net"); + } + + QUrl url(QL1S("http://www.") + currentText); + QString host = url.host(); + if (!host.endsWith(append, Qt::CaseInsensitive)) + { + host += append; + url.setHost(host); + setText(url.toString()); + } + } - setUrl(urlString); - emit activated(m_currentUrl); + if (event->key() == Qt::Key_Escape) + { + clearFocus(); + event->accept(); + } + + KLineEdit::keyPressEvent(event); } -void UrlBar::cleared() +void UrlBar::focusInEvent(QFocusEvent *event) { - // clear the history on user's request from context menu - clear(); + activateSuggestions(true); + + KLineEdit::focusInEvent(event); } -void UrlBar::loadFinished(bool) +void UrlBar::setPrivateMode(bool on) { - // reset progress bar after small delay - m_progress = 0; - QTimer::singleShot(200, this, SLOT(repaint())); + _privateMode = on; } -void UrlBar::updateProgress(int progress) +void UrlBar::dropEvent(QDropEvent *event) { - m_progress = progress; - repaint(); + KLineEdit::dropEvent(event); + activated(text()); } -void UrlBar::paintEvent(QPaintEvent *event) +void UrlBar::loadFinished() { - // set background color of UrlBar - QPalette p = palette(); - p.setColor(QPalette::Base, s_defaultBaseColor); - setPalette(p); + if (_tab->progress() != 0) + return; - KHistoryComboBox::paintEvent(event); + if (_tab->url().scheme() == QL1S("about")) + { + update(); + return; + } - if (!hasFocus()) + // show KGet downloads?? + if (ReKonfig::kgetList()) { - QPainter painter(this); + IconButton *bt = addRightIcon(UrlBar::KGet); + connect(bt, SIGNAL(clicked(QPoint)), _tab->page(), SLOT(downloadAllContentsWithKGet(QPoint))); + } - QColor loadingColor; - if (m_currentUrl.scheme() == QLatin1String("https")) - { - loadingColor = QColor(248, 248, 100); - } - else - { - loadingColor = QColor(116, 192, 250); - } - 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(); + // show RSS + if (_tab->hasRSSInfo()) + { + IconButton *bt = addRightIcon(UrlBar::RSS); + connect(bt, SIGNAL(clicked(QPoint)), _tab, SLOT(showRSSInfo(QPoint))); + } + + // show SSL + if (_tab->url().scheme() == QL1S("https")) + { + IconButton *bt = addRightIcon(UrlBar::SSL); + connect(bt, SIGNAL(clicked(QPoint)), _tab->page(), SLOT(showSSLInfo(QPoint))); } + + update(); } -QSize UrlBar::sizeHint() const +void UrlBar::loadTyped(const QString &text) { - return lineEdit()->sizeHint(); + activated(KUrl(text)); } -QLinearGradient UrlBar::generateGradient(const QColor &color, int height) +void UrlBar::activateSuggestions(bool b) { - 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; + if (b) + { + if (_box.isNull()) + { + _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 &))); + } + } + else + { + removeEventFilter(_box.data()); + _box.data()->deleteLater(); + } } -void UrlBar::setBackgroundColor(QColor c) +void UrlBar::mouseDoubleClickEvent(QMouseEvent *) { - s_defaultBaseColor = c; - repaint(); + selectAll(); } -bool UrlBar::isLoading() +IconButton *UrlBar::addRightIcon(UrlBar::icon ic) { - if(m_progress == 0) + IconButton *rightIcon = new IconButton(this); + + switch (ic) { - return false; + case UrlBar::KGet: + rightIcon->setIcon(KIcon("download")); + rightIcon->setToolTip(i18n("List all links with KGet")); + break; + case UrlBar::RSS: + rightIcon->setIcon(KIcon("application-rss+xml")); + rightIcon->setToolTip(i18n("List all available RSS feeds")); + break; + case UrlBar::SSL: + rightIcon->setIcon(KIcon("object-locked")); + rightIcon->setToolTip(i18n("Show SSL Info")); + break; + default: + kDebug() << "ERROR.. default non extant case!!"; + break; } - return true; + + _rightIconsList << rightIcon; + int iconsCount = _rightIconsList.count(); + rightIcon->move(width() - 23*iconsCount, 6); + rightIcon->show(); + + return rightIcon; } -void UrlBar::keyPressEvent(QKeyEvent *event) + +void UrlBar::clearRightIcons() { - QString currentText = m_lineEdit->text().trimmed(); - if ((event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) - && !currentText.startsWith(QLatin1String("http://"), Qt::CaseInsensitive)) - { - 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"); - } + qDeleteAll(_rightIconsList); + _rightIconsList.clear(); +} - 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()); - } + +void UrlBar::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); } - KHistoryComboBox::keyPressEvent(event); -} + KLineEdit::resizeEvent(event); +} diff --git a/src/urlbar/urlbar.h b/src/urlbar/urlbar.h index 8d267b2c..b644f84f 100644 --- a/src/urlbar/urlbar.h +++ b/src/urlbar/urlbar.h @@ -13,9 +13,9 @@ * 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 +* 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 @@ -30,69 +30,93 @@ #ifndef URLBAR_H #define URLBAR_H - -// Local Includes -#include "lineedit.h" +// Rekonq Includes +#include "rekonq_defines.h" // KDE Includes #include <KUrl> -#include <KHistoryComboBox> +#include <KLineEdit> // Qt Includes -#include <QUrl> +#include <QWeakPointer> +#include <QToolButton> // Forward Declarations class QLinearGradient; class QWidget; -class KCompletion; +class CompletionWidget; +class WebTab; -class UrlBar : public KHistoryComboBox +class IconButton : public QToolButton { Q_OBJECT public: - UrlBar(QWidget *parent = 0); - ~UrlBar(); - - void selectAll() const; - KUrl url() const; - QSize sizeHint() const; - void setBackgroundColor(QColor); - bool isLoading(); + IconButton(QWidget *parent = 0); - 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 clicked(QPoint); protected: - virtual void paintEvent(QPaintEvent *event); - virtual void keyPressEvent(QKeyEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + +}; + + +// Definitions +typedef QList<IconButton *> IconButtonPointerList; + + +// ------------------------------------------------------------------------------------ -private: - void setupLineEdit(); - KLineEdit *lineEdit() const; +class REKONQ_TESTS_EXPORT UrlBar : public KLineEdit +{ + Q_OBJECT + +public: - static QLinearGradient generateGradient(const QColor &color, int height); + enum icon + { + KGet = 0x00000001, + RSS = 0x00000010, + SSL = 0x00000100, + }; - static QColor s_defaultBaseColor; + explicit UrlBar(QWidget *parent = 0); + ~UrlBar(); + + void setPrivateMode(bool on); + +private slots: + void activated(const KUrl& url, Rekonq::OpenType = Rekonq::CurrentTab); + void setQUrl(const QUrl &url); - LineEdit *m_lineEdit; + void loadFinished(); + void loadTyped(const QString &); - KUrl m_currentUrl; - int m_progress; + void clearRightIcons(); + +protected: + void paintEvent(QPaintEvent *event); + void keyPressEvent(QKeyEvent *event); + void focusInEvent(QFocusEvent *event); + void dropEvent(QDropEvent *event); + void mouseDoubleClickEvent(QMouseEvent *); + void resizeEvent(QResizeEvent *); + +private: + IconButton *addRightIcon(UrlBar::icon); + void activateSuggestions(bool); + + QWeakPointer<CompletionWidget> _box; + WebTab *_tab; + bool _privateMode; + + IconButton *_icon; + IconButtonPointerList _rightIconsList; }; + #endif diff --git a/src/urlbar/urlresolver.cpp b/src/urlbar/urlresolver.cpp new file mode 100644 index 00000000..276c2531 --- /dev/null +++ b/src/urlbar/urlresolver.cpp @@ -0,0 +1,217 @@ +/* ============================================================ +* +* 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 <KService> +#include <KConfig> +#include <KConfigGroup> + +// Qt Includes +#include <QByteArray> + +// 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==(const 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 << qurlFromUserInputResolution(); + list << webSearchesResolution(); + + if (_typedString.length() >= 2) + { + 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(const UrlSearchItem &i, common) + { + list << i; + } + + foreach(const 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( QL1S("http://") ) + || _typedString.startsWith( QL1S("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()) + { + QString gTitle = i18nc("Browse a website", "Browse"); + UrlSearchItem gItem(UrlSearchItem::Browse, urlFromUserInput, gTitle); + list << gItem; + } + + return list; +} + + +// STEP 2 = Web Searches +UrlSearchList UrlResolver::webSearchesResolution() +{ + return UrlSearchList() << UrlSearchItem(UrlSearchItem::Search, KUrl(), QString()); +} + + +// 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..d3cdedbe --- /dev/null +++ b/src/urlbar/urlresolver.h @@ -0,0 +1,88 @@ +/* ============================================================ +* +* 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 + + +// Rekonq Includes +#include "rekonq_defines.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==(const 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 |