rebrand to orc-gallery and optimise search/thumbnail responsiveness

Rebrand:
- Rename project, binary, desktop file, and icons from screenshot-gallery/orcs-gallery to orc-gallery
- Update display name to "ORC Gallery" throughout (window title, .desktop, README, plan.md)
- Config dir changed from ScreenshotOCRGallery to OrcGallery

Performance:
- cancelSearch() is now non-blocking; new searches start immediately instead of waiting for the previous thread to drain
- Remove double-emit from QFutureWatcher::finished handler; results emitted once directly from background thread
- SQLite WAL mode + NORMAL sync + 20 MB page cache + memory temp store + 256 MB mmap applied on init and per-thread connections
- Typing inactivity timer reduced from 500 ms to 150 ms
- COUNT(*) OVER() window function folds total-count into the main SELECT, eliminating a separate COUNT round-trip per search
- ImageThumbnail::paintEvent draws the filename overlay; removes 3 child QObjects (QFrame + QLabel + QHBoxLayout) per thumbnail
- loadThumbnailAsync posts QImage load+scale to QThreadPool; QPixmap::fromImage called on main thread via Qt::QueuedConnection invokeMethod; QPointer guards against use-after-free on gallery clear

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
yzinchuk
2026-07-03 03:53:07 -04:00
parent 3fb8d7e507
commit 55454d7ef6
23 changed files with 231 additions and 315 deletions
+34 -25
View File
@@ -1,4 +1,4 @@
# OCR Screenshot Gallery — Project Reference
# ORC Gallery — Project Reference
A Qt6 desktop application for Linux that OCRs screenshots and provides a searchable, paginated gallery interface. Users run a Python OCR script to populate a SQLite database, then browse and search all recognized text visually.
@@ -7,12 +7,12 @@ A Qt6 desktop application for Linux that OCRs screenshots and provides a searcha
## Directory Structure
```
ocr-screenshot-gallery/
orc-gallery/
├── CMakeLists.txt # CMake build configuration (Qt6)
├── build.sh # One-shot build automation script
├── README.md # User-facing documentation
├── resources.qrc # Qt resource file bundling icons
├── screenshot-gallery.desktop # Linux XDG desktop entry
├── orc-gallery.desktop # Linux XDG desktop entry
├── .gitignore
├── src/ # C++ application source
@@ -34,13 +34,13 @@ ocr-screenshot-gallery/
│ └── screenshot_ocr.db # Example/seed database
├── icons/ # Application icon assets
│ ├── orcs-gallery-512.png
│ ├── orcs-gallery-256.png
│ ├── orcs-gallery-128.png
│ └── orcs-gallery-64.png
│ ├── orc-gallery-512.png
│ ├── orc-gallery-256.png
│ ├── orc-gallery-128.png
│ └── orc-gallery-64.png
└── build/ # CMake build output (git-ignored)
└── screenshot-gallery # Compiled executable
└── orc-gallery # Compiled executable
```
---
@@ -86,20 +86,20 @@ make -j$(nproc)
### Run
```bash
./build/screenshot-gallery
./build/orc-gallery
```
### Install system-wide
```bash
cd build && sudo make install
screenshot-gallery # from anywhere
orc-gallery # from anywhere
```
Installation puts:
- Binary → `${CMAKE_INSTALL_BINDIR}` (typically `/usr/local/bin/`)
- Icons → `/share/icons/hicolor/{64x64,128x128,256x256,512x512}/apps/orcs-gallery.png`
- Desktop entry → `/share/applications/screenshot-gallery.desktop`
- Icons → `/share/icons/hicolor/{64x64,128x128,256x256,512x512}/apps/orc-gallery.png`
- Desktop entry → `/share/applications/orc-gallery.desktop`
---
@@ -107,9 +107,9 @@ Installation puts:
### Location
Default (XDG-compliant): `~/.local/share/screenshot-gallery/screenshot_ocr.db`
Default (XDG-compliant): `~/.local/share/orc-gallery/screenshot_ocr.db`
Configurable in Settings dialog; stored in `~/.config/ScreenshotOCRGallery/settings.ini`.
Configurable in Settings dialog; stored in `~/.config/OrcGallery/settings.ini`.
### Schema
@@ -162,7 +162,7 @@ Responsibilities:
- Search bar (`QLineEdit`) with a 500 ms typing-inactivity timer (`m_typingTimer`) — search only fires after the user stops typing
- Animated "Searching…" status bar indicator (`m_searchingAnimationTimer`)
- Instantiates and owns `DatabaseManager` and `ImageGallery`
- Reads/writes settings via `QSettings` (INI at `~/.config/ScreenshotOCRGallery/settings.ini`)
- Reads/writes settings via `QSettings` (INI at `~/.config/OrcGallery/settings.ini`)
- On search complete: updates status bar with result count
- On clear search: reloads all images (first page)
@@ -282,7 +282,7 @@ Main OCR runner. Scans a screenshots directory, runs Tesseract on each image not
```bash
python3 OCR-scripts/ocr_screenshots.py \
--db ~/.local/share/screenshot-gallery/screenshot_ocr.db \
--db ~/.local/share/orc-gallery/screenshot_ocr.db \
--screenshots-dir ~/Screenshots
```
@@ -307,11 +307,11 @@ These scripts hook OCR-screenshot workflows into the [Rofi](https://github.com/d
## Settings & Configuration
**Settings file:** `~/.config/ScreenshotOCRGallery/settings.ini`
**Settings file:** `~/.config/OrcGallery/settings.ini`
```ini
[General]
databasePath=/home/<user>/.local/share/screenshot-gallery/screenshot_ocr.db
databasePath=/home/<user>/.local/share/orc-gallery/screenshot_ocr.db
screenshotsDir=/home/<user>/Screenshots
imagePreloadCount=20
```
@@ -344,28 +344,33 @@ All three keys have fallbacks defined in `MainWindow::loadSettings()` and `Setti
| Repeated searches | 5-minute LRU cache in `DatabaseManager` |
| Large galleries | Explicit pagination (default 20, user-controlled via Load More) |
| Column reflow cost | 300 ms debounce on resize events |
| Typing lag | 500 ms inactivity timer before issuing query |
| Typing lag | 150 ms inactivity timer before issuing query |
| Thread-safe DB access | Per-thread `QSqlDatabase` connections + `QMutex` guards |
| Missing files | Placeholder thumbnail rendered inline; no crash |
| Cancel stall | Non-blocking cancel: flag set immediately, old thread drains in background |
| COUNT round-trip | `COUNT(*) OVER()` window function folds count into the main SELECT |
| SQLite I/O | WAL journal + 20 MB page cache + memory-mapped I/O via PRAGMA on init |
| Thumbnail load stall | `QImage` loaded/scaled on `QThreadPool`, marshalled to main thread via `invokeMethod` |
| Overlay widget cost | Filename drawn in `ImageThumbnail::paintEvent` — no child QFrame/QLabel/QHBoxLayout |
---
## Linux Desktop Integration
**`screenshot-gallery.desktop`**
**`orc-gallery.desktop`**
```ini
[Desktop Entry]
Type=Application
Name=Screenshot OCR Gallery
Icon=orcs-gallery
Exec=screenshot-gallery
Name=ORC Gallery
Icon=orc-gallery
Exec=orc-gallery
Categories=Graphics;Utility;Viewer;
Keywords=screenshots;ocr;gallery;search;images;
```
XDG paths used by the application:
- Config: `QStandardPaths::AppConfigLocation``~/.config/ScreenshotOCRGallery/`
- Data: `QStandardPaths::AppLocalDataLocation``~/.local/share/screenshot-gallery/`
- Config: `QStandardPaths::AppConfigLocation``~/.config/OrcGallery/`
- Data: `QStandardPaths::AppLocalDataLocation``~/.local/share/orc-gallery/`
---
@@ -378,3 +383,7 @@ XDG paths used by the application:
- The `UpdateDatabaseDialog` is instantiated fresh each time (not reused) to avoid stale process state.
- `ImageGallery` does not use a `QAbstractItemModel`; it builds `ImageThumbnail` widgets directly and manages them in a flat list (`m_thumbnails`).
- Database connections must not be shared across threads — each `QtConcurrent` task opens its own named connection and closes it on exit.
- `cancelSearch()` is non-blocking: it sets `m_searchCancelled` and returns immediately. The background thread checks the flag at multiple points and exits early. The destructor sets the flag then calls `waitForFinished()` for clean shutdown.
- The watcher's `finished` signal is not used for emitting results (was causing double-emit). Results are emitted directly from `performSearchInBackground` once and only if `m_currentSearchText == searchText`.
- `ImageThumbnail::paintEvent` draws the filename overlay; no child widgets needed. The `m_displayName` field is pre-truncated in the constructor.
- Async thumbnail loading: `loadThumbnailAsync` posts to `QThreadPool::globalInstance()`. `QImage` is loaded and `.scaled()` off the main thread; `QPixmap::fromImage()` is called inside a `Qt::QueuedConnection` invokeMethod lambda. A `QPointer<ImageThumbnail>` guard prevents use-after-free if the gallery clears before the load completes.