Skip to content

Commit

Permalink
feat(ui): implement smart selection in the search box (closes #1033)
Browse files Browse the repository at this point in the history
Using focus shortcuts when the search box is already focus, will
result in the selection expansion depending on the current state.
  • Loading branch information
trollixx committed Mar 25, 2019
1 parent 0b45d6e commit 5ef5111
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 37 deletions.
84 changes: 50 additions & 34 deletions src/libs/ui/widgets/searchedit.cpp
Expand Up @@ -67,57 +67,73 @@ void SearchEdit::clearQuery()

void SearchEdit::selectQuery()
{
setSelection(queryStart(), text().size());
if (text().isEmpty())
return;

const int pos = hasSelectedText() ? selectionStart() : cursorPosition();
const int queryPos = queryStart();
const int textSize = text().size();
if (pos >= queryPos && selectionEnd() < textSize) {
setSelection(queryPos, textSize);
return;
}

selectAll();
}

bool SearchEdit::event(QEvent *event)
{
if (event->type() != QEvent::KeyPress)
return QLineEdit::event(event);
switch (event->type()) {
case QEvent::KeyPress: {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
// Tab key cannot be overriden in keyPressEvent().
if (keyEvent->key() == Qt::Key_Tab) {
const QString completed = currentCompletion(text());
if (!completed.isEmpty()) {
setText(completed);
}

return true;
} else if (keyEvent->key() == Qt::Key_Escape) {
clearQuery();
return true;
}

// Tab key cannot be overriden in keyPressEvent()
if (static_cast<QKeyEvent *>(event)->key() != Qt::Key_Tab)
return QLineEdit::event(event);
break;
}
case QEvent::ShortcutOverride: {
// TODO: Should be obtained from the ActionManager.
static const QStringList focusShortcuts = {
QStringLiteral("Ctrl+K"),
QStringLiteral("Ctrl+L")
};

QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
const int keyCode = keyEvent->key() | static_cast<int>(keyEvent->modifiers());
if (focusShortcuts.contains(QKeySequence(keyCode).toString())) {
selectQuery();
event->accept();
return true;
}

const QString completed = currentCompletion(text());
if (!completed.isEmpty())
setText(completed);
break;
}
default:
break;
}

return true;
return QLineEdit::event(event);
}

void SearchEdit::focusInEvent(QFocusEvent *event)
{
QLineEdit::focusInEvent(event);

// Do not change default behaviour when focused with mouse
// Do not change the default behaviour when focused with mouse.
if (event->reason() == Qt::MouseFocusReason)
return;

selectQuery();
m_focusing = true;
}

void SearchEdit::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Escape:
clearQuery();
event->accept();
break;
default:
QLineEdit::keyPressEvent(event);
break;
}
}

void SearchEdit::mousePressEvent(QMouseEvent *event)
{
// Let the focusInEvent code deal with initial selection on focus.
if (!m_focusing)
QLineEdit::mousePressEvent(event);

m_focusing = false;
}

void SearchEdit::showCompletions(const QString &newValue)
Expand Down
3 changes: 0 additions & 3 deletions src/libs/ui/widgets/searchedit.h
Expand Up @@ -46,8 +46,6 @@ class SearchEdit : public QLineEdit
protected:
bool event(QEvent *event) override;
void focusInEvent(QFocusEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;

private slots:
void showCompletions(const QString &text);
Expand All @@ -58,7 +56,6 @@ private slots:

QCompleter *m_prefixCompleter = nullptr;
QLabel *m_completionLabel = nullptr;
bool m_focusing = false;
};

} // namespace WidgetUi
Expand Down

0 comments on commit 5ef5111

Please sign in to comment.