Prefetch modes: Off / Adjacent (4 cardinals) / Full page (spiral)

- Off: no prefetching
- Adjacent: simultaneous left/right/up/down (4 posts)
- Full page: ring expansion in all 8 directions
Dropdown in Settings > General replaces the old checkbox.
This commit is contained in:
pax 2026-04-05 19:55:21 -05:00
parent 81b609f55e
commit 0aa5d139d3
2 changed files with 39 additions and 27 deletions

View File

@ -845,7 +845,7 @@ class BooruApp(QMainWindow):
self._grid.setFocus() self._grid.setFocus()
# Start prefetching from top of page # Start prefetching from top of page
if self._db.get_setting_bool("prefetch_adjacent") and posts: if self._db.get_setting("prefetch_mode") in ("Adjacent", "Full page") and posts:
self._prefetch_adjacent(0) self._prefetch_adjacent(0)
# Infinite scroll: if first page doesn't fill viewport, load more # Infinite scroll: if first page doesn't fill viewport, load more
@ -912,7 +912,7 @@ class BooruApp(QMainWindow):
# All done — unlock loading, evict, prefetch # All done — unlock loading, evict, prefetch
self._loading = False self._loading = False
self._auto_evict_cache() self._auto_evict_cache()
if self._db.get_setting_bool("prefetch_adjacent"): if self._db.get_setting("prefetch_mode") in ("Adjacent", "Full page"):
self._prefetch_adjacent(idx) self._prefetch_adjacent(idx)
# Check if still at bottom or content doesn't fill viewport # Check if still at bottom or content doesn't fill viewport
sb = self._grid.verticalScrollBar() sb = self._grid.verticalScrollBar()
@ -1000,37 +1000,45 @@ class BooruApp(QMainWindow):
self._run_async(_load) self._run_async(_load)
# Prefetch adjacent posts # Prefetch adjacent posts
if self._db.get_setting_bool("prefetch_adjacent"): if self._db.get_setting("prefetch_mode") in ("Adjacent", "Full page"):
self._prefetch_adjacent(index) self._prefetch_adjacent(index)
def _prefetch_adjacent(self, index: int) -> None: def _prefetch_adjacent(self, index: int) -> None:
"""Prefetch outward from clicked post in all directions, covering the whole page.""" """Prefetch posts around the given index."""
total = len(self._posts) total = len(self._posts)
if total == 0: if total == 0:
return return
cols = self._grid._flow.columns cols = self._grid._flow.columns
mode = self._db.get_setting("prefetch_mode")
# Build ring order: at each distance, grab all 8 directions if mode == "Adjacent":
seen = {index} # Just 4 cardinals: left, right, up, down
order = [] order = []
for dist in range(1, total): for offset in [1, -1, cols, -cols]:
ring = set() adj = index + offset
for dy in (-dist, 0, dist): if 0 <= adj < total:
for dx in (-dist, 0, dist): order.append(adj)
if dy == 0 and dx == 0: else:
continue # Full page: ring expansion in all 8 directions
adj = index + dy * cols + dx seen = {index}
order = []
for dist in range(1, total):
ring = set()
for dy in (-dist, 0, dist):
for dx in (-dist, 0, dist):
if dy == 0 and dx == 0:
continue
adj = index + dy * cols + dx
if 0 <= adj < total and adj not in seen:
ring.add(adj)
for adj in (index + dist, index - dist):
if 0 <= adj < total and adj not in seen: if 0 <= adj < total and adj not in seen:
ring.add(adj) ring.add(adj)
# Also add pure linear neighbors for non-grid nav for adj in sorted(ring):
for adj in (index + dist, index - dist): seen.add(adj)
if 0 <= adj < total and adj not in seen: order.append(adj)
ring.add(adj) if len(order) >= total - 1:
for adj in sorted(ring): break
seen.add(adj)
order.append(adj)
if len(order) >= total - 1:
break
async def _prefetch_spiral(): async def _prefetch_spiral():
for adj in order: for adj in order:

View File

@ -111,9 +111,13 @@ class SettingsDialog(QDialog):
form.addRow("", self._preload) form.addRow("", self._preload)
# Prefetch adjacent posts # Prefetch adjacent posts
self._prefetch = QCheckBox("Prefetch whole page over time") self._prefetch_combo = QComboBox()
self._prefetch.setChecked(self._db.get_setting_bool("prefetch_adjacent")) self._prefetch_combo.addItems(["Off", "Adjacent", "Full page"])
form.addRow("", self._prefetch) prefetch_mode = self._db.get_setting("prefetch_mode") or "Off"
idx = self._prefetch_combo.findText(prefetch_mode)
if idx >= 0:
self._prefetch_combo.setCurrentIndex(idx)
form.addRow("Prefetch:", self._prefetch_combo)
# Infinite scroll # Infinite scroll
self._infinite_scroll = QCheckBox("Infinite scroll (replaces page buttons)") self._infinite_scroll = QCheckBox("Infinite scroll (replaces page buttons)")
@ -681,7 +685,7 @@ class SettingsDialog(QDialog):
self._db.set_setting("default_rating", self._default_rating.currentText()) self._db.set_setting("default_rating", self._default_rating.currentText())
self._db.set_setting("default_score", str(self._default_score.value())) self._db.set_setting("default_score", str(self._default_score.value()))
self._db.set_setting("preload_thumbnails", "1" if self._preload.isChecked() else "0") self._db.set_setting("preload_thumbnails", "1" if self._preload.isChecked() else "0")
self._db.set_setting("prefetch_adjacent", "1" if self._prefetch.isChecked() else "0") self._db.set_setting("prefetch_mode", self._prefetch_combo.currentText())
self._db.set_setting("infinite_scroll", "1" if self._infinite_scroll.isChecked() else "0") self._db.set_setting("infinite_scroll", "1" if self._infinite_scroll.isChecked() else "0")
self._db.set_setting("slideshow_monitor", self._monitor_combo.currentText()) self._db.set_setting("slideshow_monitor", self._monitor_combo.currentText())
self._db.set_setting("library_dir", self._library_dir.text().strip()) self._db.set_setting("library_dir", self._library_dir.text().strip())