1
mirror of https://invent.kde.org/network/falkon.git synced 2024-12-20 18:56:34 +01:00

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
This commit is contained in:
nowrep 2012-04-22 17:09:43 +02:00
parent 98d51b0661
commit 64bdafde87
11 changed files with 519 additions and 186 deletions

View File

@ -50,7 +50,6 @@ SOURCES += \
history/historymodel.cpp \ history/historymodel.cpp \
history/historymanager.cpp \ history/historymanager.cpp \
navigation/websearchbar.cpp \ navigation/websearchbar.cpp \
navigation/locationcompleter.cpp \
navigation/locationbar.cpp \ navigation/locationbar.cpp \
network/networkmanagerproxy.cpp \ network/networkmanagerproxy.cpp \
network/networkmanager.cpp \ network/networkmanager.cpp \
@ -170,7 +169,10 @@ SOURCES += \
tools/plaineditwithlines.cpp \ tools/plaineditwithlines.cpp \
webview/websettings.cpp \ webview/websettings.cpp \
tools/focusselectlineedit.cpp \ tools/focusselectlineedit.cpp \
navigation/locationcompleterdelegate.cpp navigation/completer/locationcompleterdelegate.cpp \
navigation/completer/locationcompleter.cpp \
navigation/completer/locationcompletermodel.cpp \
navigation/completer/locationcompleterview.cpp
HEADERS += \ HEADERS += \
webview/tabpreview.h \ webview/tabpreview.h \
@ -189,7 +191,6 @@ HEADERS += \
history/historymodel.h \ history/historymodel.h \
history/historymanager.h \ history/historymanager.h \
navigation/websearchbar.h \ navigation/websearchbar.h \
navigation/locationcompleter.h \
navigation/locationbar.h \ navigation/locationbar.h \
network/networkmanagerproxy.h \ network/networkmanagerproxy.h \
network/networkmanager.h \ network/networkmanager.h \
@ -313,7 +314,10 @@ HEADERS += \
sidebar/sidebarinterface.h \ sidebar/sidebarinterface.h \
webview/websettings.h \ webview/websettings.h \
tools/focusselectlineedit.h \ tools/focusselectlineedit.h \
navigation/locationcompleterdelegate.h navigation/completer/locationcompleterdelegate.h \
navigation/completer/locationcompleter.h \
navigation/completer/locationcompletermodel.h \
navigation/completer/locationcompleterview.h
FORMS += \ FORMS += \
preferences/autofillmanager.ui \ preferences/autofillmanager.ui \

View File

@ -0,0 +1,120 @@
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2010-2012 David Rosca <nowrep@gmail.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 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 <http://www.gnu.org/licenses/>.
* ============================================================ */
#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();
}

View File

@ -0,0 +1,63 @@
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2010-2012 David Rosca <nowrep@gmail.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 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 <http://www.gnu.org/licenses/>.
* ============================================================ */
#ifndef LOCATIONCOMPLETER_H
#define LOCATIONCOMPLETER_H
#include <QObject>
#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

View File

@ -16,78 +16,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */ * ============================================================ */
#include "locationcompleterdelegate.h" #include "locationcompleterdelegate.h"
#include "locationcompleterview.h"
#include <QPainter> #include <QPainter>
#include <QApplication> #include <QApplication>
#include <QMouseEvent> #include <QMouseEvent>
#include <QDebug> LocationCompleterDelegate::LocationCompleterDelegate(LocationCompleterView* parent)
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 &current, 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)
: QStyledItemDelegate(parent) : QStyledItemDelegate(parent)
, m_rowHeight(0) , m_rowHeight(0)
, m_padding(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 leftPosition = m_padding * 2;
int rightPosition = opt.rect.right() - m_padding; int rightPosition = opt.rect.right() - m_padding;
if (m_listView->ignoreSelectedFlag()) { // if (m_view->ignoreSelectedFlag()) {
if (opt.state.testFlag(QStyle::State_MouseOver)) { // if (opt.state.testFlag(QStyle::State_MouseOver)) {
if (m_view->hoveredIndex() == index) {
opt.state |= QStyle::State_Selected; opt.state |= QStyle::State_Selected;
} }
else { else {
opt.state &= ~QStyle::State_Selected; opt.state &= ~QStyle::State_Selected;
} }
} // }
const QPalette::ColorRole colorRole = opt.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text; 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; 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); const QFontMetrics titleMetrics(titleFont);
m_rowHeight = 2 * m_padding + opt.fontMetrics.leading() + opt.fontMetrics.height() + titleMetrics.height(); 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); return QSize(200, m_rowHeight);
} }

View File

@ -19,38 +19,15 @@
#define LOCATIONCOMPLETERDELEGATE_H #define LOCATIONCOMPLETERDELEGATE_H
#include <QStyledItemDelegate> #include <QStyledItemDelegate>
#include <QListView>
#include "qz_namespace.h" #include "qz_namespace.h"
class QT_QUPZILLA_EXPORT CompleterListView : public QListView class LocationCompleterView;
{
Q_OBJECT
public:
explicit CompleterListView(QWidget* parent = 0);
bool ignoreSelectedFlag() const;
int rowHeight() const;
void setRowHeight(int height);
private slots:
void currentChanged(const QModelIndex &current, const QModelIndex &previous);
protected:
void mouseMoveEvent(QMouseEvent* event);
void keyPressEvent(QKeyEvent* event);
private:
bool m_selectedItemByMousePosition;
int m_rowHeight;
QModelIndex m_lastMouseIndex;
};
class QT_QUPZILLA_EXPORT LocationCompleterDelegate : public QStyledItemDelegate class QT_QUPZILLA_EXPORT LocationCompleterDelegate : public QStyledItemDelegate
{ {
public: public:
explicit LocationCompleterDelegate(CompleterListView* parent = 0); explicit LocationCompleterDelegate(LocationCompleterView* parent = 0);
void paint(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; void paint(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
QSize sizeHint(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_rowHeight;
mutable int m_padding; mutable int m_padding;
CompleterListView* m_listView; LocationCompleterView* m_view;
}; };
#endif // LOCATIONCOMPLETERDELEGATE_H #endif // LOCATIONCOMPLETERDELEGATE_H

View File

@ -15,65 +15,37 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */ * ============================================================ */
#include "locationcompleter.h" #include "locationcompletermodel.h"
#include "locationcompleterdelegate.h"
#include "locationbar.h"
#include "iconprovider.h" #include "iconprovider.h"
#include "mainapplication.h" #include "mainapplication.h"
#include <QStandardItemModel>
#include <QSqlQuery> #include <QSqlQuery>
LocationCompleter::LocationCompleter(QObject* parent) LocationCompleterModel::LocationCompleterModel(QObject* parent)
: QCompleter(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); if (m_lastCompletion == string) {
return QStringList(); return;
} }
void LocationCompleter::showMostVisited() m_lastCompletion = string;
{
m_model->clear();
QSqlQuery query; if (string.isEmpty()) {
query.exec("SELECT url, title FROM history ORDER BY count DESC LIMIT 15"); showMostVisited();
return;
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);
} }
QCompleter::complete(); clear();
}
void LocationCompleter::refreshCompleter(const QString &string)
{
int limit = string.size() < 3 ? 25 : 15; int limit = string.size() < 3 ? 25 : 15;
QString searchString = QString("%%1%").arg(string); QString searchString = QString("%%1%").arg(string);
QList<QUrl> urlList; QList<QUrl> urlList;
m_model->clear();
QSqlQuery query; QSqlQuery query;
query.prepare("SELECT url, title, icon FROM bookmarks WHERE title LIKE ? OR url LIKE ? LIMIT ?"); query.prepare("SELECT url, title, icon FROM bookmarks WHERE title LIKE ? OR url LIKE ? LIMIT ?");
query.addBindValue(searchString); query.addBindValue(searchString);
@ -89,7 +61,7 @@ void LocationCompleter::refreshCompleter(const QString &string)
item->setData(query.value(1), Qt::UserRole); item->setData(query.value(1), Qt::UserRole);
item->setIcon(IconProvider::iconFromImage(QImage::fromData(query.value(2).toByteArray()))); item->setIcon(IconProvider::iconFromImage(QImage::fromData(query.value(2).toByteArray())));
m_model->appendRow(item); appendRow(item);
urlList.append(url); urlList.append(url);
} }
@ -113,6 +85,25 @@ void LocationCompleter::refreshCompleter(const QString &string)
item->setText(url.toEncoded()); item->setText(url.toEncoded());
item->setData(query.value(1), Qt::UserRole); 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);
} }
} }

View File

@ -15,34 +15,26 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */ * ============================================================ */
#ifndef LOCATIONCOMPLETER_H #ifndef LOCATIONCOMPLETERMODEL_H
#define LOCATIONCOMPLETER_H #define LOCATIONCOMPLETERMODEL_H
#include <QCompleter> #include <QStandardItemModel>
#include "qz_namespace.h" class LocationCompleterModel : public QStandardItemModel
class QStandardItemModel;
class CompleterListView;
class QT_QUPZILLA_EXPORT LocationCompleter : public QCompleter
{ {
Q_OBJECT
public: 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: signals:
public slots: public slots:
void refreshCompleter(const QString &string);
void showMostVisited();
private: private:
CompleterListView* m_listView; QString m_lastCompletion;
QStandardItemModel* m_model;
}; };
#endif // LOCATIONCOMPLETER_H #endif // LOCATIONCOMPLETERMODEL_H

View File

@ -0,0 +1,188 @@
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2010-2012 David Rosca <nowrep@gmail.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 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 <http://www.gnu.org/licenses/>.
* ============================================================ */
#include "locationcompleterview.h"
#include <QKeyEvent>
#include <QApplication>
#include <QStyle>
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<QKeyEvent*>(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<QObject*>(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 &current, 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);
}

View File

@ -0,0 +1,53 @@
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2010-2012 David Rosca <nowrep@gmail.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 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 <http://www.gnu.org/licenses/>.
* ============================================================ */
#ifndef LOCATIONCOMPLETERVIEW_H
#define LOCATIONCOMPLETERVIEW_H
#include <QListView>
#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 &current, const QModelIndex &previous);
protected:
void mouseMoveEvent(QMouseEvent* event);
private:
bool m_ignoreNextMouseMove;
QPersistentModelIndex m_hoveredIndex;
};
#endif // LOCATIONCOMPLETERVIEW_H

View File

@ -20,7 +20,6 @@
#include "tabbedwebview.h" #include "tabbedwebview.h"
#include "rssmanager.h" #include "rssmanager.h"
#include "mainapplication.h" #include "mainapplication.h"
#include "locationcompleter.h"
#include "clickablelabel.h" #include "clickablelabel.h"
#include "siteinfowidget.h" #include "siteinfowidget.h"
#include "rsswidget.h" #include "rsswidget.h"
@ -66,12 +65,11 @@ LocationBar::LocationBar(QupZilla* mainClass)
setWidgetSpacing(0); setWidgetSpacing(0);
m_locationCompleter = new LocationCompleter(); m_completer.setLocationBar(this);
setCompleter(m_locationCompleter); 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)), 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_siteIcon, SIGNAL(clicked()), this, SLOT(showSiteInfo()));
connect(m_goIcon, SIGNAL(clicked(QPoint)), this, SLOT(urlEnter())); connect(m_goIcon, SIGNAL(clicked(QPoint)), this, SLOT(urlEnter()));
connect(m_rssIcon, SIGNAL(clicked(QPoint)), this, SLOT(rssIconClicked())); 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)); 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 LocationBar::createUrl()
{ {
QUrl urlToLoad; QUrl urlToLoad;
@ -124,7 +128,7 @@ QUrl LocationBar::createUrl()
void LocationBar::urlEnter() void LocationBar::urlEnter()
{ {
m_locationCompleter->popup()->hide(); m_completer.closePopup();
m_webView->setFocus(); m_webView->setFocus();
emit loadUrl(createUrl()); emit loadUrl(createUrl());
@ -132,6 +136,13 @@ void LocationBar::urlEnter()
void LocationBar::textEdit() void LocationBar::textEdit()
{ {
if (!text().isEmpty()) {
m_completer.complete(text());
}
else {
m_completer.closePopup();
}
showGoButton(); showGoButton();
} }
@ -165,15 +176,7 @@ void LocationBar::hideGoButton()
void LocationBar::showMostVisited() void LocationBar::showMostVisited()
{ {
if (text().isEmpty()) { m_completer.complete(QString());
// 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();
} }
void LocationBar::showSiteInfo() void LocationBar::showSiteInfo()
@ -400,6 +403,10 @@ void LocationBar::keyPressEvent(QKeyEvent* event)
} }
break; break;
case Qt::Key_Down:
m_completer.complete(text());
break;
case Qt::Key_Escape: case Qt::Key_Escape:
m_webView->setFocus(); m_webView->setFocus();
showUrl(m_webView->url()); showUrl(m_webView->url());
@ -470,5 +477,4 @@ void LocationBar::keyReleaseEvent(QKeyEvent* event)
LocationBar::~LocationBar() LocationBar::~LocationBar()
{ {
delete m_bookmarkIcon; delete m_bookmarkIcon;
delete m_locationCompleter;
} }

View File

@ -22,6 +22,7 @@
#include "qz_namespace.h" #include "qz_namespace.h"
#include "lineedit.h" #include "lineedit.h"
#include "completer/locationcompleter.h"
class QupZilla; class QupZilla;
class LineEdit; class LineEdit;
@ -52,7 +53,7 @@ signals:
public slots: public slots:
void showUrl(const QUrl &url); void showUrl(const QUrl &url);
virtual void setText(const QString &text); void setText(const QString &text);
private slots: private slots:
void siteIconChanged(); void siteIconChanged();
@ -67,6 +68,7 @@ private slots:
void pasteAndGo(); void pasteAndGo();
void updatePlaceHolderText(); void updatePlaceHolderText();
void showCompletion(const QString &newText);
private: private:
void contextMenuEvent(QContextMenuEvent* event); void contextMenuEvent(QContextMenuEvent* event);
@ -82,6 +84,8 @@ private:
void showGoButton(); void showGoButton();
void hideGoButton(); void hideGoButton();
LocationCompleter m_completer;
BookmarkIcon* m_bookmarkIcon; BookmarkIcon* m_bookmarkIcon;
GoIcon* m_goIcon; GoIcon* m_goIcon;
RssIcon* m_rssIcon; RssIcon* m_rssIcon;
@ -89,7 +93,6 @@ private:
QupZilla* p_QupZilla; QupZilla* p_QupZilla;
TabbedWebView* m_webView; TabbedWebView* m_webView;
LocationCompleter* m_locationCompleter;
QMenu* m_menu; QMenu* m_menu;
QAction* m_pasteAndGoAction; QAction* m_pasteAndGoAction;