* Dataset-info plot hover shows a horizontal crosshair alongside the existing vertical one, so a run of hovers reads as a level or a drift at a glance. * `A` applies auto-contrast once instead of switching on persistent Auto mode (a new `oneShotAutoForeground()`, distinct from the toolbar's Auto toggle); pressing it a second time on the same image switches Auto on for good, and pressing it while Auto is already on leaves it on. The value itself comes from one `AutoForegroundValue()` shared with the continuous Auto path. * `Home`/`End`/`Page Up`/`Page Down` navigate the dataset (first/last image, one image forward/back); claimed in the diffraction view's keyPressEvent before QGraphicsView's default handling, which otherwise eats them to scroll the viewport. * Alt+wheel dataset navigation is removed - some window managers already took it before the app ever saw it, per the caveat that used to sit next to its entry in the shortcuts list. * The image strip dock and its dedicated thumbnail-rendering machinery in the reading worker (SetThumbnail*, RenderThumbnail_i) are removed; it cost a lot and nothing else used any of it. * Toolbar text: "Colour" -> "Color". * Color map, Auto and HDR mode now persist across sessions, the same way the window layout already does. * The Inspector's "Dataset:" path wraps at '/' (a zero-width space after each one) instead of being cut off when it doesn't fit one line. * LoadFile no longer reopens an already-open file - it forwards straight to LoadImage instead - which was the likely cause of a D-Bus client's per-image navigation lagging behind the same navigation done via the grid-scan hover. * New file-manager dock (left, tabbed with Settings via tabifyDockWidget): a directory tree filtered to *_master.h5/*_process.h5, rooted at JUNGFRAUJOCH_DATA_ROOT if set, else the last-browsed root, else the home directory. Most beamline users care about opening images, not reprocessing settings, so it's the tab raised by default. Its filter box narrows files only - a directory always passes - because filtering the directories too hid the matching files under any directory whose own name did not match, and hid the root's ancestors, which left the tree with no valid root index until the root was set again by hand. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PogHY7bWXV4bpctDPdyuDN Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
115 lines
4.8 KiB
C++
115 lines
4.8 KiB
C++
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#include "JFJochViewerToolbarDisplay.h"
|
|
#include <QLabel>
|
|
#include "../../common/ColorScale.h"
|
|
#include "../widgets/ToolbarIcons.h"
|
|
|
|
constexpr double MAX_SLIDER_NO_IMAGE = 65000;
|
|
|
|
JFJochViewerToolbarDisplay::JFJochViewerToolbarDisplay(QWidget *parent)
|
|
: QToolBar(parent) {
|
|
setWindowTitle("Display"); // shown in the toolbar/dock context menu
|
|
addWidget(new QLabel(" Foreground ", this));
|
|
|
|
foreground_slider = new SliderPlusBox(1, MAX_SLIDER_NO_IMAGE, 1.0, 1, this,
|
|
SliderPlusBox::ScaleType::Logarithmic);
|
|
foreground_slider->setValue(10);
|
|
foreground_slider->setToolTip("White point of the color map (image contrast)");
|
|
foreground_slider->setStyleSheet(
|
|
"QSlider::groove:horizontal { height:6px; background:#F3D9D4; border-radius:3px; }"
|
|
"QSlider::sub-page:horizontal { background:#FA7268; border-radius:3px; }"
|
|
"QSlider::handle:horizontal { background:#1F3A5F; width:14px; margin:-5px 0; border-radius:7px; }"
|
|
"QSlider::handle:horizontal:hover { background:#16314F; }");
|
|
addWidget(foreground_slider);
|
|
|
|
auto makeToggle = [this](const QString &text, const QString &tip) {
|
|
auto *b = new QToolButton(this);
|
|
b->setText(text);
|
|
b->setToolButtonStyle(Qt::ToolButtonTextOnly);
|
|
b->setCheckable(true);
|
|
b->setToolTip(tip);
|
|
b->setCursor(Qt::PointingHandCursor);
|
|
b->setStyleSheet(ToolbarIcons::buttonStyle());
|
|
return b;
|
|
};
|
|
auto_foreground_button = makeToggle("Auto", "Auto-contrast to the current image");
|
|
addWidget(auto_foreground_button);
|
|
hdr_mode_button = makeToggle("HDR", "High dynamic range: show the full intensity range unclipped");
|
|
addWidget(hdr_mode_button);
|
|
|
|
addWidget(new QLabel(" Color map ", this));
|
|
|
|
// Initialize QComboBox with the options
|
|
color_map_select = new QComboBox(this);
|
|
color_map_select->addItem("Indigo", static_cast<int>(ColorScaleEnum::Indigo));
|
|
color_map_select->addItem("Viridis", static_cast<int>(ColorScaleEnum::Viridis));
|
|
color_map_select->addItem("Magma", static_cast<int>(ColorScaleEnum::Magma));
|
|
color_map_select->addItem("Inferno", static_cast<int>(ColorScaleEnum::Inferno));
|
|
color_map_select->addItem("Heat", static_cast<int>(ColorScaleEnum::Heat));
|
|
color_map_select->addItem("Black on white", static_cast<int>(ColorScaleEnum::BW));
|
|
color_map_select->addItem("White on black", static_cast<int>(ColorScaleEnum::WB));
|
|
color_map_select->addItem("Green", static_cast<int>(ColorScaleEnum::Green));
|
|
|
|
color_map_select->setCurrentIndex(static_cast<int>(ColorScaleEnum::Indigo));
|
|
addWidget(color_map_select);
|
|
|
|
connect(foreground_slider, &SliderPlusBox::valueChanged, this, &JFJochViewerToolbarDisplay::foregroundSet);
|
|
connect(color_map_select, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
|
this, &JFJochViewerToolbarDisplay::colorComboBoxSet);
|
|
connect(auto_foreground_button, &QToolButton::clicked, this, &JFJochViewerToolbarDisplay::autoForegroundButtonPressed);
|
|
connect(hdr_mode_button, &QToolButton::clicked, this, &JFJochViewerToolbarDisplay::HDRModeButtonPressed);
|
|
auto *stretch = new QWidget(this);
|
|
stretch->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
|
addWidget(stretch);
|
|
}
|
|
|
|
void JFJochViewerToolbarDisplay::foregroundSet(double val) {
|
|
emit setForeground(static_cast<float>(val));
|
|
}
|
|
|
|
void JFJochViewerToolbarDisplay::updateForeground(float val) {
|
|
QSignalBlocker blocker(foreground_slider);
|
|
foreground_slider->setValue(val);
|
|
}
|
|
|
|
void JFJochViewerToolbarDisplay::colorComboBoxSet(int val) {
|
|
emit colorMapChanged(val);
|
|
}
|
|
|
|
void JFJochViewerToolbarDisplay::autoForegroundButtonPressed() {
|
|
emit setAutoForeground(auto_foreground_button->isChecked());
|
|
}
|
|
|
|
void JFJochViewerToolbarDisplay::updateAutoForeground(bool val) {
|
|
QSignalBlocker blocker(auto_foreground_button);
|
|
auto_foreground_button->setChecked(val);
|
|
}
|
|
|
|
void JFJochViewerToolbarDisplay::updateColorMap(int val) {
|
|
QSignalBlocker blocker(color_map_select);
|
|
color_map_select->setCurrentIndex(val);
|
|
}
|
|
|
|
void JFJochViewerToolbarDisplay::updateHDRMode(bool val) {
|
|
QSignalBlocker blocker(hdr_mode_button);
|
|
hdr_mode_button->setChecked(val);
|
|
}
|
|
|
|
void JFJochViewerToolbarDisplay::HDRModeButtonPressed() {
|
|
emit setHDRMode(hdr_mode_button->isChecked());
|
|
}
|
|
|
|
void JFJochViewerToolbarDisplay::imageLoaded(std::shared_ptr<const JFJochReaderImage> image) {
|
|
if (image) {
|
|
auto valid = image->ValidMinMax();
|
|
if (valid.has_value() && valid->second > 1)
|
|
foreground_slider->setMax(valid->second);
|
|
else
|
|
foreground_slider->setMax(MAX_SLIDER_NO_IMAGE);
|
|
} else {
|
|
foreground_slider->setMax(MAX_SLIDER_NO_IMAGE);
|
|
}
|
|
}
|