UI/Qt: Preview non-prefix autocomplete suggestions
Allow highlighted rows that are not valid inline completions to preview their full suggestion text in the location editor. This covers history entries matched by title or URL substring, while ordinary typing stays on the inline-only path. Keep automatic inline autocomplete text when Escape closes the popup. Escape still cancels hovered or keyboard-selected preview text.
This commit is contained in:
parent
3fcd9d83a1
commit
2f0fe26ce9
2 changed files with 99 additions and 25 deletions
|
|
@ -256,12 +256,20 @@ LocationEdit::LocationEdit(QWidget* parent)
|
|||
if (!hasFocus())
|
||||
return;
|
||||
|
||||
auto query = current_query();
|
||||
auto query = autocomplete_query();
|
||||
int selected_row = -1;
|
||||
if (!m_autocomplete_query_without_inline.isNull() && text() == m_autocomplete_query_without_inline)
|
||||
if (!m_autocomplete_preview_query.isNull()) {
|
||||
for (size_t i = 0; i < suggestions.size(); ++i) {
|
||||
if (qstring_from_ak_string(suggestions[i].text) == text()) {
|
||||
selected_row = static_cast<int>(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (!m_autocomplete_query_without_inline.isNull() && text() == m_autocomplete_query_without_inline) {
|
||||
selected_row = 0;
|
||||
else
|
||||
} else {
|
||||
selected_row = apply_inline_autocomplete(suggestions);
|
||||
}
|
||||
|
||||
// Do not update the popup while results are still changing.
|
||||
// Intermediate updates are triggered on every keystroke and would
|
||||
|
|
@ -286,22 +294,29 @@ LocationEdit::LocationEdit(QWidget* parent)
|
|||
};
|
||||
|
||||
connect(m_autocomplete, &Autocomplete::suggestion_activated, this, [this](QString const& text) {
|
||||
m_is_applying_inline_autocomplete = true;
|
||||
setText(text);
|
||||
m_is_applying_inline_autocomplete = false;
|
||||
m_autocomplete_preview_query = QString();
|
||||
m_current_inline_autocomplete_suggestion.clear();
|
||||
set_text_without_inline_autocomplete(text);
|
||||
m_autocomplete->close();
|
||||
emit returnPressed();
|
||||
});
|
||||
|
||||
connect(m_autocomplete, &Autocomplete::suggestion_highlighted, this, [this](QString const& text) {
|
||||
auto query = current_query();
|
||||
apply_inline_autocomplete_suggestion_text(text, query);
|
||||
m_has_highlighted_autocomplete_suggestion = true;
|
||||
auto query = autocomplete_query();
|
||||
apply_inline_autocomplete_suggestion_text(text, query, true);
|
||||
});
|
||||
|
||||
connect(m_autocomplete, &Autocomplete::did_close, this, [this] {
|
||||
auto should_preserve_inline_autocomplete = m_should_preserve_inline_autocomplete_on_close;
|
||||
auto should_restore_query = should_restore_autocomplete_query();
|
||||
m_should_preserve_inline_autocomplete_on_close = false;
|
||||
m_has_highlighted_autocomplete_suggestion = false;
|
||||
m_current_inline_autocomplete_suggestion.clear();
|
||||
if (should_preserve_inline_autocomplete)
|
||||
return;
|
||||
if (!m_autocomplete_query_without_inline.isNull()) {
|
||||
if (hasSelectedText())
|
||||
if (should_restore_query)
|
||||
restore_query();
|
||||
m_autocomplete_query_without_inline = QString();
|
||||
return;
|
||||
|
|
@ -330,6 +345,8 @@ LocationEdit::LocationEdit(QWidget* parent)
|
|||
return;
|
||||
|
||||
m_autocomplete_query_without_inline = QString();
|
||||
m_autocomplete_preview_query = QString();
|
||||
m_has_highlighted_autocomplete_suggestion = false;
|
||||
|
||||
if (m_url_is_hidden)
|
||||
m_has_user_edited_hidden_url = true;
|
||||
|
|
@ -460,12 +477,10 @@ void LocationEdit::focusOutEvent(QFocusEvent* event)
|
|||
|
||||
animate_focus_glow(0);
|
||||
|
||||
if (hasSelectedText()) {
|
||||
if (should_restore_autocomplete_query()) {
|
||||
auto query = current_query();
|
||||
m_is_applying_inline_autocomplete = true;
|
||||
setText(query);
|
||||
set_text_without_inline_autocomplete(query);
|
||||
setCursorPosition(query.length());
|
||||
m_is_applying_inline_autocomplete = false;
|
||||
}
|
||||
|
||||
auto should_cancel_pending_query = !m_should_skip_autocomplete_cancel_on_focus_out;
|
||||
|
|
@ -512,8 +527,17 @@ void LocationEdit::animate_focus_glow(int target_alpha)
|
|||
void LocationEdit::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if (event->key() == Qt::Key_Escape) {
|
||||
if (m_autocomplete->close())
|
||||
if (m_autocomplete->is_visible()
|
||||
&& m_autocomplete_query_without_inline.isNull()
|
||||
&& m_autocomplete_preview_query.isNull()
|
||||
&& !m_has_highlighted_autocomplete_suggestion
|
||||
&& hasSelectedText()) {
|
||||
m_should_preserve_inline_autocomplete_on_close = true;
|
||||
}
|
||||
if (m_autocomplete->close()) {
|
||||
m_autocomplete->cancel_pending_query();
|
||||
return;
|
||||
}
|
||||
reset_autocomplete_state();
|
||||
if (m_url.has_value())
|
||||
setText(serialized_url());
|
||||
|
|
@ -532,7 +556,7 @@ void LocationEdit::keyPressEvent(QKeyEvent* event)
|
|||
}
|
||||
|
||||
if ((event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) && m_autocomplete->is_visible()) {
|
||||
auto query = current_query();
|
||||
auto query = autocomplete_query();
|
||||
if (m_autocomplete_popup_query == query) {
|
||||
activate_selected_autocomplete_suggestion();
|
||||
event->accept();
|
||||
|
|
@ -952,6 +976,9 @@ QString LocationEdit::display_url() const
|
|||
|
||||
QString LocationEdit::current_query() const
|
||||
{
|
||||
if (!m_autocomplete_preview_query.isNull())
|
||||
return m_autocomplete_preview_query;
|
||||
|
||||
if (!hasSelectedText())
|
||||
return text();
|
||||
int start = selectionStart();
|
||||
|
|
@ -1070,7 +1097,7 @@ int LocationEdit::apply_inline_autocomplete(Vector<WebView::AutocompleteSuggesti
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool LocationEdit::apply_inline_autocomplete_suggestion_text(QString const& suggestion_text, QString const& query)
|
||||
bool LocationEdit::apply_inline_autocomplete_suggestion_text(QString const& suggestion_text, QString const& query, bool allow_preview)
|
||||
{
|
||||
if (suggestion_matches_query_exactly(query, suggestion_text)) {
|
||||
restore_query();
|
||||
|
|
@ -1079,6 +1106,10 @@ bool LocationEdit::apply_inline_autocomplete_suggestion_text(QString const& sugg
|
|||
}
|
||||
|
||||
auto inline_text = inline_autocomplete_text_for_suggestion(query, suggestion_text);
|
||||
if (inline_text.isEmpty() && allow_preview) {
|
||||
apply_autocomplete_preview_text(suggestion_text, query);
|
||||
return true;
|
||||
}
|
||||
if (inline_text.isEmpty())
|
||||
return false;
|
||||
|
||||
|
|
@ -1102,18 +1133,33 @@ void LocationEdit::apply_inline_autocomplete_text(QString const& inline_text, QS
|
|||
&& selectedText().length() == completion_length)
|
||||
return;
|
||||
|
||||
m_is_applying_inline_autocomplete = true;
|
||||
setText(inline_text);
|
||||
m_autocomplete_preview_query = QString();
|
||||
set_text_without_inline_autocomplete(inline_text);
|
||||
setSelection(completion_start, completion_length);
|
||||
m_is_applying_inline_autocomplete = false;
|
||||
}
|
||||
|
||||
void LocationEdit::apply_autocomplete_preview_text(QString const& suggestion_text, QString const& query)
|
||||
{
|
||||
if (!hasFocus())
|
||||
return;
|
||||
|
||||
if (text() == suggestion_text && hasSelectedText()
|
||||
&& selectionStart() == 0
|
||||
&& selectedText().length() == suggestion_text.length())
|
||||
return;
|
||||
|
||||
m_current_inline_autocomplete_suggestion.clear();
|
||||
m_autocomplete_preview_query = query;
|
||||
set_text_without_inline_autocomplete(suggestion_text);
|
||||
selectAll();
|
||||
}
|
||||
|
||||
void LocationEdit::activate_selected_autocomplete_suggestion()
|
||||
{
|
||||
if (auto selected = m_autocomplete->selected_suggestion(); selected.has_value()) {
|
||||
m_is_applying_inline_autocomplete = true;
|
||||
setText(qstring_from_ak_string(*selected));
|
||||
m_is_applying_inline_autocomplete = false;
|
||||
m_autocomplete_preview_query = QString();
|
||||
m_current_inline_autocomplete_suggestion.clear();
|
||||
set_text_without_inline_autocomplete(qstring_from_ak_string(*selected));
|
||||
}
|
||||
m_autocomplete->close();
|
||||
emit returnPressed();
|
||||
|
|
@ -1128,17 +1174,38 @@ void LocationEdit::restore_query()
|
|||
if (text() == query && !hasSelectedText())
|
||||
return;
|
||||
|
||||
m_is_applying_inline_autocomplete = true;
|
||||
setText(query);
|
||||
set_text_without_inline_autocomplete(query);
|
||||
setCursorPosition(query.length());
|
||||
m_autocomplete_preview_query = QString();
|
||||
}
|
||||
|
||||
void LocationEdit::set_text_without_inline_autocomplete(QString const& text)
|
||||
{
|
||||
m_is_applying_inline_autocomplete = true;
|
||||
setText(text);
|
||||
m_is_applying_inline_autocomplete = false;
|
||||
}
|
||||
|
||||
bool LocationEdit::should_restore_autocomplete_query() const
|
||||
{
|
||||
return !m_autocomplete_preview_query.isNull() || !m_current_inline_autocomplete_suggestion.isEmpty();
|
||||
}
|
||||
|
||||
QString LocationEdit::autocomplete_query() const
|
||||
{
|
||||
if (!m_autocomplete_query_without_inline.isNull())
|
||||
return m_autocomplete_query_without_inline;
|
||||
return current_query();
|
||||
}
|
||||
|
||||
void LocationEdit::reset_autocomplete_state()
|
||||
{
|
||||
m_autocomplete_popup_query = QString();
|
||||
m_autocomplete_query_without_inline = QString();
|
||||
m_autocomplete_preview_query = QString();
|
||||
m_current_inline_autocomplete_suggestion.clear();
|
||||
m_has_highlighted_autocomplete_suggestion = false;
|
||||
m_should_preserve_inline_autocomplete_on_close = false;
|
||||
m_should_skip_autocomplete_cancel_on_focus_out = false;
|
||||
m_pending_autocomplete_activation_query = QString();
|
||||
m_suppressed_inline_autocomplete_query = QString();
|
||||
|
|
|
|||
|
|
@ -73,10 +73,14 @@ private:
|
|||
QString display_url() const;
|
||||
|
||||
int apply_inline_autocomplete(Vector<WebView::AutocompleteSuggestion> const&);
|
||||
bool apply_inline_autocomplete_suggestion_text(QString const& suggestion_text, QString const& query);
|
||||
bool apply_inline_autocomplete_suggestion_text(QString const& suggestion_text, QString const& query, bool allow_preview = false);
|
||||
void apply_inline_autocomplete_text(QString const& inline_text, QString const& query);
|
||||
void apply_autocomplete_preview_text(QString const& suggestion_text, QString const& query);
|
||||
void activate_selected_autocomplete_suggestion();
|
||||
void restore_query();
|
||||
void set_text_without_inline_autocomplete(QString const& text);
|
||||
bool should_restore_autocomplete_query() const;
|
||||
QString autocomplete_query() const;
|
||||
QString current_query() const;
|
||||
void reset_autocomplete_state();
|
||||
|
||||
|
|
@ -99,9 +103,12 @@ private:
|
|||
|
||||
bool m_is_applying_inline_autocomplete { false };
|
||||
bool m_should_suppress_inline_autocomplete_on_next_change { false };
|
||||
bool m_has_highlighted_autocomplete_suggestion { false };
|
||||
bool m_should_preserve_inline_autocomplete_on_close { false };
|
||||
bool m_should_skip_autocomplete_cancel_on_focus_out { false };
|
||||
QString m_autocomplete_popup_query;
|
||||
QString m_autocomplete_query_without_inline;
|
||||
QString m_autocomplete_preview_query;
|
||||
QString m_current_inline_autocomplete_suggestion;
|
||||
QString m_pending_autocomplete_activation_query;
|
||||
QString m_suppressed_inline_autocomplete_query;
|
||||
|
|
|
|||
Loading…
Reference in a new issue