1
mirror of https://invent.kde.org/network/falkon.git synced 2024-11-11 01:22:10 +01:00

[LocationCompleter] Support Ctrl / Shift activation of items

Ctrl activation: Opens url in new tab
Shift activation: Opens url in new window
Closes #1245

Bookmarks: Update visit count also from location completer
BookmarkItem: Added new method updateVisitCount
This commit is contained in:
nowrep 2014-03-01 13:02:57 +01:00
parent 8f9f187b80
commit b826ebc52a
13 changed files with 399 additions and 247 deletions

View File

@ -142,6 +142,11 @@ void BookmarkItem::setVisitCount(int count)
m_visitCount = count;
}
void BookmarkItem::updateVisitCount()
{
m_visitCount++;
}
bool BookmarkItem::isExpanded() const
{
return m_type == Root ? true : m_expanded;

View File

@ -68,6 +68,9 @@ public:
int visitCount() const;
void setVisitCount(int count);
// Increments visitCount() (may also update last load time when implemented)
void updateVisitCount();
// Expanded state in Manager
bool isExpanded() const;
void setExpanded(bool expanded);

View File

@ -227,7 +227,7 @@ void BookmarksTools::openBookmark(BrowserWindow* window, BookmarkItem* item)
openFolderInTabs(window, item);
}
else if (item->isUrl()) {
item->setVisitCount(item->visitCount() + 1);
item->updateVisitCount();
window->loadAddress(item->url());
}
}
@ -244,7 +244,7 @@ void BookmarksTools::openBookmarkInNewTab(BrowserWindow* window, BookmarkItem* i
openFolderInTabs(window, item);
}
else if (item->isUrl()) {
item->setVisitCount(item->visitCount() + 1);
item->updateVisitCount();
window->tabWidget()->addView(item->url(), item->title(), qzSettings->newTabPosition);
}
}
@ -255,7 +255,7 @@ void BookmarksTools::openBookmarkInNewWindow(BookmarkItem* item)
return;
}
item->setVisitCount(item->visitCount() + 1);
item->updateVisitCount();
mApp->makeNewWindow(Qz::BW_NewWindow, item->url());
}
@ -265,7 +265,7 @@ void BookmarksTools::openBookmarkInNewPrivateWindow(BookmarkItem* item)
return;
}
item->setVisitCount(item->visitCount() + 1);
item->updateVisitCount();
mApp->startPrivateBrowsing(item->url());
}

View File

@ -18,8 +18,14 @@
#include "locationcompleter.h"
#include "locationcompletermodel.h"
#include "locationcompleterview.h"
#include "locationcompleterdelegate.h"
#include "locationbar.h"
#include "mainapplication.h"
#include "browserwindow.h"
#include "tabbedwebview.h"
#include "tabwidget.h"
#include "history.h"
#include "bookmarks.h"
#include "bookmarkitem.h"
#include "qzsettings.h"
LocationCompleterView* LocationCompleter::s_view = 0;
@ -27,19 +33,22 @@ LocationCompleterModel* LocationCompleter::s_model = 0;
LocationCompleter::LocationCompleter(QObject* parent)
: QObject(parent)
, m_window(0)
, m_locationBar(0)
, m_ignoreCurrentChangedSignal(false)
, m_showingMostVisited(false)
{
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::setMainWindow(BrowserWindow* window)
{
m_window = window;
}
void LocationCompleter::setLocationBar(LocationBar* locationBar)
{
m_locationBar = locationBar;
@ -50,16 +59,11 @@ QString LocationCompleter::domainCompletion() const
return qzSettings->useInlineCompletion ? m_completedDomain : QString();
}
bool LocationCompleter::showingMostVisited() const
bool LocationCompleter::isShowingMostVisited() const
{
return m_showingMostVisited;
}
bool LocationCompleter::isPopupSelected() const
{
return s_view->currentIndex().isValid();
}
bool LocationCompleter::isPopupVisible() const
{
return s_view->isVisible();
@ -91,10 +95,6 @@ void LocationCompleter::showMostVisited()
void LocationCompleter::currentChanged(const QModelIndex &index)
{
if (m_ignoreCurrentChangedSignal) {
return;
}
QString completion = index.data().toString();
if (completion.isEmpty()) {
@ -106,14 +106,106 @@ void LocationCompleter::currentChanged(const QModelIndex &index)
void LocationCompleter::slotPopupClosed()
{
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(slotPopupClosed()));
disconnect(s_view, SIGNAL(aboutToActivateTab(TabPosition)), m_locationBar, SLOT(clear()));
disconnect(s_view, SIGNAL(indexActivated(QModelIndex)), this, SLOT(indexActivated(QModelIndex)));
disconnect(s_view, SIGNAL(indexCtrlActivated(QModelIndex)), this, SLOT(indexCtrlActivated(QModelIndex)));
disconnect(s_view, SIGNAL(indexShiftActivated(QModelIndex)), this, SLOT(indexShiftActivated(QModelIndex)));
disconnect(s_view, SIGNAL(indexDeleteRequested(QModelIndex)), this, SLOT(indexDeleteRequested(QModelIndex)));
disconnect(s_view->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(currentChanged(QModelIndex)));
emit popupClosed();
}
void LocationCompleter::indexActivated(const QModelIndex &index)
{
Q_ASSERT(index.isValid());
const QUrl url = index.data(LocationCompleterModel::UrlRole).toUrl();
const int tabPos = index.data(LocationCompleterModel::TabPositionTabRole).toInt();
// Switch to tab with simple index activation
if (tabPos > -1) {
BrowserWindow* window = static_cast<BrowserWindow*>(index.data(LocationCompleterModel::TabPositionWindowRole).value<void*>());
Q_ASSERT(window);
switchToTab(window, tabPos);
return;
}
if (index.data(LocationCompleterModel::BookmarkRole).toBool()) {
BookmarkItem* bookmark = static_cast<BookmarkItem*>(index.data(LocationCompleterModel::BookmarkItemRole).value<void*>());
bookmark->updateVisitCount();
}
loadUrl(url);
}
void LocationCompleter::indexCtrlActivated(const QModelIndex &index)
{
Q_ASSERT(index.isValid());
Q_ASSERT(m_window);
if (index.data(LocationCompleterModel::BookmarkRole).toBool()) {
BookmarkItem* bookmark = static_cast<BookmarkItem*>(index.data(LocationCompleterModel::BookmarkItemRole).value<void*>());
bookmark->updateVisitCount();
}
const QUrl url = index.data(LocationCompleterModel::UrlRole).toUrl();
const QString title = index.data(LocationCompleterModel::TitleRole).toString();
closePopup();
// Clear locationbar
emit clearCompletion();
// Open url in new tab
m_window->tabWidget()->addView(url, title, Qz::NT_CleanSelectedTab);
}
void LocationCompleter::indexShiftActivated(const QModelIndex &index)
{
Q_ASSERT(index.isValid());
if (index.data(LocationCompleterModel::BookmarkRole).toBool()) {
BookmarkItem* bookmark = static_cast<BookmarkItem*>(index.data(LocationCompleterModel::BookmarkItemRole).value<void*>());
bookmark->updateVisitCount();
}
const QUrl url = index.data(LocationCompleterModel::UrlRole).toUrl();
const int tabPos = index.data(LocationCompleterModel::TabPositionTabRole).toInt();
// Load url (instead of switching to tab) with shift activation
if (tabPos > -1) {
loadUrl(url);
return;
}
closePopup();
// Clear locationbar
emit clearCompletion();
// Open new window
mApp->makeNewWindow(Qz::BW_NewWindow, url);
}
void LocationCompleter::indexDeleteRequested(const QModelIndex &index)
{
if (!index.isValid()) {
return;
}
if (index.data(LocationCompleterModel::BookmarkRole).toBool()) {
BookmarkItem* bookmark = static_cast<BookmarkItem*>(index.data(LocationCompleterModel::BookmarkItemRole).value<void*>());
mApp->bookmarks()->removeBookmark(bookmark);
}
else {
int id = index.data(LocationCompleterModel::IdRole).toInt();
mApp->history()->deleteHistoryEntry(id);
}
s_model->removeRow(index.row(), index.parent());
}
QString LocationCompleter::createDomainCompletionString(const QString &text)
{
QString completion = s_model->completeDomain(text);
@ -129,6 +221,40 @@ QString LocationCompleter::createDomainCompletionString(const QString &text)
return completion.mid(text.size());
}
void LocationCompleter::switchToTab(BrowserWindow* window, int tab)
{
Q_ASSERT(window);
Q_ASSERT(tab >= 0);
closePopup();
// Clear locationbar
emit clearCompletion();
TabWidget* tabWidget = window->tabWidget();
if (window->isActiveWindow() || tabWidget->currentIndex() != tab) {
tabWidget->setCurrentIndex(tab);
window->show();
window->activateWindow();
window->raise();
}
else {
window->weView()->setFocus();
}
}
void LocationCompleter::loadUrl(const QUrl &url)
{
closePopup();
// Show url in locationbar
emit showCompletion(url.toEncoded());
// Load url
emit loadCompletion();
}
void LocationCompleter::showPopup()
{
Q_ASSERT(m_locationBar);
@ -146,13 +272,16 @@ void LocationCompleter::showPopup()
QRect popupRect(m_locationBar->mapToGlobal(m_locationBar->pos()), m_locationBar->size());
popupRect.setY(popupRect.bottom());
s_view->setFocusProxy(m_locationBar);
s_view->setGeometry(popupRect);
s_view->setFocusProxy(m_locationBar);
s_view->setCurrentIndex(QModelIndex());
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(slotPopupClosed()));
connect(s_view, SIGNAL(aboutToActivateTab(TabPosition)), m_locationBar, SLOT(clear()));
connect(s_view, SIGNAL(indexActivated(QModelIndex)), this, SLOT(indexActivated(QModelIndex)));
connect(s_view, SIGNAL(indexCtrlActivated(QModelIndex)), this, SLOT(indexCtrlActivated(QModelIndex)));
connect(s_view, SIGNAL(indexShiftActivated(QModelIndex)), this, SLOT(indexShiftActivated(QModelIndex)));
connect(s_view, SIGNAL(indexDeleteRequested(QModelIndex)), this, SLOT(indexDeleteRequested(QModelIndex)));
connect(s_view->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(currentChanged(QModelIndex)));
adjustPopupSize();
}
@ -160,14 +289,9 @@ void LocationCompleter::showPopup()
void LocationCompleter::adjustPopupSize()
{
const int maxItemsCount = 6;
int popupHeight = s_view->sizeHintForRow(0) * qMin(maxItemsCount, s_model->rowCount());
popupHeight += 2 * s_view->frameWidth();
const int popupHeight = s_view->sizeHintForRow(0) * qMin(maxItemsCount, s_model->rowCount()) + 2 * s_view->frameWidth();
s_view->resize(s_view->width(), popupHeight);
m_ignoreCurrentChangedSignal = true;
s_view->setCurrentIndex(QModelIndex());
m_ignoreCurrentChangedSignal = false;
s_view->show();
m_originalText = m_locationBar->text();

View File

@ -22,11 +22,13 @@
#include "qzcommon.h"
class QUrl;
class QModelIndex;
class LocationBar;
class BrowserWindow;
class LocationCompleterModel;
class LocationCompleterView;
class LocationBar;
class QUPZILLA_EXPORT LocationCompleter : public QObject
{
@ -34,17 +36,20 @@ class QUPZILLA_EXPORT LocationCompleter : public QObject
public:
explicit LocationCompleter(QObject* parent = 0);
void setMainWindow(BrowserWindow* window);
void setLocationBar(LocationBar* locationBar);
QString domainCompletion() const;
bool showingMostVisited() const;
bool isPopupSelected() const;
bool isShowingMostVisited() const;
bool isPopupVisible() const;
void closePopup();
signals:
void showCompletion(const QString &);
void completionActivated();
void showCompletion(const QString &completion);
void loadCompletion();
void clearCompletion();
void popupClosed();
public slots:
@ -55,16 +60,23 @@ private slots:
void currentChanged(const QModelIndex &index);
void slotPopupClosed();
void indexActivated(const QModelIndex &index);
void indexCtrlActivated(const QModelIndex &index);
void indexShiftActivated(const QModelIndex &index);
void indexDeleteRequested(const QModelIndex &index);
private:
QString createDomainCompletionString(const QString &text);
void switchToTab(BrowserWindow* window, int tab);
void loadUrl(const QUrl &url);
void showPopup();
void adjustPopupSize();
BrowserWindow* m_window;
LocationBar* m_locationBar;
QString m_originalText;
QString m_completedDomain;
bool m_ignoreCurrentChangedSignal;
bool m_showingMostVisited;
static LocationCompleterView* s_view;

View File

@ -19,6 +19,7 @@
#include "locationcompleterview.h"
#include "locationcompletermodel.h"
#include "iconprovider.h"
#include "qzsettings.h"
#include <QPainter>
#include <QApplication>
@ -86,7 +87,6 @@ void LocationCompleterDelegate::paint(QPainter* painter, const QStyleOptionViewI
if (index.data(LocationCompleterModel::BookmarkRole).toBool()) {
const QPixmap starPixmap = qIconProvider->bookmarkIcon();
QSize starSize = starPixmap.size();
//new
starPixmapWidth = starSize.width();
QPoint pos(rightPosition - starPixmapWidth, opt.rect.top() + m_padding);
QRect starRect(pos, starSize);
@ -109,9 +109,11 @@ void LocationCompleterDelegate::paint(QPainter* painter, const QStyleOptionViewI
const int infoYPos = titleRect.bottom() + opt.fontMetrics.leading() + 2;
QRect linkRect(titleRect.x(), infoYPos, titleRect.width(), opt.fontMetrics.height());
const QByteArray linkArray = index.data(Qt::DisplayRole).toByteArray();
// Let's assume that more than 500 characters won't fit in line on any display...
// Fixes performance when trying to get elidedText for a really long
// (length() > 1000000) urls - data: urls can get that long
QString link;
if (!linkArray.startsWith("data") && !linkArray.startsWith("javascript")) {
link = QString::fromUtf8(QByteArray::fromPercentEncoding(linkArray)).left(500);
@ -122,8 +124,11 @@ void LocationCompleterDelegate::paint(QPainter* painter, const QStyleOptionViewI
link = opt.fontMetrics.elidedText(link, Qt::ElideRight, linkRect.width());
painter->setFont(opt.font);
TabPosition pos = index.data(LocationCompleterModel::TabPositionRole).value<TabPosition>();
if (m_drawSwitchToTab && pos.windowIndex != -1) {
// Draw url (or switch to tab)
int tabPos = index.data(LocationCompleterModel::TabPositionTabRole).toInt();
if (drawSwitchToTab() && tabPos != -1) {
const QIcon tabIcon = QIcon(":icons/menu/tab.png");
QRect iconRect(linkRect);
iconRect.setWidth(m_padding + 16 + m_padding);
@ -144,6 +149,53 @@ void LocationCompleterDelegate::paint(QPainter* painter, const QStyleOptionViewI
}
}
QSize LocationCompleterDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index)
if (!m_rowHeight) {
QStyleOptionViewItemV4 opt(option);
initStyleOption(&opt, index);
const QWidget* w = opt.widget;
const QStyle* style = w ? w->style() : QApplication::style();
const int padding = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0) + 1;
QFont titleFont = opt.font;
titleFont.setPointSize(titleFont.pointSize() + 1);
m_padding = padding > 3 ? padding : 3;
const QFontMetrics titleMetrics(titleFont);
// 2 px bigger space between title and link because of underlining
m_rowHeight = 2 * m_padding + opt.fontMetrics.leading() + opt.fontMetrics.height() + titleMetrics.height() + 2;
}
return QSize(200, m_rowHeight);
}
void LocationCompleterDelegate::setShowSwitchToTab(bool enable)
{
m_drawSwitchToTab = enable;
}
bool LocationCompleterDelegate::drawSwitchToTab() const
{
return qzSettings->showSwitchTab && m_drawSwitchToTab;
}
QRect LocationCompleterDelegate::adjustRect(const QRect &original, const QRect &created) const
{
if (created.left() + created.width() >= original.right()) {
QRect nRect = created;
nRect.setWidth(original.right() - created.left());
return nRect;
}
return created;
}
static bool sizeBiggerThan(const QString &s1, const QString &s2)
{
return s1.size() > s2.size();
@ -280,47 +332,3 @@ void LocationCompleterDelegate::drawTextLine(const QRect &rect, QString text, QP
style->drawItemText(painter, rect, Qt::TextSingleLine | alignment, option.palette, true, text, role);
}
}
QRect LocationCompleterDelegate::adjustRect(const QRect &original, const QRect &created) const
{
if (created.left() + created.width() >= original.right()) {
QRect nRect = created;
nRect.setWidth(original.right() - created.left());
return nRect;
}
return created;
}
QSize LocationCompleterDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index)
if (!m_rowHeight) {
QStyleOptionViewItemV4 opt(option);
initStyleOption(&opt, index);
const QWidget* w = opt.widget;
const QStyle* style = w ? w->style() : QApplication::style();
const int padding = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0) + 1;
QFont titleFont = opt.font;
titleFont.setPointSize(titleFont.pointSize() + 1);
m_padding = padding > 3 ? padding : 3;
const QFontMetrics titleMetrics(titleFont);
// 2 px bigger space between title and link because of underlining
m_rowHeight = 2 * m_padding + opt.fontMetrics.leading() + opt.fontMetrics.height() + titleMetrics.height() + 2;
}
return QSize(200, m_rowHeight);
}
void LocationCompleterDelegate::drawSwitchToTab(bool enable)
{
m_drawSwitchToTab = enable;
}

View File

@ -32,9 +32,12 @@ public:
void paint(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawSwitchToTab(bool enable);
void setShowSwitchToTab(bool enable);
private:
bool drawSwitchToTab() const;
QRect adjustRect(const QRect &original, const QRect &created) const;
void drawHighlightedTextLine(const QRect &rect, const QString &text, const QString &searchText,
QPainter* painter, const QStyle* style, const QStyleOptionViewItemV4 &option,
const QPalette::ColorRole &role) const;
@ -43,8 +46,6 @@ private:
const QStyle* style, const QStyleOptionViewItemV4 &option,
const QPalette::ColorRole &role) const;
inline QRect adjustRect(const QRect &original, const QRect &created) const;
mutable int m_rowHeight;
mutable int m_padding;
bool m_drawSwitchToTab;

View File

@ -77,13 +77,12 @@ void LocationCompleterModel::refreshCompletions(const QString &string)
item->setText(bookmark->url().toEncoded());
item->setData(-1, IdRole);
item->setData(bookmark->title(), TitleRole);
item->setData(bookmark->url(), UrlRole);
item->setData(bookmark->visitCount(), CountRole);
item->setData(QVariant(true), BookmarkRole);
item->setData(QVariant::fromValue<void*>(static_cast<void*>(bookmark)), BookmarkItemRole);
item->setData(string, SearchStringRole);
if (qzSettings->showSwitchTab) {
item->setData(QVariant::fromValue<TabPosition>(tabPositionForUrl(bookmark->url())), TabPositionRole);
}
setTabPosition(item);
urlList.append(bookmark->url());
itemList.append(item);
@ -107,12 +106,11 @@ void LocationCompleterModel::refreshCompletions(const QString &string)
item->setText(url.toEncoded());
item->setData(query.value(0), IdRole);
item->setData(query.value(2), TitleRole);
item->setData(url, UrlRole);
item->setData(query.value(3), CountRole);
item->setData(QVariant(false), BookmarkRole);
item->setData(string, SearchStringRole);
if (qzSettings->showSwitchTab) {
item->setData(QVariant::fromValue<TabPosition>(tabPositionForUrl(url)), TabPositionRole);
}
setTabPosition(item);
itemList.append(item);
}
@ -139,10 +137,9 @@ void LocationCompleterModel::showMostVisited()
item->setText(url.toEncoded());
item->setData(query.value(0), IdRole);
item->setData(query.value(2), TitleRole);
item->setData(url, UrlRole);
item->setData(QVariant(false), BookmarkRole);
if (qzSettings->showSwitchTab) {
item->setData(QVariant::fromValue<TabPosition>(tabPositionForUrl(url)), TabPositionRole);
}
setTabPosition(item);
appendRow(item);
}
@ -191,7 +188,7 @@ QString LocationCompleterModel::completeDomain(const QString &text)
return sqlQuery.value(0).toUrl().host();
}
QSqlQuery LocationCompleterModel::createQuery(const QString &searchString, int limit, bool exactMatch)
QSqlQuery LocationCompleterModel::createQuery(const QString &searchString, int limit, bool exactMatch) const
{
QStringList searchList;
QString query = QLatin1String("SELECT id, url, title, count FROM history WHERE ");
@ -231,42 +228,40 @@ QSqlQuery LocationCompleterModel::createQuery(const QString &searchString, int l
return sqlQuery;
}
TabPosition LocationCompleterModel::tabPositionForUrl(const QUrl &url) const
void LocationCompleterModel::setTabPosition(QStandardItem* item) const
{
return tabPositionForEncodedUrl(url.toEncoded());
}
Q_ASSERT(item);
TabPosition LocationCompleterModel::tabPositionForEncodedUrl(const QString &encodedUrl) const
{
QList<BrowserWindow*> windows = mApp->mainWindows();
int currentWindowIdx = windows.indexOf(mApp->getWindow());
windows.prepend(mApp->getWindow());
for (int win = 0; win < windows.count(); ++win) {
BrowserWindow* mainWin = windows.at(win);
QList<WebTab*> tabs = mainWin->tabWidget()->allTabs();
for (int tab = 0; tab < tabs.count(); ++tab) {
if (tabs[tab]->url().toEncoded() == encodedUrl) {
TabPosition pos;
pos.windowIndex = win == 0 ? currentWindowIdx : win - 1;
pos.tabIndex = tab;
return pos;
}
}
}
return TabPosition();
}
void LocationCompleterModel::refreshTabPositions()
{
if (!qzSettings->showSwitchTab) {
return;
}
for (int row = 0; row < rowCount(); ++row) {
QStandardItem* aItem = item(row);
if (!aItem) {
continue;
const QUrl url = item->data(UrlRole).toUrl();
const QList<BrowserWindow*> windows = mApp->mainWindows();
foreach (BrowserWindow* window, windows) {
QList<WebTab*> tabs = window->tabWidget()->allTabs();
for (int i = 0; i < tabs.count(); ++i) {
WebTab* tab = tabs.at(i);
if (tab->url() == url) {
item->setData(QVariant::fromValue<void*>(static_cast<void*>(window)), TabPositionWindowRole);
item->setData(i, TabPositionTabRole);
return;
}
}
}
// Tab wasn't found
item->setData(QVariant::fromValue<void*>(static_cast<void*>(0)), TabPositionWindowRole);
item->setData(-1, TabPositionTabRole);
}
void LocationCompleterModel::refreshTabPositions() const
{
for (int row = 0; row < rowCount(); ++row) {
QStandardItem* itm = item(row);
if (itm) {
setTabPosition(itm);
}
aItem->setData(QVariant::fromValue<TabPosition>(tabPositionForEncodedUrl(aItem->text())), TabPositionRole);
}
}

View File

@ -25,27 +25,21 @@
class QSqlQuery;
class QUrl;
struct TabPosition {
int windowIndex;
int tabIndex;
TabPosition()
: windowIndex(-1)
, tabIndex(-1)
{}
};
Q_DECLARE_METATYPE(TabPosition)
class LocationCompleterModel : public QStandardItemModel
{
public:
enum Role {
TitleRole = Qt::UserRole + 1,
BookmarkRole = Qt::UserRole + 2,
IdRole = Qt::UserRole + 3,
SearchStringRole = Qt::UserRole + 4,
CountRole = Qt::UserRole + 5,
TabPositionRole = Qt::UserRole + 6
IdRole = Qt::UserRole + 1,
TitleRole = Qt::UserRole + 2,
UrlRole = Qt::UserRole + 3,
CountRole = Qt::UserRole + 4,
BookmarkRole = Qt::UserRole + 5,
BookmarkItemRole = Qt::UserRole + 6,
SearchStringRole = Qt::UserRole + 7,
TabPositionWindowRole = Qt::UserRole + 8,
TabPositionTabRole = Qt::UserRole + 9
};
explicit LocationCompleterModel(QObject* parent = 0);
void refreshCompletions(const QString &string);
@ -61,12 +55,10 @@ private:
Nothing = 4
};
QSqlQuery createQuery(const QString &searchString,
int limit, bool exactMatch = false);
QSqlQuery createQuery(const QString &searchString, int limit, bool exactMatch = false) const;
TabPosition tabPositionForUrl(const QUrl &url) const;
TabPosition tabPositionForEncodedUrl(const QString &encodedUrl) const;
void refreshTabPositions();
void setTabPosition(QStandardItem* item) const;
void refreshTabPositions() const;
QString m_lastCompletion;
};

View File

@ -18,12 +18,6 @@
#include "locationcompleterview.h"
#include "locationcompletermodel.h"
#include "locationcompleterdelegate.h"
#include "mainapplication.h"
#include "browserwindow.h"
#include "history.h"
#include "tabwidget.h"
#include "qzsettings.h"
#include "tabbedwebview.h"
#include <QKeyEvent>
#include <QApplication>
@ -33,6 +27,7 @@
LocationCompleterView::LocationCompleterView()
: QListView(0)
, m_ignoreNextMouseMove(false)
, m_buttons(Qt::NoButton)
{
setWindowFlags(Qt::Popup);
@ -45,6 +40,9 @@ LocationCompleterView::LocationCompleterView()
setMouseTracking(true);
installEventFilter(this);
m_delegate = new LocationCompleterDelegate(this);
setItemDelegate(m_delegate);
}
QPersistentModelIndex LocationCompleterView::hoveredIndex() const
@ -60,31 +58,39 @@ bool LocationCompleterView::eventFilter(QObject* object, QEvent* event)
switch (event->type()) {
case QEvent::KeyPress: {
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
QModelIndex curIndex = m_hoveredIndex;
Qt::KeyboardModifiers modifiers = keyEvent->modifiers();
QModelIndex idx = m_hoveredIndex;
if ((keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down)
&& currentIndex() != curIndex) {
setCurrentIndex(curIndex);
if ((keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down) && currentIndex() != idx) {
setCurrentIndex(idx);
}
switch (keyEvent->key()) {
case Qt::Key_Return:
case Qt::Key_Enter:
if (qzSettings->showSwitchTab && !(keyEvent->modifiers() & Qt::ShiftModifier)) {
QModelIndex idx = selectionModel()->currentIndex();
if (idx.isValid()) {
TabPosition pos = idx.data(LocationCompleterModel::TabPositionRole).value<TabPosition>();
if (pos.windowIndex != -1) {
activateTab(pos);
return true;
}
}
if (!idx.isValid()) {
break;
}
if (modifiers == Qt::NoModifier) {
emit indexActivated(idx);
return true;
}
if (modifiers == Qt::ControlModifier) {
emit indexCtrlActivated(idx);
return true;
}
if (modifiers == Qt::ShiftModifier) {
emit indexShiftActivated(idx);
return true;
}
break;
case Qt::Key_End:
case Qt::Key_Home:
if (keyEvent->modifiers() & Qt::ControlModifier) {
if (modifiers & Qt::ControlModifier) {
return false;
}
break;
@ -94,7 +100,7 @@ bool LocationCompleterView::eventFilter(QObject* object, QEvent* event)
return false;
case Qt::Key_F4:
if (keyEvent->modifiers() == Qt::AltModifier) {
if (modifiers == Qt::AltModifier) {
close();
return false;
}
@ -109,25 +115,25 @@ bool LocationCompleterView::eventFilter(QObject* object, QEvent* event)
}
case Qt::Key_Up:
if (!curIndex.isValid()) {
if (!idx.isValid()) {
int rowCount = model()->rowCount();
QModelIndex lastIndex = model()->index(rowCount - 1, 0);
setCurrentIndex(lastIndex);
return true;
}
else if (curIndex.row() == 0) {
else if (idx.row() == 0) {
setCurrentIndex(QModelIndex());
return true;
}
return false;
case Qt::Key_Down:
if (!curIndex.isValid()) {
if (!idx.isValid()) {
QModelIndex firstIndex = model()->index(0, 0);
setCurrentIndex(firstIndex);
return true;
}
else if (curIndex.row() == model()->rowCount() - 1) {
else if (idx.row() == model()->rowCount() - 1) {
setCurrentIndex(QModelIndex());
scrollToTop();
return true;
@ -135,12 +141,8 @@ bool LocationCompleterView::eventFilter(QObject* object, QEvent* event)
return false;
case Qt::Key_Delete:
if (viewport()->rect().contains(visualRect(curIndex)) &&
!curIndex.data(LocationCompleterModel::BookmarkRole).toBool()) {
int id = curIndex.data(LocationCompleterModel::IdRole).toInt();
model()->removeRow(curIndex.row(), curIndex.parent());
mApp->history()->deleteHistoryEntry(id);
if (viewport()->rect().contains(visualRect(idx))) {
emit indexDeleteRequested(idx);
return true;
}
break;
@ -151,8 +153,8 @@ bool LocationCompleterView::eventFilter(QObject* object, QEvent* event)
case Qt::Key_Shift:
// don't switch if there is no hovered or selected index to not disturb typing
if (qzSettings->showSwitchTab && (selectionModel()->currentIndex().isValid() || m_hoveredIndex.isValid())) {
static_cast<LocationCompleterDelegate*>(itemDelegate())->drawSwitchToTab(false);
if (idx.isValid() || m_hoveredIndex.isValid()) {
m_delegate->setShowSwitchToTab(false);
viewport()->update();
return true;
}
@ -168,17 +170,15 @@ bool LocationCompleterView::eventFilter(QObject* object, QEvent* event)
switch (keyEvent->key()) {
case Qt::Key_Shift:
if (qzSettings->showSwitchTab) {
static_cast<LocationCompleterDelegate*>(itemDelegate())->drawSwitchToTab(true);
viewport()->update();
return true;
}
m_delegate->setShowSwitchToTab(true);
viewport()->update();
return true;
}
break;
}
case QEvent::Show:
// Don't hover item when showing completer and mouse is currently in rect
m_ignoreNextMouseMove = true;
break;
@ -203,14 +203,13 @@ bool LocationCompleterView::eventFilter(QObject* object, QEvent* event)
void LocationCompleterView::close()
{
emit closed();
m_hoveredIndex = QPersistentModelIndex();
QListView::hide();
verticalScrollBar()->setValue(0);
if (qzSettings->showSwitchTab) {
static_cast<LocationCompleterDelegate*>(itemDelegate())->drawSwitchToTab(true);
}
m_hoveredIndex = QPersistentModelIndex();
m_delegate->setShowSwitchToTab(true);
emit closed();
}
void LocationCompleterView::currentChanged(const QModelIndex &current, const QModelIndex &previous)
@ -226,7 +225,6 @@ void LocationCompleterView::mouseMoveEvent(QMouseEvent* event)
{
if (m_ignoreNextMouseMove || !isVisible()) {
m_ignoreNextMouseMove = false;
QListView::mouseMoveEvent(event);
return;
}
@ -245,36 +243,33 @@ void LocationCompleterView::mouseMoveEvent(QMouseEvent* event)
QListView::mouseMoveEvent(event);
}
void LocationCompleterView::mouseReleaseEvent(QMouseEvent* event)
void LocationCompleterView::mousePressEvent(QMouseEvent* event)
{
if (qzSettings->showSwitchTab && !(event->modifiers() & Qt::ShiftModifier) && m_hoveredIndex.isValid()) {
TabPosition pos = m_hoveredIndex.data(LocationCompleterModel::TabPositionRole).value<TabPosition>();
if (pos.windowIndex != -1) {
event->accept();
activateTab(pos);
}
else {
QListView::mouseReleaseEvent(event);
}
}
else {
QListView::mouseReleaseEvent(event);
}
m_buttons = event->buttons();
QListView::mousePressEvent(event);
}
void LocationCompleterView::activateTab(TabPosition pos)
void LocationCompleterView::mouseReleaseEvent(QMouseEvent* event)
{
BrowserWindow* win = mApp->mainWindows().at(pos.windowIndex);
if (mApp->getWindow() != win || mApp->getWindow()->tabWidget()->currentIndex() != pos.tabIndex) {
emit aboutToActivateTab(pos);
close();
win->tabWidget()->setCurrentIndex(pos.tabIndex);
win->show();
win->activateWindow();
win->raise();
}
else {
close();
win->weView()->setFocus();
if (m_hoveredIndex.isValid()) {
Qt::KeyboardModifiers modifiers = event->modifiers();
if (m_buttons == Qt::LeftButton && modifiers == Qt::NoModifier) {
emit indexActivated(m_hoveredIndex);
return;
}
if (m_buttons == Qt::MiddleButton || (m_buttons == Qt::LeftButton && modifiers == Qt::ControlModifier)) {
emit indexCtrlActivated(m_hoveredIndex);
return;
}
if (m_buttons == Qt::LeftButton && modifiers == Qt::ShiftModifier) {
emit indexShiftActivated(m_hoveredIndex);
return;
}
}
QListView::mouseReleaseEvent(event);
}

View File

@ -21,7 +21,8 @@
#include <QListView>
#include "qzcommon.h"
#include "locationcompletermodel.h"
class LocationCompleterDelegate;
class QUPZILLA_EXPORT LocationCompleterView : public QListView
{
@ -35,23 +36,29 @@ public:
signals:
void closed();
void aboutToActivateTab(TabPosition pos);
void indexActivated(const QModelIndex &index);
void indexCtrlActivated(const QModelIndex &index);
void indexShiftActivated(const QModelIndex &index);
void indexDeleteRequested(const QModelIndex &index);
public slots:
void close();
private slots:
void currentChanged(const QModelIndex &current, const QModelIndex &previous);
void activateTab(TabPosition pos);
protected:
void mouseMoveEvent(QMouseEvent* event);
void mousePressEvent(QMouseEvent* event);
void mouseReleaseEvent(QMouseEvent* event);
private:
bool m_ignoreNextMouseMove;
LocationCompleterDelegate* m_delegate;
QPersistentModelIndex m_hoveredIndex;
Qt::MouseButtons m_buttons;
};
#endif // LOCATIONCOMPLETERVIEW_H

View File

@ -37,6 +37,7 @@
#include "qzsettings.h"
#include "colors.h"
#include "autofillicon.h"
#include "completer/locationcompleter.h"
#include <QMimeData>
#include <QClipboard>
@ -82,14 +83,17 @@ LocationBar::LocationBar(BrowserWindow* window)
addWidget(m_goIcon, LineEdit::RightSide);
addWidget(down, LineEdit::RightSide);
m_completer.setLocationBar(this);
connect(&m_completer, SIGNAL(showCompletion(QString)), this, SLOT(showCompletion(QString)));
connect(&m_completer, SIGNAL(completionActivated()), this, SLOT(urlEnter()));
connect(&m_completer, SIGNAL(popupClosed()), this, SLOT(completionPopupClosed()));
m_completer = new LocationCompleter(this);
m_completer->setMainWindow(m_window);
m_completer->setLocationBar(this);
connect(m_completer, SIGNAL(showCompletion(QString)), this, SLOT(showCompletion(QString)));
connect(m_completer, SIGNAL(loadCompletion()), this, SLOT(urlEnter()));
connect(m_completer, SIGNAL(clearCompletion()), this, SLOT(clearCompletion()));
connect(m_completer, SIGNAL(popupClosed()), this, SLOT(completionPopupClosed()));
connect(this, SIGNAL(textEdited(QString)), this, SLOT(textEdit()));
connect(m_goIcon, SIGNAL(clicked(QPoint)), this, SLOT(urlEnter()));
connect(down, SIGNAL(clicked(QPoint)), &m_completer, SLOT(showMostVisited()));
connect(down, SIGNAL(clicked(QPoint)), m_completer, SLOT(showMostVisited()));
connect(mApp->searchEnginesManager(), SIGNAL(activeEngineChanged()), this, SLOT(updatePlaceHolderText()));
connect(mApp->searchEnginesManager(), SIGNAL(defaultEngineChanged()), this, SLOT(updatePlaceHolderText()));
connect(mApp, SIGNAL(message(Qz::AppMessageType,bool)), SLOT(onMessage(Qz::AppMessageType,bool)));
@ -143,6 +147,12 @@ void LocationBar::showCompletion(const QString &newText)
end(false);
}
void LocationBar::clearCompletion()
{
m_webView->setFocus();
showUrl(m_webView->url());
}
void LocationBar::completionPopupClosed()
{
m_inlineCompletionVisible = false;
@ -166,7 +176,7 @@ QUrl LocationBar::createUrl()
}
if (isInlineCompletionVisible()) {
urlToLoad = WebView::guessUrlFromString(text() + m_completer.domainCompletion());
urlToLoad = WebView::guessUrlFromString(text() + m_completer->domainCompletion());
}
if (urlToLoad.isEmpty()) {
@ -200,7 +210,7 @@ QString LocationBar::convertUrlToText(const QUrl &url) const
bool LocationBar::isInlineCompletionVisible() const
{
return m_inlineCompletionVisible && !m_completer.domainCompletion().isEmpty();
return m_inlineCompletionVisible && !m_completer->domainCompletion().isEmpty();
}
void LocationBar::urlEnter()
@ -208,7 +218,7 @@ void LocationBar::urlEnter()
const QUrl url = createUrl();
const QString urlString = convertUrlToText(url);
m_completer.closePopup();
m_completer->closePopup();
m_webView->setFocus();
if (urlString != text()) {
@ -221,11 +231,11 @@ void LocationBar::urlEnter()
void LocationBar::textEdit()
{
if (!text().isEmpty()) {
m_completer.complete(text());
m_completer->complete(text());
m_inlineCompletionVisible = true;
}
else {
m_completer.closePopup();
m_completer->closePopup();
}
showGoButton();
@ -459,29 +469,29 @@ void LocationBar::keyPressEvent(QKeyEvent* event)
break;
case Qt::Key_Down:
m_completer.complete(text());
m_completer->complete(text());
break;
case Qt::Key_End:
case Qt::Key_Right: {
const QString completionText = m_completer.domainCompletion();
const QString completionText = m_completer->domainCompletion();
if (m_inlineCompletionVisible && !completionText.isEmpty()) {
m_inlineCompletionVisible = false;
setText(text() + completionText);
setCursorPosition(text().size());
m_completer.closePopup();
m_completer->closePopup();
}
if (m_completer.isPopupVisible()) {
m_completer.closePopup();
if (m_completer->isPopupVisible()) {
m_completer->closePopup();
}
break;
}
case Qt::Key_Left:
if (m_completer.isPopupVisible()) {
m_completer.closePopup();
if (m_completer->isPopupVisible()) {
m_completer->closePopup();
}
break;
@ -514,7 +524,7 @@ void LocationBar::keyPressEvent(QKeyEvent* event)
break;
case Qt::AltModifier:
m_completer.closePopup();
m_completer->closePopup();
m_window->tabWidget()->addView(createUrl());
m_holdingAlt = false;
break;
@ -647,7 +657,7 @@ void LocationBar::paintEvent(QPaintEvent* event)
if (hasFocus() && m_inlineCompletionVisible) {
// Draw inline domain completion if available
const QString completionText = m_completer.domainCompletion();
const QString completionText = m_completer->domainCompletion();
if (!completionText.isEmpty()) {
QRect completionRect = textRect;
@ -665,7 +675,7 @@ void LocationBar::paintEvent(QPaintEvent* event)
}
}
if (m_completer.isPopupVisible() && !m_completer.showingMostVisited()) {
if (m_completer->isPopupVisible() && !m_completer->isShowingMostVisited()) {
// We need to draw cursor when popup is visible
// But don't paint it if we are just showing most visited sites
const int cursorWidth = style()->pixelMetric(QStyle::PM_TextCursorWidth, &option, this);

View File

@ -22,7 +22,6 @@
#include "qzcommon.h"
#include "lineedit.h"
#include "completer/locationcompleter.h"
class BrowserWindow;
class LineEdit;
@ -71,6 +70,7 @@ private slots:
void updatePlaceHolderText();
void showCompletion(const QString &newText);
void clearCompletion();
void completionPopupClosed();
void onLoadStarted();
@ -103,7 +103,7 @@ private:
void loadSettings();
LocationCompleter m_completer;
LocationCompleter* m_completer;
BookmarksIcon* m_bookmarkIcon;
GoIcon* m_goIcon;