|
|
|
|
@ -1,6 +1,6 @@ |
|
|
|
|
/* ============================================================
|
|
|
|
|
* Falkon - Qt web browser |
|
|
|
|
* Copyright (C) 2010-2017 David Rosca <nowrep@gmail.com> |
|
|
|
|
* Copyright (C) 2010-2018 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 |
|
|
|
|
@ -22,9 +22,10 @@ |
|
|
|
|
#include <QKeyEvent> |
|
|
|
|
#include <QApplication> |
|
|
|
|
#include <QScrollBar> |
|
|
|
|
#include <QVBoxLayout> |
|
|
|
|
|
|
|
|
|
LocationCompleterView::LocationCompleterView() |
|
|
|
|
: QListView(0) |
|
|
|
|
: QWidget(nullptr) |
|
|
|
|
, m_ignoreNextMouseMove(false) |
|
|
|
|
{ |
|
|
|
|
setAttribute(Qt::WA_ShowWithoutActivating); |
|
|
|
|
@ -36,18 +37,51 @@ LocationCompleterView::LocationCompleterView() |
|
|
|
|
setWindowFlags(Qt::Popup); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
setUniformItemSizes(true); |
|
|
|
|
setEditTriggers(QAbstractItemView::NoEditTriggers); |
|
|
|
|
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); |
|
|
|
|
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
|
|
|
|
setSelectionBehavior(QAbstractItemView::SelectRows); |
|
|
|
|
setSelectionMode(QAbstractItemView::SingleSelection); |
|
|
|
|
QVBoxLayout *layout = new QVBoxLayout(this); |
|
|
|
|
layout->setContentsMargins(0, 0, 0, 0); |
|
|
|
|
layout->setSpacing(0); |
|
|
|
|
setLayout(layout); |
|
|
|
|
|
|
|
|
|
setMouseTracking(true); |
|
|
|
|
m_view = new QListView(this); |
|
|
|
|
layout->addWidget(m_view); |
|
|
|
|
|
|
|
|
|
m_view->setUniformItemSizes(true); |
|
|
|
|
m_view->setEditTriggers(QAbstractItemView::NoEditTriggers); |
|
|
|
|
m_view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); |
|
|
|
|
m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
|
|
|
|
m_view->setSelectionBehavior(QAbstractItemView::SelectRows); |
|
|
|
|
m_view->setSelectionMode(QAbstractItemView::SingleSelection); |
|
|
|
|
|
|
|
|
|
m_view->setMouseTracking(true); |
|
|
|
|
qApp->installEventFilter(this); |
|
|
|
|
|
|
|
|
|
m_delegate = new LocationCompleterDelegate(this); |
|
|
|
|
setItemDelegate(m_delegate); |
|
|
|
|
m_view->setItemDelegate(m_delegate); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QAbstractItemModel *LocationCompleterView::model() const |
|
|
|
|
{ |
|
|
|
|
return m_view->model(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void LocationCompleterView::setModel(QAbstractItemModel *model) |
|
|
|
|
{ |
|
|
|
|
m_view->setModel(model); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QModelIndex LocationCompleterView::currentIndex() const |
|
|
|
|
{ |
|
|
|
|
return m_view->currentIndex(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void LocationCompleterView::setCurrentIndex(const QModelIndex &index) |
|
|
|
|
{ |
|
|
|
|
m_view->setCurrentIndex(index); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QItemSelectionModel *LocationCompleterView::selectionModel() const |
|
|
|
|
{ |
|
|
|
|
return m_view->selectionModel(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void LocationCompleterView::setOriginalText(const QString &originalText) |
|
|
|
|
@ -55,11 +89,47 @@ void LocationCompleterView::setOriginalText(const QString &originalText) |
|
|
|
|
m_delegate->setOriginalText(originalText); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void LocationCompleterView::adjustSize() |
|
|
|
|
{ |
|
|
|
|
const int maxItemsCount = 12; |
|
|
|
|
m_view->setFixedHeight(m_view->sizeHintForRow(0) * qMin(maxItemsCount, model()->rowCount()) + 2 * m_view->frameWidth()); |
|
|
|
|
setFixedHeight(sizeHint().height()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool LocationCompleterView::eventFilter(QObject* object, QEvent* event) |
|
|
|
|
{ |
|
|
|
|
// Event filter based on QCompleter::eventFilter from qcompleter.cpp
|
|
|
|
|
|
|
|
|
|
if (object == this || !isVisible()) { |
|
|
|
|
if (object == this || object == m_view || !isVisible()) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (object == m_view->viewport()) { |
|
|
|
|
if (event->type() == QEvent::MouseButtonRelease) { |
|
|
|
|
QMouseEvent *e = static_cast<QMouseEvent*>(event); |
|
|
|
|
QModelIndex idx = m_view->indexAt(e->pos()); |
|
|
|
|
if (!idx.isValid()) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Qt::MouseButton button = e->button(); |
|
|
|
|
Qt::KeyboardModifiers modifiers = e->modifiers(); |
|
|
|
|
|
|
|
|
|
if (button == Qt::LeftButton && modifiers == Qt::NoModifier) { |
|
|
|
|
emit indexActivated(idx); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (button == Qt::MiddleButton || (button == Qt::LeftButton && modifiers == Qt::ControlModifier)) { |
|
|
|
|
emit indexCtrlActivated(idx); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (button == Qt::LeftButton && modifiers == Qt::ShiftModifier) { |
|
|
|
|
emit indexShiftActivated(idx); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -67,11 +137,11 @@ bool LocationCompleterView::eventFilter(QObject* object, QEvent* event) |
|
|
|
|
case QEvent::KeyPress: { |
|
|
|
|
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event); |
|
|
|
|
Qt::KeyboardModifiers modifiers = keyEvent->modifiers(); |
|
|
|
|
const QModelIndex idx = currentIndex(); |
|
|
|
|
const QModelIndex idx = m_view->currentIndex(); |
|
|
|
|
const QModelIndex visitSearchIdx = model()->index(0, 0).data(LocationCompleterModel::VisitSearchItemRole).toBool() ? model()->index(0, 0) : QModelIndex(); |
|
|
|
|
|
|
|
|
|
if ((keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down) && currentIndex() != idx) { |
|
|
|
|
setCurrentIndex(idx); |
|
|
|
|
if ((keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down) && m_view->currentIndex() != idx) { |
|
|
|
|
m_view->setCurrentIndex(idx); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
switch (keyEvent->key()) { |
|
|
|
|
@ -99,7 +169,7 @@ bool LocationCompleterView::eventFilter(QObject* object, QEvent* event) |
|
|
|
|
|
|
|
|
|
case Qt::Key_End: |
|
|
|
|
if (modifiers & Qt::ControlModifier) { |
|
|
|
|
setCurrentIndex(model()->index(model()->rowCount() - 1, 0)); |
|
|
|
|
m_view->setCurrentIndex(model()->index(model()->rowCount() - 1, 0)); |
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
|
close(); |
|
|
|
|
@ -108,8 +178,8 @@ bool LocationCompleterView::eventFilter(QObject* object, QEvent* event) |
|
|
|
|
|
|
|
|
|
case Qt::Key_Home: |
|
|
|
|
if (modifiers & Qt::ControlModifier) { |
|
|
|
|
setCurrentIndex(model()->index(0, 0)); |
|
|
|
|
scrollToTop(); |
|
|
|
|
m_view->setCurrentIndex(model()->index(0, 0)); |
|
|
|
|
m_view->scrollToTop(); |
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
|
close(); |
|
|
|
|
@ -142,52 +212,46 @@ bool LocationCompleterView::eventFilter(QObject* object, QEvent* event) |
|
|
|
|
if (!idx.isValid() || idx == visitSearchIdx) { |
|
|
|
|
int rowCount = model()->rowCount(); |
|
|
|
|
QModelIndex lastIndex = model()->index(rowCount - 1, 0); |
|
|
|
|
setCurrentIndex(lastIndex); |
|
|
|
|
m_view->setCurrentIndex(lastIndex); |
|
|
|
|
} else if (idx.row() == 0) { |
|
|
|
|
setCurrentIndex(QModelIndex()); |
|
|
|
|
m_view->setCurrentIndex(QModelIndex()); |
|
|
|
|
} else { |
|
|
|
|
setCurrentIndex(model()->index(idx.row() - 1, 0)); |
|
|
|
|
m_view->setCurrentIndex(model()->index(idx.row() - 1, 0)); |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
case Qt::Key_Down: |
|
|
|
|
if (!idx.isValid()) { |
|
|
|
|
QModelIndex firstIndex = model()->index(0, 0); |
|
|
|
|
setCurrentIndex(firstIndex); |
|
|
|
|
m_view->setCurrentIndex(firstIndex); |
|
|
|
|
} else if (idx != visitSearchIdx && idx.row() == model()->rowCount() - 1) { |
|
|
|
|
setCurrentIndex(visitSearchIdx); |
|
|
|
|
scrollToTop(); |
|
|
|
|
m_view->setCurrentIndex(visitSearchIdx); |
|
|
|
|
m_view->scrollToTop(); |
|
|
|
|
} else { |
|
|
|
|
setCurrentIndex(model()->index(idx.row() + 1, 0)); |
|
|
|
|
m_view->setCurrentIndex(model()->index(idx.row() + 1, 0)); |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
case Qt::Key_Delete: |
|
|
|
|
if (idx != visitSearchIdx && viewport()->rect().contains(visualRect(idx))) { |
|
|
|
|
if (idx != visitSearchIdx && m_view->viewport()->rect().contains(m_view->visualRect(idx))) { |
|
|
|
|
emit indexDeleteRequested(idx); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case Qt::Key_PageUp: |
|
|
|
|
if (keyEvent->modifiers() != Qt::NoModifier) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
selectionModel()->setCurrentIndex(moveCursor(QAbstractItemView::MovePageUp, Qt::NoModifier), QItemSelectionModel::SelectCurrent); |
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
case Qt::Key_PageDown: |
|
|
|
|
if (keyEvent->modifiers() != Qt::NoModifier) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
selectionModel()->setCurrentIndex(moveCursor(QAbstractItemView::MovePageDown, Qt::NoModifier), QItemSelectionModel::SelectCurrent); |
|
|
|
|
QApplication::sendEvent(m_view, event); |
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
case Qt::Key_Shift: |
|
|
|
|
// don't switch if there is no hovered or selected index to not disturb typing
|
|
|
|
|
if (idx != visitSearchIdx || underMouse()) { |
|
|
|
|
m_delegate->setShowSwitchToTab(false); |
|
|
|
|
viewport()->update(); |
|
|
|
|
m_view->viewport()->update(); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
@ -205,7 +269,7 @@ bool LocationCompleterView::eventFilter(QObject* object, QEvent* event) |
|
|
|
|
switch (keyEvent->key()) { |
|
|
|
|
case Qt::Key_Shift: |
|
|
|
|
m_delegate->setShowSwitchToTab(true); |
|
|
|
|
viewport()->update(); |
|
|
|
|
m_view->viewport()->update(); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
@ -250,38 +314,10 @@ bool LocationCompleterView::eventFilter(QObject* object, QEvent* event) |
|
|
|
|
|
|
|
|
|
void LocationCompleterView::close() |
|
|
|
|
{ |
|
|
|
|
QListView::hide(); |
|
|
|
|
verticalScrollBar()->setValue(0); |
|
|
|
|
hide(); |
|
|
|
|
m_view->verticalScrollBar()->setValue(0); |
|
|
|
|
|
|
|
|
|
m_delegate->setShowSwitchToTab(true); |
|
|
|
|
|
|
|
|
|
emit closed(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void LocationCompleterView::mouseReleaseEvent(QMouseEvent* event) |
|
|
|
|
{ |
|
|
|
|
QModelIndex idx = indexAt(event->pos()); |
|
|
|
|
if (!idx.isValid()) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Qt::MouseButton button = event->button(); |
|
|
|
|
Qt::KeyboardModifiers modifiers = event->modifiers(); |
|
|
|
|
|
|
|
|
|
if (button == Qt::LeftButton && modifiers == Qt::NoModifier) { |
|
|
|
|
emit indexActivated(idx); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (button == Qt::MiddleButton || (button == Qt::LeftButton && modifiers == Qt::ControlModifier)) { |
|
|
|
|
emit indexCtrlActivated(idx); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (button == Qt::LeftButton && modifiers == Qt::ShiftModifier) { |
|
|
|
|
emit indexShiftActivated(idx); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QListView::mouseReleaseEvent(event); |
|
|
|
|
} |
|
|
|
|
|