Files
Jungfraujoch/viewer/image_viewer/JFJochGridScanImage.h
T
leonarski_fandClaude Opus 5 501ce1ba3d Viewer: rate-limit hover feedback to ~15 Hz
The status bar, the resolution readout and the magnifier were all regenerated
on every single mouse motion event. Each regeneration repaints, and on a remote
X session a repaint uploads the whole window regardless of how little changed,
so the pointer merely crossing the image saturates the link: measured with a
counting relay in front of the X server, 50 motions over the image cost 273 MB,
and a build with the hover work removed cost 18 KB.

Rate-limit it. Two details matter:

- The limit is applied inline, not from a timer. Running the update inside the
  mouse event keeps its damage in the same repaint as anything else that event
  triggers (a pan). A first attempt deferred the work to a timer instead, which
  split one repaint into two and made panning measurably worse.
- The catch-up that reports the final position is debounced, not queued per
  skipped motion, so it fires once after the pointer stops rather than
  repeatedly mid-gesture.

mouseHover() now takes the scene position and modifiers instead of the event,
which also removes the identical mapToScene() from all four implementations.

Hover traffic over 3 repeats: 173 MB mean -> 140 MB, and the run-to-run spread
drops from +-14% to +-2%. The harness tops out near 30 motions/s, barely above
the 15 Hz limit; a real mouse reports far faster, where the cap does more.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 20:12:36 +02:00

36 lines
1.1 KiB
C++

// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include "JFJochImage.h"
#include "../../reader/JFJochReaderDataset.h"
Q_DECLARE_METATYPE(GridScanSettings)
class JFJochGridScanImage : public JFJochImage {
Q_OBJECT
std::optional<GridScanSettings> settings;
std::vector<int64_t> image_index;
int64_t current_image_W = -1;
int64_t current_image_H = -1;
bool one_over_d2 = false;
void mouseHover(const QPointF &scenePos, Qt::KeyboardModifiers modifiers) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
void loadImage(QMouseEvent *event);
void addCustomOverlay() override;
signals:
void imageSelected(int64_t number);
void writeStatusBar(QString string, int timeout_ms = 0);
public:
JFJochGridScanImage(QWidget *parent = nullptr);
public slots:
void loadData(const std::vector<float> &data, const GridScanSettings &settings, bool one_over_d2);
void setImage(int64_t val);
void clear();
};