From 64bdafde87f2adb892801e08838191588297eb44 Mon Sep 17 00:00:00 2001 From: nowrep Date: Sun, 22 Apr 2012 17:09:43 +0200 Subject: [PATCH] Completely rewritten whole completion for address bar. - fixed occasional flickering when typing in address bar - support for opening completions with pressing Down key - support for selecting completions with Tab key closes #105 --- src/lib/lib.pro | 12 +- .../completer/locationcompleter.cpp | 120 +++++++++++ .../navigation/completer/locationcompleter.h | 63 ++++++ .../locationcompleterdelegate.cpp | 86 +------- .../locationcompleterdelegate.h | 29 +-- .../locationcompletermodel.cpp} | 81 ++++---- .../locationcompletermodel.h} | 28 +-- .../completer/locationcompleterview.cpp | 188 ++++++++++++++++++ .../completer/locationcompleterview.h | 53 +++++ src/lib/navigation/locationbar.cpp | 38 ++-- src/lib/navigation/locationbar.h | 7 +- 11 files changed, 519 insertions(+), 186 deletions(-) create mode 100644 src/lib/navigation/completer/locationcompleter.cpp create mode 100644 src/lib/navigation/completer/locationcompleter.h rename src/lib/navigation/{ => completer}/locationcompleterdelegate.cpp (70%) rename src/lib/navigation/{ => completer}/locationcompleterdelegate.h (67%) rename src/lib/navigation/{locationcompleter.cpp => completer/locationcompletermodel.cpp} (75%) rename src/lib/navigation/{locationcompleter.h => completer/locationcompletermodel.h} (65%) create mode 100644 src/lib/navigation/completer/locationcompleterview.cpp create mode 100644 src/lib/navigation/completer/locationcompleterview.h diff --git a/src/lib/lib.pro b/src/lib/lib.pro index 7dabf2fea..89ad489c1 100644 --- a/src/lib/lib.pro +++ b/src/lib/lib.pro @@ -50,7 +50,6 @@ SOURCES += \ history/historymodel.cpp \ history/historymanager.cpp \ navigation/websearchbar.cpp \ - navigation/locationcompleter.cpp \ navigation/locationbar.cpp \ network/networkmanagerproxy.cpp \ network/networkmanager.cpp \ @@ -170,7 +169,10 @@ SOURCES += \ tools/plaineditwithlines.cpp \ webview/websettings.cpp \ tools/focusselectlineedit.cpp \ - navigation/locationcompleterdelegate.cpp + navigation/completer/locationcompleterdelegate.cpp \ + navigation/completer/locationcompleter.cpp \ + navigation/completer/locationcompletermodel.cpp \ + navigation/completer/locationcompleterview.cpp HEADERS += \ webview/tabpreview.h \ @@ -189,7 +191,6 @@ HEADERS += \ history/historymodel.h \ history/historymanager.h \ navigation/websearchbar.h \ - navigation/locationcompleter.h \ navigation/locationbar.h \ network/networkmanagerproxy.h \ network/networkmanager.h \ @@ -313,7 +314,10 @@ HEADERS += \ sidebar/sidebarinterface.h \ webview/websettings.h \ tools/focusselectlineedit.h \ - navigation/locationcompleterdelegate.h + navigation/completer/locationcompleterdelegate.h \ + navigation/completer/locationcompleter.h \ + navigation/completer/locationcompletermodel.h \ + navigation/completer/locationcompleterview.h FORMS += \ preferences/autofillmanager.ui \ diff --git a/src/lib/navigation/completer/locationcompleter.cpp b/src/lib/navigation/completer/locationcompleter.cpp new file mode 100644 index 000000000..c6f091d3d --- /dev/null +++ b/src/lib/navigation/completer/locationcompleter.cpp @@ -0,0 +1,120 @@ +/* ============================================================ +* QupZilla - WebKit based browser +* Copyright (C) 2010-2012 David Rosca +* +* 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 3 of the License, or +* (at your option) any later version. +* +* 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 . +* ============================================================ */ +#include "locationcompleter.h" +#include "locationcompletermodel.h" +#include "locationcompleterview.h" +#include "locationcompleterdelegate.h" +#include "locationbar.h" + +LocationCompleterView* LocationCompleter::s_view = 0; +LocationCompleterModel* LocationCompleter::s_model = 0; + +LocationCompleter::LocationCompleter(QObject* parent) + : QObject(parent) + , m_locationBar(0) +{ + if (!s_view) { + s_model = new LocationCompleterModel; + s_view = new LocationCompleterView; + + s_view->setModel(s_model); + s_view->setItemDelegate(new LocationCompleterDelegate(s_view)); + } +} + +void LocationCompleter::setLocationBar(LocationBar* locationBar) +{ + m_locationBar = locationBar; +} + +void LocationCompleter::closePopup() +{ + s_view->close(); +} + +void LocationCompleter::complete(const QString &string) +{ + s_model->refreshCompletions(string); + + showPopup(); +} + +void LocationCompleter::showMostVisited() +{ + s_model->refreshCompletions(QString()); + + showPopup(); +} + +void LocationCompleter::currentChanged(const QModelIndex &index) +{ + QString completion = index.data().toString(); + if (completion.isEmpty()) { + completion = m_originalText; + } + + emit showCompletion(completion); +} + +void LocationCompleter::popupClosed() +{ + disconnect(s_view->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), this, SLOT(currentChanged(QModelIndex))); + disconnect(s_view, SIGNAL(clicked(QModelIndex)), this, SIGNAL(completionActivated())); + disconnect(s_view, SIGNAL(closed()), this, SLOT(popupClosed())); +} + +void LocationCompleter::showPopup() +{ + Q_ASSERT(m_locationBar); + + if (s_model->rowCount() == 0) { + s_view->close(); + return; + } + + if (s_view->isVisible()) { + adjustPopupSize(); + return; + } + + QRect popupRect(m_locationBar->mapToGlobal(m_locationBar->pos()), m_locationBar->size()); + popupRect.setY(popupRect.bottom()); + + s_view->setFocusProxy(m_locationBar); + s_view->setGeometry(popupRect); + + connect(s_view->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), this, SLOT(currentChanged(QModelIndex))); + connect(s_view, SIGNAL(clicked(QModelIndex)), this, SIGNAL(completionActivated())); + connect(s_view, SIGNAL(closed()), this, SLOT(popupClosed())); + + adjustPopupSize(); +} + +void LocationCompleter::adjustPopupSize() +{ + const int maxItemsCount = 6; + + int popupHeight = s_view->sizeHintForRow(0) * qMin(maxItemsCount, s_model->rowCount()); + popupHeight += 2 * s_view->frameWidth(); + + s_view->resize(s_view->width(), popupHeight); + s_view->setCurrentIndex(QModelIndex()); + s_view->show(); + + m_originalText = m_locationBar->text(); +} diff --git a/src/lib/navigation/completer/locationcompleter.h b/src/lib/navigation/completer/locationcompleter.h new file mode 100644 index 000000000..635d7ad65 --- /dev/null +++ b/src/lib/navigation/completer/locationcompleter.h @@ -0,0 +1,63 @@ +/* ============================================================ +* QupZilla - WebKit based browser +* Copyright (C) 2010-2012 David Rosca +* +* 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 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* ============================================================ */ +#ifndef LOCATIONCOMPLETER_H +#define LOCATIONCOMPLETER_H + +#include + +#include "qz_namespace.h" + +class QModelIndex; + +class LocationCompleterModel; +class LocationCompleterView; +class LocationBar; + +class QT_QUPZILLA_EXPORT LocationCompleter : public QObject +{ + Q_OBJECT +public: + explicit LocationCompleter(QObject* parent = 0); + + void setLocationBar(LocationBar* locationBar); + void closePopup(); + +signals: + void showCompletion(const QString &); + void completionActivated(); + +public slots: + void complete(const QString &string); + void showMostVisited(); + +private slots: + void currentChanged(const QModelIndex &index); + void popupClosed(); + +private: + void showPopup(); + void adjustPopupSize(); + + LocationBar* m_locationBar; + QString m_originalText; + + static LocationCompleterView* s_view; + static LocationCompleterModel* s_model; +}; + +#endif // LOCATIONCOMPLETER_H diff --git a/src/lib/navigation/locationcompleterdelegate.cpp b/src/lib/navigation/completer/locationcompleterdelegate.cpp similarity index 70% rename from src/lib/navigation/locationcompleterdelegate.cpp rename to src/lib/navigation/completer/locationcompleterdelegate.cpp index d7179b94b..827d137dc 100644 --- a/src/lib/navigation/locationcompleterdelegate.cpp +++ b/src/lib/navigation/completer/locationcompleterdelegate.cpp @@ -16,78 +16,17 @@ * along with this program. If not, see . * ============================================================ */ #include "locationcompleterdelegate.h" +#include "locationcompleterview.h" #include #include #include -#include - -CompleterListView::CompleterListView(QWidget* parent) - : QListView(parent) - , m_selectedItemByMousePosition(false) - , m_rowHeight(0) -{ - setMouseTracking(true); - setUniformItemSizes(true); -} - -bool CompleterListView::ignoreSelectedFlag() const -{ - return m_selectedItemByMousePosition; -} - -int CompleterListView::rowHeight() const -{ - return m_rowHeight; -} - -void CompleterListView::setRowHeight(int height) -{ - m_rowHeight = height; -} - -void CompleterListView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) -{ - m_selectedItemByMousePosition = false; - m_lastMouseIndex = current; - - QListView::currentChanged(current, previous); - - viewport()->repaint(); -} - -void CompleterListView::mouseMoveEvent(QMouseEvent* event) -{ - QModelIndex last = m_lastMouseIndex; - QModelIndex atCursor = indexAt(mapFromGlobal(QCursor::pos())); - - if (atCursor.isValid()) { - m_lastMouseIndex = atCursor; - m_selectedItemByMousePosition = true; - } - - if (last != atCursor) { - viewport()->repaint(); - } - - QListView::mouseMoveEvent(event); -} - -void CompleterListView::keyPressEvent(QKeyEvent* event) -{ - if (currentIndex() != m_lastMouseIndex) { - setCurrentIndex(m_lastMouseIndex); - } - - QListView::keyPressEvent(event); -} - -LocationCompleterDelegate::LocationCompleterDelegate(CompleterListView* parent) +LocationCompleterDelegate::LocationCompleterDelegate(LocationCompleterView* parent) : QStyledItemDelegate(parent) , m_rowHeight(0) , m_padding(0) - , m_listView(parent) + , m_view(parent) { } @@ -110,14 +49,15 @@ void LocationCompleterDelegate::paint(QPainter* painter, const QStyleOptionViewI int leftPosition = m_padding * 2; int rightPosition = opt.rect.right() - m_padding; - if (m_listView->ignoreSelectedFlag()) { - if (opt.state.testFlag(QStyle::State_MouseOver)) { - opt.state |= QStyle::State_Selected; - } - else { - opt.state &= ~QStyle::State_Selected; - } +// if (m_view->ignoreSelectedFlag()) { +// if (opt.state.testFlag(QStyle::State_MouseOver)) { + if (m_view->hoveredIndex() == index) { + opt.state |= QStyle::State_Selected; } + else { + opt.state &= ~QStyle::State_Selected; + } +// } const QPalette::ColorRole colorRole = opt.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text; const QPalette::ColorRole colorLinkRole = opt.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Link; @@ -169,11 +109,7 @@ QSize LocationCompleterDelegate::sizeHint(const QStyleOptionViewItem &option, co const QFontMetrics titleMetrics(titleFont); m_rowHeight = 2 * m_padding + opt.fontMetrics.leading() + opt.fontMetrics.height() + titleMetrics.height(); - - m_listView->setRowHeight(m_rowHeight); - m_listView->setMaximumHeight(6 * m_rowHeight); } return QSize(200, m_rowHeight); } - diff --git a/src/lib/navigation/locationcompleterdelegate.h b/src/lib/navigation/completer/locationcompleterdelegate.h similarity index 67% rename from src/lib/navigation/locationcompleterdelegate.h rename to src/lib/navigation/completer/locationcompleterdelegate.h index 2cc012f75..7d4f9bcbd 100644 --- a/src/lib/navigation/locationcompleterdelegate.h +++ b/src/lib/navigation/completer/locationcompleterdelegate.h @@ -19,38 +19,15 @@ #define LOCATIONCOMPLETERDELEGATE_H #include -#include #include "qz_namespace.h" -class QT_QUPZILLA_EXPORT CompleterListView : public QListView -{ - Q_OBJECT -public: - explicit CompleterListView(QWidget* parent = 0); - - bool ignoreSelectedFlag() const; - - int rowHeight() const; - void setRowHeight(int height); - -private slots: - void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); -protected: - void mouseMoveEvent(QMouseEvent* event); - void keyPressEvent(QKeyEvent* event); - -private: - bool m_selectedItemByMousePosition; - int m_rowHeight; - - QModelIndex m_lastMouseIndex; -}; +class LocationCompleterView; class QT_QUPZILLA_EXPORT LocationCompleterDelegate : public QStyledItemDelegate { public: - explicit LocationCompleterDelegate(CompleterListView* parent = 0); + explicit LocationCompleterDelegate(LocationCompleterView* parent = 0); void paint(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; @@ -59,7 +36,7 @@ private: mutable int m_rowHeight; mutable int m_padding; - CompleterListView* m_listView; + LocationCompleterView* m_view; }; #endif // LOCATIONCOMPLETERDELEGATE_H diff --git a/src/lib/navigation/locationcompleter.cpp b/src/lib/navigation/completer/locationcompletermodel.cpp similarity index 75% rename from src/lib/navigation/locationcompleter.cpp rename to src/lib/navigation/completer/locationcompletermodel.cpp index 919a1b9c7..25c8550db 100644 --- a/src/lib/navigation/locationcompleter.cpp +++ b/src/lib/navigation/completer/locationcompletermodel.cpp @@ -15,65 +15,37 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ============================================================ */ -#include "locationcompleter.h" -#include "locationcompleterdelegate.h" -#include "locationbar.h" +#include "locationcompletermodel.h" #include "iconprovider.h" #include "mainapplication.h" -#include #include -LocationCompleter::LocationCompleter(QObject* parent) - : QCompleter(parent) +LocationCompleterModel::LocationCompleterModel(QObject* parent) + : QStandardItemModel(parent) + , m_lastCompletion(QChar(QChar::Nbsp)) { - m_model = new QStandardItemModel(); - - m_listView = new CompleterListView(); - m_listView->setItemDelegateForColumn(0, new LocationCompleterDelegate(m_listView)); - - setModel(m_model); - setPopup(m_listView); - - setCompletionMode(QCompleter::PopupCompletion); - setMaxVisibleItems(6); } -QStringList LocationCompleter::splitPath(const QString &path) const +void LocationCompleterModel::refreshCompletions(const QString &string) { - Q_UNUSED(path); - return QStringList(); -} - -void LocationCompleter::showMostVisited() -{ - m_model->clear(); - - QSqlQuery query; - query.exec("SELECT url, title FROM history ORDER BY count DESC LIMIT 15"); - - while (query.next()) { - QStandardItem* item = new QStandardItem(); - const QUrl &url = query.value(0).toUrl(); - - item->setIcon(_iconForUrl(url)); - item->setText(url.toEncoded()); - item->setData(query.value(1), Qt::UserRole); - - m_model->appendRow(item); + if (m_lastCompletion == string) { + return; } - QCompleter::complete(); -} + m_lastCompletion = string; + + if (string.isEmpty()) { + showMostVisited(); + return; + } + + clear(); -void LocationCompleter::refreshCompleter(const QString &string) -{ int limit = string.size() < 3 ? 25 : 15; QString searchString = QString("%%1%").arg(string); QList urlList; - m_model->clear(); - QSqlQuery query; query.prepare("SELECT url, title, icon FROM bookmarks WHERE title LIKE ? OR url LIKE ? LIMIT ?"); query.addBindValue(searchString); @@ -89,7 +61,7 @@ void LocationCompleter::refreshCompleter(const QString &string) item->setData(query.value(1), Qt::UserRole); item->setIcon(IconProvider::iconFromImage(QImage::fromData(query.value(2).toByteArray()))); - m_model->appendRow(item); + appendRow(item); urlList.append(url); } @@ -113,6 +85,25 @@ void LocationCompleter::refreshCompleter(const QString &string) item->setText(url.toEncoded()); item->setData(query.value(1), Qt::UserRole); - m_model->appendRow(item); + appendRow(item); + } +} + +void LocationCompleterModel::showMostVisited() +{ + clear(); + + QSqlQuery query; + query.exec("SELECT url, title FROM history ORDER BY count DESC LIMIT 15"); + + while (query.next()) { + QStandardItem* item = new QStandardItem(); + const QUrl &url = query.value(0).toUrl(); + + item->setIcon(_iconForUrl(url)); + item->setText(url.toEncoded()); + item->setData(query.value(1), Qt::UserRole); + + appendRow(item); } } diff --git a/src/lib/navigation/locationcompleter.h b/src/lib/navigation/completer/locationcompletermodel.h similarity index 65% rename from src/lib/navigation/locationcompleter.h rename to src/lib/navigation/completer/locationcompletermodel.h index 542367128..672b7b54f 100644 --- a/src/lib/navigation/locationcompleter.h +++ b/src/lib/navigation/completer/locationcompletermodel.h @@ -15,34 +15,26 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ============================================================ */ -#ifndef LOCATIONCOMPLETER_H -#define LOCATIONCOMPLETER_H +#ifndef LOCATIONCOMPLETERMODEL_H +#define LOCATIONCOMPLETERMODEL_H -#include +#include -#include "qz_namespace.h" - -class QStandardItemModel; - -class CompleterListView; - -class QT_QUPZILLA_EXPORT LocationCompleter : public QCompleter +class LocationCompleterModel : public QStandardItemModel { - Q_OBJECT public: - explicit LocationCompleter(QObject* parent = 0); + explicit LocationCompleterModel(QObject* parent = 0); - virtual QStringList splitPath(const QString &path) const; + void refreshCompletions(const QString &string); + void showMostVisited(); signals: public slots: - void refreshCompleter(const QString &string); - void showMostVisited(); private: - CompleterListView* m_listView; - QStandardItemModel* m_model; + QString m_lastCompletion; + }; -#endif // LOCATIONCOMPLETER_H +#endif // LOCATIONCOMPLETERMODEL_H diff --git a/src/lib/navigation/completer/locationcompleterview.cpp b/src/lib/navigation/completer/locationcompleterview.cpp new file mode 100644 index 000000000..64369adc9 --- /dev/null +++ b/src/lib/navigation/completer/locationcompleterview.cpp @@ -0,0 +1,188 @@ +/* ============================================================ +* QupZilla - WebKit based browser +* Copyright (C) 2010-2012 David Rosca +* +* 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 3 of the License, or +* (at your option) any later version. +* +* 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 . +* ============================================================ */ +#include "locationcompleterview.h" + +#include +#include +#include + +LocationCompleterView::LocationCompleterView() + : QListView(0) + , m_ignoreNextMouseMove(false) +{ + setWindowFlags(Qt::Popup); + + setUniformItemSizes(true); + setEditTriggers(QAbstractItemView::NoEditTriggers); + setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setSelectionBehavior(QAbstractItemView::SelectRows); + setSelectionMode(QAbstractItemView::SingleSelection); + + setMouseTracking(true); + installEventFilter(this); +} + +QPersistentModelIndex LocationCompleterView::hoveredIndex() const +{ + return m_hoveredIndex; +} + +bool LocationCompleterView::eventFilter(QObject* object, QEvent* event) +{ + // Event filter based on QCompleter::eventFilter from qcompleter.cpp + + switch (event->type()) { + case QEvent::KeyPress: { + QKeyEvent* keyEvent = static_cast(event); + QModelIndex curIndex = m_hoveredIndex; + + if ((keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down) + && currentIndex() != curIndex) { + setCurrentIndex(curIndex); + } + + switch (keyEvent->key()) { + case Qt::Key_End: + case Qt::Key_Home: + if (keyEvent->modifiers() & Qt::ControlModifier) { + return false; + } + break; + + case Qt::Key_Left: + case Qt::Key_Right: + close(); + break; + + case Qt::Key_Escape: + close(); + return false; + + case Qt::Key_F4: + if (keyEvent->modifiers() == Qt::AltModifier) { + close(); + return false; + } + break; + + case Qt::Key_Tab: + case Qt::Key_Backtab: { + Qt::Key k = keyEvent->key() == Qt::Key_Tab ? Qt::Key_Down : Qt::Key_Up; + QKeyEvent ev(QKeyEvent::KeyPress, k, Qt::NoModifier); + QApplication::sendEvent(this, &ev); + return false; + } + + case Qt::Key_Up: + if (!curIndex.isValid()) { + int rowCount = model()->rowCount(); + QModelIndex lastIndex = model()->index(rowCount - 1, 0); + setCurrentIndex(lastIndex); + return true; + } + else if (curIndex.row() == 0) { + setCurrentIndex(QModelIndex()); + return true; + } + return false; + + case Qt::Key_Down: + if (!curIndex.isValid()) { + QModelIndex firstIndex = model()->index(0, 0); + setCurrentIndex(firstIndex); + return true; + } + else if (curIndex.row() == model()->rowCount() - 1) { + setCurrentIndex(QModelIndex()); + scrollToTop(); + return true; + } + return false; + + case Qt::Key_PageUp: + case Qt::Key_PageDown: + return false; + } // switch (keyEvent->key()) + + (static_cast(focusProxy()))->event(keyEvent); + break; + } + + case QEvent::Show: + m_ignoreNextMouseMove = true; + return false; + + case QEvent::MouseButtonPress: + if (!underMouse()) { + close(); + return true; + } + break; + + case QEvent::InputMethod: + case QEvent::ShortcutOverride: + QApplication::sendEvent(focusProxy(), event); + break; + + default: + return QListView::eventFilter(object, event); + } // switch (event->type()) + + return QListView::eventFilter(object, event); +} + +void LocationCompleterView::close() +{ + emit closed(); + m_hoveredIndex = QPersistentModelIndex(); + + QListView::hide(); +} + +void LocationCompleterView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) +{ + m_hoveredIndex = current; + + QListView::currentChanged(current, previous); + + viewport()->update(); +} + +void LocationCompleterView::mouseMoveEvent(QMouseEvent* event) +{ + if (m_ignoreNextMouseMove || !isVisible()) { + m_ignoreNextMouseMove = false; + + QListView::mouseMoveEvent(event); + return; + } + + QModelIndex last = m_hoveredIndex; + QModelIndex atCursor = indexAt(mapFromGlobal(QCursor::pos())); + + if (atCursor.isValid()) { + m_hoveredIndex = atCursor; + } + + if (last != atCursor) { + viewport()->update(); + } + + QListView::mouseMoveEvent(event); +} diff --git a/src/lib/navigation/completer/locationcompleterview.h b/src/lib/navigation/completer/locationcompleterview.h new file mode 100644 index 000000000..b6a8545fd --- /dev/null +++ b/src/lib/navigation/completer/locationcompleterview.h @@ -0,0 +1,53 @@ +/* ============================================================ +* QupZilla - WebKit based browser +* Copyright (C) 2010-2012 David Rosca +* +* 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 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* ============================================================ */ +#ifndef LOCATIONCOMPLETERVIEW_H +#define LOCATIONCOMPLETERVIEW_H + +#include + +#include "qz_namespace.h" + +class QT_QUPZILLA_EXPORT LocationCompleterView : public QListView +{ + Q_OBJECT +public: + explicit LocationCompleterView(); + + QPersistentModelIndex hoveredIndex() const; + + bool eventFilter(QObject* object, QEvent* event); + +signals: + void closed(); + +public slots: + void close(); + +private slots: + void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); + +protected: + void mouseMoveEvent(QMouseEvent* event); + +private: + bool m_ignoreNextMouseMove; + + QPersistentModelIndex m_hoveredIndex; +}; + +#endif // LOCATIONCOMPLETERVIEW_H diff --git a/src/lib/navigation/locationbar.cpp b/src/lib/navigation/locationbar.cpp index 873e35d2c..f951b2755 100644 --- a/src/lib/navigation/locationbar.cpp +++ b/src/lib/navigation/locationbar.cpp @@ -20,7 +20,6 @@ #include "tabbedwebview.h" #include "rssmanager.h" #include "mainapplication.h" -#include "locationcompleter.h" #include "clickablelabel.h" #include "siteinfowidget.h" #include "rsswidget.h" @@ -66,12 +65,11 @@ LocationBar::LocationBar(QupZilla* mainClass) setWidgetSpacing(0); - m_locationCompleter = new LocationCompleter(); - setCompleter(m_locationCompleter); + m_completer.setLocationBar(this); + connect(&m_completer, SIGNAL(showCompletion(QString)), this, SLOT(showCompletion(QString))); + connect(&m_completer, SIGNAL(completionActivated()), this, SLOT(urlEnter())); connect(this, SIGNAL(textEdited(QString)), this, SLOT(textEdit())); - connect(this, SIGNAL(textEdited(QString)), m_locationCompleter, SLOT(refreshCompleter(QString))); - connect(m_locationCompleter->popup(), SIGNAL(clicked(QModelIndex)), this, SLOT(urlEnter())); connect(m_siteIcon, SIGNAL(clicked()), this, SLOT(showSiteInfo())); connect(m_goIcon, SIGNAL(clicked(QPoint)), this, SLOT(urlEnter())); connect(m_rssIcon, SIGNAL(clicked(QPoint)), this, SLOT(rssIconClicked())); @@ -93,6 +91,12 @@ void LocationBar::updatePlaceHolderText() setPlaceholderText(tr("Enter URL address or search on %1").arg(mApp->searchEnginesManager()->activeEngine().name)); } +void LocationBar::showCompletion(const QString &newText) +{ + LineEdit::setText(newText); + end(false); +} + QUrl LocationBar::createUrl() { QUrl urlToLoad; @@ -124,7 +128,7 @@ QUrl LocationBar::createUrl() void LocationBar::urlEnter() { - m_locationCompleter->popup()->hide(); + m_completer.closePopup(); m_webView->setFocus(); emit loadUrl(createUrl()); @@ -132,6 +136,13 @@ void LocationBar::urlEnter() void LocationBar::textEdit() { + if (!text().isEmpty()) { + m_completer.complete(text()); + } + else { + m_completer.closePopup(); + } + showGoButton(); } @@ -165,15 +176,7 @@ void LocationBar::hideGoButton() void LocationBar::showMostVisited() { - if (text().isEmpty()) { - // Workaround: If we show popup when text in locationbar is empty and then - // move up and down in completer and then we leave completer -> completer will - // set text in locationbar back to last "real" completion - QKeyEvent event(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QString(" ")); - keyPressEvent(&event); - } - - m_locationCompleter->showMostVisited(); + m_completer.complete(QString()); } void LocationBar::showSiteInfo() @@ -400,6 +403,10 @@ void LocationBar::keyPressEvent(QKeyEvent* event) } break; + case Qt::Key_Down: + m_completer.complete(text()); + break; + case Qt::Key_Escape: m_webView->setFocus(); showUrl(m_webView->url()); @@ -470,5 +477,4 @@ void LocationBar::keyReleaseEvent(QKeyEvent* event) LocationBar::~LocationBar() { delete m_bookmarkIcon; - delete m_locationCompleter; } diff --git a/src/lib/navigation/locationbar.h b/src/lib/navigation/locationbar.h index 29be93be6..806a3cf17 100644 --- a/src/lib/navigation/locationbar.h +++ b/src/lib/navigation/locationbar.h @@ -22,6 +22,7 @@ #include "qz_namespace.h" #include "lineedit.h" +#include "completer/locationcompleter.h" class QupZilla; class LineEdit; @@ -52,7 +53,7 @@ signals: public slots: void showUrl(const QUrl &url); - virtual void setText(const QString &text); + void setText(const QString &text); private slots: void siteIconChanged(); @@ -67,6 +68,7 @@ private slots: void pasteAndGo(); void updatePlaceHolderText(); + void showCompletion(const QString &newText); private: void contextMenuEvent(QContextMenuEvent* event); @@ -82,6 +84,8 @@ private: void showGoButton(); void hideGoButton(); + LocationCompleter m_completer; + BookmarkIcon* m_bookmarkIcon; GoIcon* m_goIcon; RssIcon* m_rssIcon; @@ -89,7 +93,6 @@ private: QupZilla* p_QupZilla; TabbedWebView* m_webView; - LocationCompleter* m_locationCompleter; QMenu* m_menu; QAction* m_pasteAndGoAction;