mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-05 01:23:24 -08:00
[Completer] Highlight popup rows without rewriting the line edit (#7502)
* [Completer] Highlight popup rows without rewriting the line edit Selecting a popup row with ClearAndSelect emits selectionChanged, which QCompleter turns into highlighted() and QLineEdit turns into setText(). Sincebe2c16eca5(#7466) that rewrites the typed text on every completion reset / arrow-key press (e.g. typing "A" becomes "Axe" and cannot be edited), regressing the514014dc00(#7447) fix that used NoUpdate. Add selectWithoutRewrite(), which blocks the selection-model signals while applying ClearAndSelect so the highlight stays visible without touching the line edit, then syncs the preview manually. Route both the above-popup auto-select and Up/Down navigation through it, and handle Up/Down for below-popups too instead of falling through to Qt's rewriting default. Enter/click acceptance via activated() is unchanged. * [Completer] Repaint popup highlight after silent selection change Blocking the selection model's signals also suppresses the view's own selectionChanged/currentChanged repaints, so force a viewport update after restoring signals. Use EnsureVisible to match Qt's normal scroll behaviour. --------- Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
parent
456d9d9e70
commit
bbe438b09a
2 changed files with 48 additions and 14 deletions
|
|
@ -133,29 +133,33 @@ bool CardCompleterStyler::handlePopupKeyPress(QKeyEvent *event)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!above) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto *popup = completer->popup();
|
||||
const int rowCount = completer->completionModel()->rowCount();
|
||||
if (rowCount == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle navigation ourselves so arrow keys move the highlight without
|
||||
// rewriting the line edit. QCompleter's default handling selects with a
|
||||
// selection change that QLineEdit turns into setText(), which fights the
|
||||
// user while typing (e.g. typing "A" becomes "Axe" and cannot be edited).
|
||||
// With the popup above the text edit the rows are shown in reverse order and
|
||||
// the closest match is in the bottom-most row. The up arrow then advances
|
||||
// through the list (towards its end at the top of the popup).
|
||||
const int currentRow = popup->currentIndex().row();
|
||||
const int step = (key == Qt::Key_Up) ? -1 : 1;
|
||||
const int newRow = qBound(0, currentRow + step, rowCount - 1);
|
||||
|
||||
if (newRow != currentRow) {
|
||||
const QModelIndex newIndex = completer->completionModel()->index(newRow, completer->completionColumn());
|
||||
popup->selectionModel()->setCurrentIndex(newIndex,
|
||||
QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
||||
const QModelIndex current = popup->currentIndex();
|
||||
int newRow;
|
||||
if (!current.isValid()) {
|
||||
newRow = (key == Qt::Key_Down) ? 0 : rowCount - 1;
|
||||
} else {
|
||||
const int step = (key == Qt::Key_Up) ? -1 : 1;
|
||||
newRow = qBound(0, current.row() + step, rowCount - 1);
|
||||
if (newRow == current.row()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
selectWithoutRewrite(completer->completionModel()->index(newRow, completer->completionColumn()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -218,8 +222,37 @@ void CardCompleterStyler::ensureClosestSelected()
|
|||
const int closestRow = rowCount - 1;
|
||||
|
||||
if (currentRow != closestRow) {
|
||||
popup->selectionModel()->setCurrentIndex(completionModel->index(closestRow, completer->completionColumn()),
|
||||
QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
||||
selectWithoutRewrite(completionModel->index(closestRow, completer->completionColumn()));
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void CardCompleterStyler::selectWithoutRewrite(const QModelIndex &index)
|
||||
{
|
||||
auto *popup = completer->popup();
|
||||
auto *selectionModel = popup->selectionModel();
|
||||
|
||||
// Changing the popup selection emits selectionChanged, which QCompleter
|
||||
// turns into highlighted() and QLineEdit turns into setText(). That
|
||||
// rewrites what the user typed (e.g. "A" becomes "Axe") and fights further
|
||||
// typing. Block the signals so the highlight and preview move without
|
||||
// touching the line edit; Enter/click still activates via activated().
|
||||
const bool wasBlocked = selectionModel->blockSignals(true);
|
||||
if (!index.isValid()) {
|
||||
selectionModel->clear();
|
||||
} else {
|
||||
selectionModel->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
||||
}
|
||||
selectionModel->blockSignals(wasBlocked);
|
||||
popup->viewport()->update();
|
||||
|
||||
// currentRowChanged was suppressed above, so sync the preview manually.
|
||||
updatePreview(index);
|
||||
if (index.isValid()) {
|
||||
popup->scrollTo(index, QAbstractItemView::EnsureVisible);
|
||||
} else {
|
||||
popup->scrollToTop();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ private:
|
|||
void applyPopupWidth();
|
||||
void updateOrientation();
|
||||
void ensureClosestSelected();
|
||||
void selectWithoutRewrite(const QModelIndex &index);
|
||||
|
||||
bool handlePopupKeyPress(QKeyEvent *event);
|
||||
bool isPopupAboveWidget() const;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue