All checks were successful
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 11m48s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 12m18s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 12m18s
Build Packages / build:rpm (rocky8) (push) Successful in 11m43s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 12m31s
Build Packages / Unit tests (push) Has been skipped
Build Packages / Generate python client (push) Successful in 17s
Build Packages / Create release (push) Has been skipped
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 13m2s
Build Packages / Build documentation (push) Successful in 37s
Build Packages / build:rpm (rocky9) (push) Successful in 9m45s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 6m35s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 7m8s
This is an UNSTABLE release. * jfjoch_viewer: Auto load is better handling change of states * jfjoch_viewer: Fix DBus registration * jfjoch_viewer: Handle charts better with vertical lines on hover and status bar update * jfjoch_viewer: Calculate ROI in a more efficient way Reviewed-on: #6 Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch> Co-committed-by: Filip Leonarski <filip.leonarski@psi.ch>
171 lines
5.6 KiB
C++
171 lines
5.6 KiB
C++
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
||
// SPDX-License-Identifier: GPL-3.0-only
|
||
|
||
#include "JFJochAzIntWindow.h"
|
||
#include <QGroupBox>
|
||
#include <QButtonGroup>
|
||
#include <QFormLayout>
|
||
|
||
JFJochAzIntWindow::JFJochAzIntWindow(
|
||
const AzimuthalIntegrationSettings &settings,
|
||
QWidget *parent)
|
||
: JFJochHelperWindow(parent),
|
||
m_settings(settings)
|
||
{
|
||
setWindowTitle("Azimuthal integration settings");
|
||
QWidget *centralWidget = new QWidget(this);
|
||
setCentralWidget(centralWidget);
|
||
|
||
auto mainLayout = new QVBoxLayout(centralWidget);
|
||
|
||
// Group box similar to TS Paper + stacked inputs
|
||
auto group = new QGroupBox("Azimuthal integration", this);
|
||
auto formLayout = new QFormLayout(group);
|
||
|
||
// Q spacing
|
||
m_qSpacing = new SliderPlusBox(0.01, 1.0, 0.001, 3, this);
|
||
m_qSpacing->setValue(m_settings.GetQSpacing_recipA());
|
||
formLayout->addRow(tr("Q spacing [Å⁻¹]:"), m_qSpacing);
|
||
|
||
// Low Q
|
||
m_lowQ = new SliderPlusBox(0.001, 10.0, 0.001, 3, this);
|
||
m_lowQ->setValue(m_settings.GetLowQ_recipA());
|
||
formLayout->addRow(tr("Low Q [Å⁻¹]:"), m_lowQ);
|
||
|
||
// High Q
|
||
m_highQ = new SliderPlusBox(0.001, 10.0, 0.001, 3, this);
|
||
m_highQ->setValue(m_settings.GetHighQ_recipA());
|
||
formLayout->addRow(tr("High Q [Å⁻¹]:"), m_highQ);
|
||
|
||
// Solid angle / polarization correction checkboxes
|
||
m_solidAngleCheckBox = new QCheckBox(tr("Solid angle correction"), this);
|
||
m_solidAngleCheckBox->setChecked(m_settings.IsSolidAngleCorrection());
|
||
formLayout->addRow(QString(), m_solidAngleCheckBox);
|
||
|
||
m_polarizationCheckBox = new QCheckBox(tr("Polarization correction"), this);
|
||
m_polarizationCheckBox->setChecked(m_settings.IsPolarizationCorrection());
|
||
formLayout->addRow(QString(), m_polarizationCheckBox);
|
||
|
||
// Azimuthal bins (radio buttons like TS frontend)
|
||
auto azimGroupBox = new QGroupBox(tr("Azimuthal bins"), this);
|
||
auto azimLayout = new QHBoxLayout(azimGroupBox);
|
||
m_azimuthalBinsGroup = new QButtonGroup(this);
|
||
|
||
const QList<int> binOptions = {1, 2, 4, 8, 16, 32, 64, 128};
|
||
const int currentBins = m_settings.GetAzimuthalBinCount();
|
||
|
||
for (int bins : binOptions) {
|
||
auto *btn = new QRadioButton(QString::number(bins), azimGroupBox);
|
||
m_azimuthalBinsGroup->addButton(btn, bins);
|
||
m_azimuthalBinButtons.push_back(btn);
|
||
azimLayout->addWidget(btn);
|
||
if (bins == currentBins) {
|
||
btn->setChecked(true);
|
||
}
|
||
}
|
||
|
||
group->setLayout(formLayout);
|
||
mainLayout->addWidget(group);
|
||
mainLayout->addWidget(azimGroupBox);
|
||
|
||
// Error label at bottom (no buttons)
|
||
m_errorLabel = new QLabel(this);
|
||
m_errorLabel->setStyleSheet("color: rgb(200, 0, 0);"); // red-ish text for errors
|
||
m_errorLabel->setWordWrap(true);
|
||
mainLayout->addWidget(m_errorLabel);
|
||
|
||
// Connections – on change, update errors, settings, and emit
|
||
connect(m_qSpacing, &SliderPlusBox::valueChanged, [this](double val) {
|
||
m_qSpacingError = (val < 0.01);
|
||
Update();
|
||
});
|
||
|
||
connect(m_lowQ, &SliderPlusBox::valueChanged, [this](double val) {
|
||
m_lowQError = (val < 0.001 || val > 10.0);
|
||
Update();
|
||
});
|
||
|
||
connect(m_highQ, &SliderPlusBox::valueChanged, [this](double val) {
|
||
m_highQError = (val < 0.001 || val > 10.0);
|
||
Update();
|
||
});
|
||
|
||
connect(m_solidAngleCheckBox, &QCheckBox::toggled, [this](bool /*checked*/) {
|
||
Update();
|
||
});
|
||
|
||
connect(m_polarizationCheckBox, &QCheckBox::toggled, [this](bool /*checked*/) {
|
||
Update();
|
||
});
|
||
|
||
connect(m_azimuthalBinsGroup,
|
||
QOverload<QAbstractButton *>::of(&QButtonGroup::buttonClicked),
|
||
[this](QAbstractButton * /*btn*/) {
|
||
Update();
|
||
});
|
||
|
||
Update();
|
||
}
|
||
|
||
|
||
void JFJochAzIntWindow::UpdateErrorLabel() {
|
||
const double lowQ = m_lowQ->value();
|
||
const double highQ = m_highQ->value();
|
||
|
||
QStringList messages;
|
||
|
||
if (m_qSpacingError) {
|
||
messages << tr("Q spacing must be ≥ 0.01 Å⁻¹.");
|
||
}
|
||
if (m_lowQError) {
|
||
messages << tr("Low Q must be between 0.001 and 10 Å⁻¹.");
|
||
}
|
||
if (m_highQError) {
|
||
messages << tr("High Q must be between 0.001 and 10 Å⁻¹.");
|
||
}
|
||
if (highQ <= lowQ) {
|
||
messages << tr("High Q must be greater than Low Q.");
|
||
}
|
||
|
||
if (messages.isEmpty()) {
|
||
m_errorLabel->clear();
|
||
} else {
|
||
m_errorLabel->setText(messages.join(' '));
|
||
}
|
||
}
|
||
|
||
void JFJochAzIntWindow::ApplyToSettings() {
|
||
const float lowQ = static_cast<float>(m_lowQ->value());
|
||
const float highQ = static_cast<float>(m_highQ->value());
|
||
const float qSpacing = static_cast<float>(m_qSpacing->value());
|
||
|
||
m_settings.SolidAngleCorrection(m_solidAngleCheckBox->isChecked());
|
||
m_settings.PolarizationCorrection(m_polarizationCheckBox->isChecked());
|
||
m_settings.QRange_recipA(lowQ, highQ);
|
||
m_settings.QSpacing_recipA(qSpacing);
|
||
|
||
const int bins = m_azimuthalBinsGroup->checkedId();
|
||
if (bins > 0) {
|
||
m_settings.AzimuthalBinCount(bins);
|
||
}
|
||
}
|
||
|
||
void JFJochAzIntWindow::Update() {
|
||
// Update error label first
|
||
UpdateErrorLabel();
|
||
|
||
// If there are validation errors, do not update settings / emit
|
||
const double lowQ = m_lowQ->value();
|
||
const double highQ = m_highQ->value();
|
||
const bool rangeError = (highQ <= lowQ);
|
||
const bool anyError = m_lowQError || m_highQError || m_qSpacingError || rangeError;
|
||
|
||
if (anyError)
|
||
return;
|
||
|
||
// Update internal settings from widgets
|
||
ApplyToSettings();
|
||
|
||
// Emit updated settings when valid
|
||
emit settingsChanged(m_settings);
|
||
} |