The hovered "d = ... A" readout was a QGraphicsTextItem flagged ItemIgnoresTransformations, repositioned on every mouse motion. Qt cannot compute a tight dirty rect for an item that ignores the view transform, so it marks the entire viewport dirty whenever such an item moves or changes text -- and this one moved constantly. Paint it in drawForeground() in viewport pixels instead, and repaint only the union of its old and new rectangles. That also removes the item lifetime special-casing: it was deliberately kept out of overlay_items_, had to be nulled by hand after scene()->clear(), and carried comments in three places warning about the dangling pointer. This does not reduce raw X11 traffic -- there every repaint uploads the whole window whatever the damage -- but it cuts the work per hover, and it does matter under a compressing remote protocol (VNC/NX/xpra), which encodes only the region that actually changed. Verified against the previous build: same text, colour and position. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
138 lines
5.1 KiB
C++
138 lines
5.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 <QPainterPath>
|
|
|
|
#include "JFJochImage.h"
|
|
#include "../../reader/JFJochReaderImage.h"
|
|
#include "../../common/ROIDefinition.h"
|
|
|
|
class ROIAzimuthal;
|
|
class DiffractionGeometry;
|
|
|
|
class JFJochDiffractionImage : public JFJochImage {
|
|
Q_OBJECT
|
|
|
|
QColor spot_color = Qt::green;
|
|
QColor prediction_color = Qt::darkRed;
|
|
QColor ice_ring_color = Qt::cyan;
|
|
QColor second_lattice_color = QColor(0xFA, 0x72, 0x68); // coral, the viewer "finishing" accent
|
|
|
|
float hover_resolution = NAN;
|
|
// The "d = ... A" readout is painted in drawForeground() in viewport pixels rather than kept
|
|
// as a scene item, so updating it dirties only its own rect. hover_text_rect_ is where it
|
|
// currently sits, in viewport coordinates.
|
|
QRect hover_text_rect_;
|
|
[[nodiscard]] QString HoverResolutionLabel() const;
|
|
void drawForeground(QPainter *painter, const QRectF &rect) override;
|
|
public:
|
|
enum class RingMode {Auto, Estimation, Manual, None, IceRings};
|
|
Q_ENUM(RingMode)
|
|
|
|
JFJochDiffractionImage(QWidget *parent = nullptr);
|
|
private:
|
|
|
|
void addCustomOverlay() override;
|
|
void LoadImageInternal();
|
|
// Colour straight from the int32 detector image; image_fp is only materialised when the
|
|
// base class actually needs pixel values (ROI statistics, per-pixel labels).
|
|
void ColorRow(size_t y, const PixelColorMap &map, QRgb *out) const override;
|
|
void EnsurePixelValues() override;
|
|
bool pixel_values_valid_ = false;
|
|
void DrawResolutionRings();
|
|
void DrawROIs();
|
|
void DrawAzimuthalROI(const ROIAzimuthal &az, const QColor &color, const DiffractionGeometry &geom);
|
|
void AddROILabel(const std::string &name, const QColor &color, float px, float py);
|
|
|
|
// Interactive editing of the selected (named) ROI: move box/circle for now.
|
|
bool roiEditPress(const QPointF &scenePos) override;
|
|
void roiEditMove(const QPointF &scenePos) override;
|
|
void roiEditRelease() override;
|
|
void roiScratchDrawn() override;
|
|
void keyPressEvent(QKeyEvent *event) override; // Delete removes the selected ROI
|
|
[[nodiscard]] ROIDefinition BuildEditedROIDefinition() const; // current ROIs with the edit applied
|
|
[[nodiscard]] ResizeHandle hitTestBoxHandle(const QRectF &r, const QPointF &p, qreal tol) const;
|
|
// Grab points for an azimuthal ROI: inner/outer arc (resize Q/d) and the two phi
|
|
// edges (rotate). The phi handles are only meaningful for a sector (HasPhi()).
|
|
void azimuthalHandles(const ROIAzimuthal &az, const DiffractionGeometry &geom,
|
|
QPointF &inner, QPointF &outer, QPointF &phimin, QPointF &phimax) const;
|
|
|
|
QString selected_roi_;
|
|
enum class RoiEdit { None, MoveBox, ResizeBox, MoveCircle, ResizeCircle,
|
|
AzimInner, AzimOuter, RotatePhiMin, RotatePhiMax };
|
|
RoiEdit roi_edit_ = RoiEdit::None;
|
|
ResizeHandle box_handle_ = ResizeHandle::None;
|
|
QString edit_name_;
|
|
QRectF edit_box_;
|
|
QPointF edit_center_;
|
|
double edit_radius_ = 0;
|
|
float edit_d_min_ = 0, edit_d_max_ = 0, edit_phi_min_ = 0, edit_phi_max_ = 0; // azimuthal edit state
|
|
bool edit_has_phi_ = false;
|
|
QPointF move_last_;
|
|
bool live_pending_ = false; // a live edit is being recomputed; throttles emissions
|
|
|
|
void DrawSpots();
|
|
void DrawPredictions();
|
|
void DrawBeamCenter();
|
|
void DrawTopPixels();
|
|
void DrawSaturation();
|
|
void DrawResolutionText();
|
|
void DrawCross(float x, float y, float size, float width, float z = 1);
|
|
|
|
void UpdateForeground();
|
|
void beforeOverlayCleared() override;
|
|
void leaveEvent(QEvent *event) override;
|
|
|
|
std::shared_ptr<const JFJochReaderImage> image;
|
|
|
|
int32_t show_highest_pixels = 0;
|
|
|
|
QVector<float> res_ring = {};
|
|
|
|
// Constant-d contours traced for res_ring, kept across overlay rebuilds; see DrawResolutionRings
|
|
QVector<float> ring_cache_key_ = {};
|
|
QVector<std::pair<float, QPainterPath>> ring_cache_ = {};
|
|
|
|
RingMode ring_mode = RingMode::Estimation;
|
|
|
|
bool show_spots = false;
|
|
bool show_predictions = false;
|
|
|
|
bool show_roi_labels = false;
|
|
bool show_roi_fill = false;
|
|
|
|
bool highlight_ice_rings = true;
|
|
|
|
float ice_ring_width_Q_recipA = 0.01;
|
|
|
|
void mouseHover(const QPointF &scenePos, Qt::KeyboardModifiers modifiers) override;
|
|
|
|
signals:
|
|
void roiGeometryEdited(ROIDefinition rois);
|
|
void roiSelected(QString name); // user picked an ROI by clicking it on the image
|
|
public slots:
|
|
void setSelectedROI(QString name);
|
|
void loadImage(std::shared_ptr<const JFJochReaderImage> image);
|
|
void setAutoForeground(bool input);
|
|
void setResolutionRing(QVector<float> v);
|
|
void setResolutionRingMode(RingMode mode);
|
|
|
|
void showSpots(bool input);
|
|
void showPredictions(bool input);
|
|
|
|
void showROILabels(bool input);
|
|
void showROIFill(bool input);
|
|
|
|
void setSpotColor(QColor input);
|
|
void setPredictionColor(QColor input);
|
|
|
|
void showHighestPixels(int32_t v);
|
|
void showSaturation(bool input);
|
|
|
|
void highlightIceRings(bool input);
|
|
void setHDRMode(bool input);
|
|
};
|
|
|