Throttle requests using a static "typing paused period"

symbol_search
Tyler Goodlet 2021-05-11 17:26:27 -04:00
parent ef1b0911f3
commit 25d7122cb6
1 changed files with 58 additions and 32 deletions

View File

@ -19,7 +19,6 @@ qompleterz: embeddable search and complete using trio, Qt and fuzzywuzzy.
""" """
import sys import sys
import time
from typing import ( from typing import (
List, Optional, Callable, List, Optional, Callable,
Awaitable, Sequence, Dict, Awaitable, Sequence, Dict,
@ -298,50 +297,86 @@ class FontSizedQLineEdit(QtWidgets.QLineEdit):
self.view.hide() self.view.hide()
_ongoing_search: trio.CancelScope = None _search_active: trio.Event = trio.Event()
_search_enabled: bool = False _search_enabled: bool = False
async def fill_results( async def fill_results(
search: FontSizedQLineEdit, search: FontSizedQLineEdit,
symsearch: Callable[..., Awaitable], symsearch: Callable[..., Awaitable],
recv_chan: trio.abc.ReceiveChannel, recv_chan: trio.abc.ReceiveChannel,
# pattern: str, pause_time: float = 0.25,
) -> None: ) -> None:
"""Task to search through providers and fill in possible """Task to search through providers and fill in possible
completion results. completion results.
""" """
global _ongoing_search, _search_enabled global _search_active, _search_enabled
view = search.view view = search.view
sel = search.view.selectionModel() sel = search.view.selectionModel()
model = search.view.model() model = search.view.model()
async for pattern in recv_chan: last_search_text = ''
last_text = search.text()
repeats = 0
if not _search_enabled: while True:
log.debug(f'Ignoring search for {pattern}')
last_text = search.text()
await _search_active.wait()
with trio.move_on_after(pause_time) as cs:
# cs.shield = True
pattern = await recv_chan.receive()
print(pattern)
# during fast multiple key inputs, wait until a pause
# (in typing) to initiate search
if not cs.cancelled_caught:
log.debug(f'Ignoring fast input for {pattern}')
continue continue
with trio.CancelScope() as cs: text = search.text()
_ongoing_search = cs print(f'search: {text}')
results = await symsearch(pattern)
_ongoing_search = None
if results and not cs.cancelled_caught: if not text:
print('idling')
_search_active = trio.Event()
continue
if text == last_text:
repeats += 1
if repeats > 1:
_search_active = trio.Event()
repeats = 0
if not _search_enabled:
print('search not ENABLED?')
continue
if last_search_text and last_search_text == text:
continue
log.debug(f'Search req for {text}')
last_search_text = text
results = await symsearch(text)
log.debug(f'Received search result {results}')
if results and _search_enabled:
# TODO: indented branch results for each provider # TODO: indented branch results for each provider
view.set_results(results) view.set_results(results)
# [item['altname'] for item in
# results['kraken'].values()]
# )
# XXX: these 2 lines MUST be in sequence in order # XXX: these 2 lines MUST be in sequence in order
# to get the view to show right after typing input. # to get the view to show right after typing input.
sel.setCurrentIndex( sel.setCurrentIndex(
model.index(0, 0, QModelIndex()), model.index(0, 0, QModelIndex()),
QItemSelectionModel.ClearAndSelect | # type: ignore[arg-type] QItemSelectionModel.ClearAndSelect |
QItemSelectionModel.Rows QItemSelectionModel.Rows
) )
search.show() search.show()
@ -354,7 +389,7 @@ async def handle_keyboard_input(
) -> None: ) -> None:
global _ongoing_search, _search_enabled global _search_active, _search_enabled
# startup # startup
view = search.view view = search.view
@ -375,13 +410,7 @@ async def handle_keyboard_input(
recv, recv,
) )
last_time = time.time()
async for key, mods, txt in recv_chan: async for key, mods, txt in recv_chan:
# TODO: move this logic into completer task
now = time.time()
period = now - last_time
last_time = now
log.debug(f'key: {key}, mods: {mods}, txt: {txt}') log.debug(f'key: {key}, mods: {mods}, txt: {txt}')
nidx = cidx = view.currentIndex() nidx = cidx = view.currentIndex()
@ -392,10 +421,6 @@ async def handle_keyboard_input(
if key in (Qt.Key_Enter, Qt.Key_Return): if key in (Qt.Key_Enter, Qt.Key_Return):
if _ongoing_search is not None:
_ongoing_search.cancel()
_search_enabled = False
node = model.item(nidx.row(), 2) node = model.item(nidx.row(), 2)
if node: if node:
value = node.text() value = node.text()
@ -411,6 +436,7 @@ async def handle_keyboard_input(
'info', 'info',
) )
_search_enabled = False
# release kb control of search bar # release kb control of search bar
search.unfocus() search.unfocus()
continue continue
@ -422,7 +448,6 @@ async def handle_keyboard_input(
# we're in select mode or cancelling # we're in select mode or cancelling
if ctrl: if ctrl:
# cancel and close # cancel and close
if key == Qt.Key_C: if key == Qt.Key_C:
search.unfocus() search.unfocus()
@ -435,6 +460,7 @@ async def handle_keyboard_input(
# result selection nav # result selection nav
if key in (Qt.Key_K, Qt.Key_J): if key in (Qt.Key_K, Qt.Key_J):
_search_enabled = False
if key == Qt.Key_K: if key == Qt.Key_K:
nidx = view.indexAbove(cidx) nidx = view.indexAbove(cidx)
@ -456,10 +482,10 @@ async def handle_keyboard_input(
# to figure out the desired field(s) # to figure out the desired field(s)
value = model.item(nidx.row(), 2).text() value = model.item(nidx.row(), 2).text()
else: else:
if period >= 0.1: # relay to completer task
_search_enabled = True _search_enabled = True
# relay to completer task send.send_nowait(search.text())
send.send_nowait(search.text()) _search_active.set()
if __name__ == '__main__': if __name__ == '__main__':