viewer: panel polish — accordions, shared geometry, detector tilt, SG name

Declutter the side and settings panels (review items a–f):

- New CollapsibleSection widget (slim navy header + coral rule + chevron).
- Inspector: Image features / Resolution rings / ROI are now collapsible and
  start folded (ROI auto-expands when ROIs change); drop the Data-analysis and
  Powder-calibration sections (they live in the hero buttons and settings dock).
- Settings dock: move Geometry to a shared section above the MX/AzInt toggle
  (both communities need it); add Detector tilt (PONI rot1/rot2, deg) and
  rename "Beam center" -> "Beam origin" with PONI/XDS tooltips; show the
  space-group number and resolved Hermann–Mauguin symbol on one line; wrap
  sections in accordions, anchored top with a bottom stretch so expanding one
  does not shift the others.
- Toolbar: drop the redundant "Image number" label.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-23 16:26:15 +02:00
co-authored by Claude Opus 4.8
parent e7edee6b2e
commit 03ac43da69
8 changed files with 209 additions and 72 deletions
+2
View File
@@ -62,6 +62,8 @@ ADD_EXECUTABLE(jfjoch_viewer jfjoch_viewer.cpp JFJochViewerWindow.cpp JFJochView
widgets/JFJochViewerSidePanelChart.h
widgets/JFJochViewerSettingsDock.cpp
widgets/JFJochViewerSettingsDock.h
widgets/CollapsibleSection.cpp
widgets/CollapsibleSection.h
windows/JFJochViewerSpotListWindow.cpp
windows/JFJochViewerSpotListWindow.h
image_viewer/JFJochAzIntImage.cpp
+23 -28
View File
@@ -8,8 +8,8 @@
#include "JFJochViewerSidePanel.h"
#include "widgets/TitleLabel.h"
#include "widgets/CollapsibleSection.h"
#include "widgets/JFJochViewerImageStatistics.h"
#include "widgets/PowderCalibrationWidget.h"
JFJochViewerSidePanel::JFJochViewerSidePanel(QWidget *parent) : QWidget(parent) {
@@ -21,7 +21,7 @@ JFJochViewerSidePanel::JFJochViewerSidePanel(QWidget *parent) : QWidget(parent)
layout->addWidget(stats);
connect(this, &JFJochViewerSidePanel::imageLoaded, stats, &JFJochViewerImageStatistics::loadImage);
layout->addWidget(new TitleLabel("Image features", this));
auto *featuresSection = new CollapsibleSection("Image features", this);
auto spotToggleCheckBox = new QCheckBox("Show spots", this);
spotToggleCheckBox->setCheckState(Qt::CheckState::Unchecked);
@@ -84,9 +84,13 @@ JFJochViewerSidePanel::JFJochViewerSidePanel(QWidget *parent) : QWidget(parent)
image_feature_grid->addWidget(colorSelectButton, 3, 0);
image_feature_grid->addWidget(spotColorSelectButton, 3, 1);
layout->addLayout(image_feature_grid);
featuresSection->setContentLayout(image_feature_grid);
featuresSection->setExpanded(false);
layout->addWidget(featuresSection);
layout->addWidget(new TitleLabel("Resolution rings", this));
auto *ringsSection = new CollapsibleSection("Resolution rings", this);
auto *ringsLayout = new QVBoxLayout();
ringsLayout->setContentsMargins(0, 0, 0, 0);
res_rings = new ResolutionRingWidget(this);
connect(res_rings, &ResolutionRingWidget::resRingsSet, [this] (const QVector<float> &v) {
@@ -97,12 +101,18 @@ JFJochViewerSidePanel::JFJochViewerSidePanel(QWidget *parent) : QWidget(parent)
emit ringModeSet(mode);
});
layout->addWidget(res_rings);
ringsLayout->addWidget(res_rings);
ringsSection->setContentLayout(ringsLayout);
ringsSection->setExpanded(false);
layout->addWidget(ringsSection);
// The per-image statistics plot now lives in the dataset-info dock (its "Per-image" toggle),
// so it is no longer duplicated here.
// and powder calibration / full analysis live in the settings dock and the hero buttons,
// so they are no longer duplicated here.
layout->addWidget(new TitleLabel("ROI", this));
roiSection = new CollapsibleSection("ROI", this);
auto *roiLayout = new QVBoxLayout();
roiLayout->setContentsMargins(0, 0, 0, 0);
auto roiLabelsCheckBox = new QCheckBox("Show labels", this);
roiLabelsCheckBox->setCheckState(Qt::CheckState::Unchecked);
@@ -115,35 +125,20 @@ JFJochViewerSidePanel::JFJochViewerSidePanel(QWidget *parent) : QWidget(parent)
auto roiToggleRow = new QHBoxLayout();
roiToggleRow->addWidget(roiLabelsCheckBox);
roiToggleRow->addWidget(roiFillCheckBox);
layout->addLayout(roiToggleRow);
roiLayout->addLayout(roiToggleRow);
roi_list = new JFJochViewerROIList(this);
layout->addWidget(roi_list);
roiLayout->addWidget(roi_list);
connect(this, &JFJochViewerSidePanel::imageLoaded, roi_list, &JFJochViewerROIList::loadImage);
connect(roi_list, &JFJochViewerROIList::roisChanged, this, &JFJochViewerSidePanel::roisChanged);
connect(roi_list, &JFJochViewerROIList::selectedROIChanged, this, &JFJochViewerSidePanel::selectedROIChanged);
connect(roi_list, &JFJochViewerROIList::downloadROIs, this, &JFJochViewerSidePanel::downloadROIs);
connect(roi_list, &JFJochViewerROIList::uploadROIs, this, &JFJochViewerSidePanel::uploadROIs);
connect(roi_list, &JFJochViewerROIList::maskFromROI, this, &JFJochViewerSidePanel::maskFromROI);
layout->addWidget(new TitleLabel("Data analysis", this));
auto analyzeButton = new QPushButton("Full analysis", this);
connect(analyzeButton, &QPushButton::clicked,[this] {emit analyze();});
layout->addWidget(analyzeButton);
// Calibrant selection combo box
layout->addWidget(new TitleLabel("Powder geometry calibration", this));
auto power_calibration = new PowderCalibrationWidget(this);
layout->addWidget(power_calibration);
connect(this, &JFJochViewerSidePanel::imageLoaded, power_calibration, &PowderCalibrationWidget::loadImage);
connect(power_calibration, &PowderCalibrationWidget::ringsFromCalibration, res_rings, &ResolutionRingWidget::setRings);
connect(power_calibration, &PowderCalibrationWidget::findBeamCenter,
[this] (const UnitCell& input, bool guess) {
emit findBeamCenter(input, guess);
});
connect(roi_list, &JFJochViewerROIList::roisChanged, this, [this] { roiSection->setExpanded(true); });
roiSection->setContentLayout(roiLayout);
roiSection->setExpanded(false);
layout->addWidget(roiSection);
layout->addStretch();
setLayout(layout); // Set the layout to the widget
+3
View File
@@ -13,11 +13,14 @@
#include "charts/JFJochSimpleChartView.h"
#include "widgets/ResolutionRingWidget.h"
class CollapsibleSection;
class JFJochViewerSidePanel : public QWidget {
Q_OBJECT
JFJochViewerROIList *roi_list = nullptr;
ResolutionRingWidget *res_rings = nullptr;
CollapsibleSection *roiSection = nullptr; // auto-expands when ROIs change
signals:
void showSpots(bool input);
@@ -8,9 +8,6 @@
JFJochViewerToolbarImage::JFJochViewerToolbarImage(QWidget *parent) : QToolBar(parent) {
image_count_in_dataset = 0;
auto title = new QLabel("<b>Image number</b> ", this);
addWidget(title);
leftmost_button = new QPushButton(this);
leftmost_button->setIcon(style()->standardIcon(QStyle::SP_MediaSkipBackward));
leftmost_button->setToolTip("First image");
+44
View File
@@ -0,0 +1,44 @@
// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include "CollapsibleSection.h"
#include <QToolButton>
#include <QVBoxLayout>
CollapsibleSection::CollapsibleSection(const QString &title, QWidget *parent) : QWidget(parent) {
auto *v = new QVBoxLayout(this);
v->setContentsMargins(0, 0, 0, 0);
v->setSpacing(0);
header_ = new QToolButton(this);
header_->setText(title);
header_->setCheckable(true);
header_->setChecked(true);
header_->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
header_->setArrowType(Qt::DownArrow);
header_->setCursor(Qt::PointingHandCursor);
header_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
header_->setStyleSheet(
"QToolButton { color:#1F3A5F; font-weight:bold; text-align:left;"
" padding:3px 6px 3px 6px; border:none;"
" border-left:3px solid #FA7268; border-bottom:1px solid #FA7268; background:transparent; }");
content_ = new QWidget(this);
v->addWidget(header_);
v->addWidget(content_);
connect(header_, &QToolButton::toggled, this, [this](bool on) {
content_->setVisible(on);
header_->setArrowType(on ? Qt::DownArrow : Qt::RightArrow);
});
}
void CollapsibleSection::setContentLayout(QLayout *layout) {
content_->setLayout(layout);
}
void CollapsibleSection::setExpanded(bool on) {
header_->setChecked(on);
}
+23
View File
@@ -0,0 +1,23 @@
// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include <QWidget>
class QToolButton;
class QLayout;
// A slim collapsible section: a clickable navy header with a coral accent rule and a chevron,
// over a content area that folds away. Used to keep the side and settings panels compact.
class CollapsibleSection : public QWidget {
Q_OBJECT
public:
explicit CollapsibleSection(const QString &title, QWidget *parent = nullptr);
void setContentLayout(QLayout *layout);
void setExpanded(bool on);
private:
QToolButton *header_;
QWidget *content_;
};
+106 -40
View File
@@ -6,7 +6,6 @@
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QFormLayout>
#include <QGroupBox>
#include <QPushButton>
#include <QButtonGroup>
#include <QStackedWidget>
@@ -19,7 +18,9 @@
#include "SliderPlusBox.h"
#include "NumberLineEdit.h"
#include "PowderCalibrationWidget.h"
#include "TitleLabel.h"
#include "CollapsibleSection.h"
#include "../../common/JFJochMath.h"
#include "../../gemmi_gph/gemmi/symmetry.hpp"
JFJochViewerSettingsDock::JFJochViewerSettingsDock(const SpotFindingSettings &spot,
const IndexingSettings &indexing,
@@ -50,39 +51,63 @@ JFJochViewerSettingsDock::JFJochViewerSettingsDock(const SpotFindingSettings &sp
stack->addWidget(BuildAzIntPage());
connect(group, &QButtonGroup::idClicked, stack, &QStackedWidget::setCurrentIndex);
// Geometry is common to both communities, so it lives above the toggle rather than per page.
auto *layout = new QVBoxLayout(this);
layout->addLayout(toggleRow);
layout->addWidget(BuildGeometrySection());
layout->addWidget(stack);
layout->addStretch();
}
QWidget *JFJochViewerSettingsDock::BuildGeometrySection() {
auto *section = new CollapsibleSection("Geometry", this);
auto *geom = new QFormLayout();
energy_ = new NumberLineEdit(1.0, 200.0, 12.4, 4, "keV", this);
distance_ = new NumberLineEdit(10.0, 5000.0, 100.0, 2, "mm", this);
beamX_ = new NumberLineEdit(-20000.0, 20000.0, 0.0, 1, "px", this);
beamY_ = new NumberLineEdit(-20000.0, 20000.0, 0.0, 1, "px", this);
rot1_ = new NumberLineEdit(-180.0, 180.0, 0.0, 3, "°", this);
rot2_ = new NumberLineEdit(-180.0, 180.0, 0.0, 3, "°", this);
// The detector origin is the PONI (PyFAI) point; in MX (XDS-style) terms it is the beam origin,
// which coincides with the beam center only when the detector is untilted.
const QString beamTip =
"Beam origin (XDS convention): the PONI point where the un-tilted beam meets the detector. "
"Equals the beam center only when the detector tilt is zero.";
beamX_->setToolTip(beamTip);
beamY_->setToolTip(beamTip);
const QString tiltTip = "Detector tilt about the two in-plane axes (PyFAI PONI rot1 / rot2), in degrees.";
rot1_->setToolTip(tiltTip);
rot2_->setToolTip(tiltTip);
auto *beam = new QHBoxLayout();
beam->addWidget(beamX_);
beam->addWidget(beamY_);
auto *tilt = new QHBoxLayout();
tilt->addWidget(rot1_);
tilt->addWidget(rot2_);
geom->addRow("Photon energy", energy_);
geom->addRow("Detector distance", distance_);
geom->addRow("Beam origin", beam);
geom->addRow("Detector tilt", tilt);
for (auto *f : {energy_, distance_, beamX_, beamY_, rot1_, rot2_})
connect(f, &NumberLineEdit::newValue, this, [this] { EmitExperiment(); });
section->setContentLayout(geom);
return section;
}
QWidget *JFJochViewerSettingsDock::BuildMXPage() {
auto *page = new QWidget(this);
auto *layout = new QVBoxLayout(page);
layout->setContentsMargins(0, 0, 0, 0);
// --- Geometry ---
layout->addWidget(new TitleLabel("Geometry", page));
auto *geomGroup = new QGroupBox(page);
auto *geom = new QFormLayout(geomGroup);
energy_ = new NumberLineEdit(1.0, 200.0, 12.4, 4, "keV", page);
distance_ = new NumberLineEdit(10.0, 5000.0, 100.0, 2, "mm", page);
beamX_ = new NumberLineEdit(0.0, 20000.0, 0.0, 1, "px", page);
beamY_ = new NumberLineEdit(0.0, 20000.0, 0.0, 1, "px", page);
geom->addRow("Photon energy", energy_);
geom->addRow("Detector distance", distance_);
auto *beam = new QHBoxLayout();
beam->addWidget(beamX_);
beam->addWidget(beamY_);
geom->addRow("Beam center", beam);
layout->addWidget(geomGroup);
for (auto *f : {energy_, distance_, beamX_, beamY_})
connect(f, &NumberLineEdit::newValue, this, [this] { EmitExperiment(); });
// --- Unit cell + space group (new: no input existed before) ---
layout->addWidget(new TitleLabel("Unit cell", page));
auto *cellGroup = new QGroupBox(page);
auto *cell = new QFormLayout(cellGroup);
auto *cellSection = new CollapsibleSection("Unit cell", page);
auto *cell = new QFormLayout();
cellKnown_ = new QCheckBox("Known unit cell", page);
cell->addRow("", cellKnown_);
cellA_ = new NumberLineEdit(1.0, 2000.0, 79.0, 3, "Å", page);
@@ -92,14 +117,21 @@ QWidget *JFJochViewerSettingsDock::BuildMXPage() {
cellBeta_ = new NumberLineEdit(1.0, 179.0, 90.0, 2, "°", page);
cellGamma_ = new NumberLineEdit(1.0, 179.0, 90.0, 2, "°", page);
spaceGroup_ = new NumberLineEdit(0.0, 230.0, 0.0, 0, "", page);
spaceGroup_->setToolTip("Space group number (1230); 0 = unset.");
spaceGroupName_ = new QLabel("", page);
auto *abc = new QHBoxLayout();
abc->addWidget(cellA_); abc->addWidget(cellB_); abc->addWidget(cellC_);
auto *angles = new QHBoxLayout();
angles->addWidget(cellAlpha_); angles->addWidget(cellBeta_); angles->addWidget(cellGamma_);
// Number and symbol split the line evenly, like the beam-origin row.
auto *sgRow = new QHBoxLayout();
sgRow->addWidget(spaceGroup_, 1);
sgRow->addWidget(spaceGroupName_, 1);
cell->addRow("a, b, c", abc);
cell->addRow("α, β, γ", angles);
cell->addRow("Space group", spaceGroup_);
layout->addWidget(cellGroup);
cell->addRow("Space group", sgRow);
cellSection->setContentLayout(cell);
layout->addWidget(cellSection);
auto enableCellFields = [this](bool on) {
for (auto *f : {cellA_, cellB_, cellC_, cellAlpha_, cellBeta_, cellGamma_, spaceGroup_})
@@ -108,15 +140,19 @@ QWidget *JFJochViewerSettingsDock::BuildMXPage() {
enableCellFields(false);
connect(cellKnown_, &QCheckBox::toggled, this, [this, enableCellFields](bool on) {
enableCellFields(on);
UpdateSpaceGroupName();
EmitExperiment();
});
for (auto *f : {cellA_, cellB_, cellC_, cellAlpha_, cellBeta_, cellGamma_, spaceGroup_})
for (auto *f : {cellA_, cellB_, cellC_, cellAlpha_, cellBeta_, cellGamma_})
connect(f, &NumberLineEdit::newValue, this, [this] { EmitExperiment(); });
connect(spaceGroup_, &NumberLineEdit::newValue, this, [this] {
UpdateSpaceGroupName();
EmitExperiment();
});
// --- Spot finding ---
layout->addWidget(new TitleLabel("Spot finding", page));
auto *spotGroup = new QGroupBox(page);
auto *spot = new QFormLayout(spotGroup);
auto *spotSection = new CollapsibleSection("Spot finding", page);
auto *spot = new QFormLayout();
auto *snr = new SliderPlusBox(1.0, 10.0, 0.1, 1, page);
snr->setValue(spot_.signal_to_noise_threshold);
auto *count = new SliderPlusBox(0.0, 100.0, 1.0, 0, page);
@@ -126,7 +162,8 @@ QWidget *JFJochViewerSettingsDock::BuildMXPage() {
spot->addRow("Signal/noise", snr);
spot->addRow("Photon count", count);
spot->addRow("Min pixels/spot", minPix);
layout->addWidget(spotGroup);
spotSection->setContentLayout(spot);
layout->addWidget(spotSection);
connect(snr, &SliderPlusBox::valueChanged, this, [this](double v) {
spot_.signal_to_noise_threshold = static_cast<float>(v); EmitSpotFinding(); });
connect(count, &SliderPlusBox::valueChanged, this, [this](double v) {
@@ -135,9 +172,8 @@ QWidget *JFJochViewerSettingsDock::BuildMXPage() {
spot_.min_pix_per_spot = std::lround(v); EmitSpotFinding(); });
// --- Indexing ---
layout->addWidget(new TitleLabel("Indexing", page));
auto *idxGroup = new QGroupBox(page);
auto *idx = new QFormLayout(idxGroup);
auto *idxSection = new CollapsibleSection("Indexing", page);
auto *idx = new QFormLayout();
auto *algo = new QComboBox(page);
algo->addItem("Auto", static_cast<int>(IndexingAlgorithmEnum::Auto));
algo->addItem("FFBIDX (GPU, known cell)", static_cast<int>(IndexingAlgorithmEnum::FFBIDX));
@@ -153,7 +189,8 @@ QWidget *JFJochViewerSettingsDock::BuildMXPage() {
refine->setCurrentIndex(refine->findData(static_cast<int>(indexing_.GetGeomRefinementAlgorithm())));
idx->addRow("Algorithm", algo);
idx->addRow("Refinement", refine);
layout->addWidget(idxGroup);
idxSection->setContentLayout(idx);
layout->addWidget(idxSection);
connect(algo, &QComboBox::currentIndexChanged, this, [this, algo] {
indexing_.Algorithm(static_cast<IndexingAlgorithmEnum>(algo->currentData().toInt()));
EmitSpotFinding();
@@ -163,6 +200,7 @@ QWidget *JFJochViewerSettingsDock::BuildMXPage() {
EmitSpotFinding();
});
layout->addStretch(); // anchor sections to the top so expanding an accordion grows downward
return page;
}
@@ -171,9 +209,8 @@ QWidget *JFJochViewerSettingsDock::BuildAzIntPage() {
auto *layout = new QVBoxLayout(page);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(new TitleLabel("Azimuthal integration", page));
auto *azGroup = new QGroupBox(page);
auto *az = new QFormLayout(azGroup);
auto *azSection = new CollapsibleSection("Azimuthal integration", page);
auto *az = new QFormLayout();
auto *lowQ = new SliderPlusBox(1e-5, 10.0, 0.001, 4, page);
lowQ->setValue(azint_.GetLowQ_recipA());
auto *highQ = new SliderPlusBox(2e-5, 10.0, 0.001, 4, page);
@@ -188,7 +225,8 @@ QWidget *JFJochViewerSettingsDock::BuildAzIntPage() {
az->addRow("High Q [Å⁻¹]", highQ);
az->addRow("Q spacing [Å⁻¹]", spacing);
az->addRow("Azimuthal bins", azimBins);
layout->addWidget(azGroup);
azSection->setContentLayout(az);
layout->addWidget(azSection);
auto emitAz = [=, this] {
azint_.QRange_recipA(static_cast<float>(lowQ->value()), static_cast<float>(highQ->value()));
@@ -202,12 +240,17 @@ QWidget *JFJochViewerSettingsDock::BuildAzIntPage() {
connect(azimBins, &QComboBox::currentIndexChanged, this, [emitAz] { emitAz(); });
// Powder calibration (calibrant rings + geometry refinement) - reuse the existing widget.
layout->addWidget(new TitleLabel("Powder calibration", page));
auto *powderSection = new CollapsibleSection("Powder calibration", page);
auto *powderLayout = new QVBoxLayout();
powderLayout->setContentsMargins(0, 0, 0, 0);
powder_ = new PowderCalibrationWidget(page);
connect(powder_, &PowderCalibrationWidget::findBeamCenter, this, &JFJochViewerSettingsDock::findBeamCenter);
connect(powder_, &PowderCalibrationWidget::ringsFromCalibration, this, &JFJochViewerSettingsDock::ringsFromCalibration);
layout->addWidget(powder_);
powderLayout->addWidget(powder_);
powderSection->setContentLayout(powderLayout);
layout->addWidget(powderSection);
layout->addStretch(); // anchor sections to the top so expanding an accordion grows downward
return page;
}
@@ -222,6 +265,8 @@ void JFJochViewerSettingsDock::EmitExperiment() {
experiment_.DetectorDistance_mm(static_cast<float>(distance_->value()));
experiment_.BeamX_pxl(static_cast<float>(beamX_->value()));
experiment_.BeamY_pxl(static_cast<float>(beamY_->value()));
experiment_.PoniRot1_rad(static_cast<float>(rot1_->value() * PI / 180.0));
experiment_.PoniRot2_rad(static_cast<float>(rot2_->value() * PI / 180.0));
if (cellKnown_->isChecked()) {
experiment_.SetUnitCell(UnitCell{
static_cast<float>(cellA_->value()), static_cast<float>(cellB_->value()),
@@ -243,6 +288,8 @@ void JFJochViewerSettingsDock::RefreshGeometryFields() {
distance_->setValue(experiment_.GetDetectorDistance_mm());
beamX_->setValue(experiment_.GetBeamX_pxl());
beamY_->setValue(experiment_.GetBeamY_pxl());
rot1_->setValue(experiment_.GetPoniRot1_rad() * 180.0 / PI);
rot2_->setValue(experiment_.GetPoniRot2_rad() * 180.0 / PI);
const auto cell = experiment_.GetUnitCell();
QSignalBlocker blockKnown(cellKnown_);
@@ -254,6 +301,25 @@ void JFJochViewerSettingsDock::RefreshGeometryFields() {
cellAlpha_->setValue(cell->alpha); cellBeta_->setValue(cell->beta); cellGamma_->setValue(cell->gamma);
spaceGroup_->setValue(experiment_.GetSpaceGroupNumber().value_or(0));
}
UpdateSpaceGroupName();
}
void JFJochViewerSettingsDock::UpdateSpaceGroupName() {
if (!cellKnown_->isChecked()) {
spaceGroupName_->setText("");
return;
}
const int n = static_cast<int>(std::lround(spaceGroup_->value()));
if (n >= 1 && n <= 230) {
try {
const auto &sg = gemmi::get_spacegroup_by_number(n); // HermannMauguin short symbol
spaceGroupName_->setText(QString::fromStdString(sg.short_name()));
} catch (...) {
spaceGroupName_->setText("invalid");
}
} else {
spaceGroupName_->setText(n == 0 ? "" : "invalid");
}
}
void JFJochViewerSettingsDock::datasetLoaded(std::shared_ptr<const JFJochReaderDataset> dataset) {
+8 -1
View File
@@ -16,6 +16,7 @@
class QStackedWidget;
class QCheckBox;
class QComboBox;
class QLabel;
class SliderPlusBox;
class NumberLineEdit;
class PowderCalibrationWidget;
@@ -48,21 +49,27 @@ private:
bool have_experiment_ = false; // geometry edits only take effect once a dataset is loaded
int64_t max_spots_ = 1000;
// MX geometry + crystal fields
// Geometry fields (shared by both MX and AzInt, since both need the same geometry)
NumberLineEdit *energy_ = nullptr;
NumberLineEdit *distance_ = nullptr;
NumberLineEdit *beamX_ = nullptr;
NumberLineEdit *beamY_ = nullptr;
NumberLineEdit *rot1_ = nullptr; // detector tilt (PONI rot1), deg
NumberLineEdit *rot2_ = nullptr; // detector tilt (PONI rot2), deg
// Crystal fields
QCheckBox *cellKnown_ = nullptr;
NumberLineEdit *cellA_ = nullptr, *cellB_ = nullptr, *cellC_ = nullptr;
NumberLineEdit *cellAlpha_ = nullptr, *cellBeta_ = nullptr, *cellGamma_ = nullptr;
NumberLineEdit *spaceGroup_ = nullptr;
QLabel *spaceGroupName_ = nullptr; // resolved HermannMauguin symbol
PowderCalibrationWidget *powder_ = nullptr;
QWidget *BuildGeometrySection();
QWidget *BuildMXPage();
QWidget *BuildAzIntPage();
void EmitSpotFinding();
void EmitExperiment();
void RefreshGeometryFields();
void UpdateSpaceGroupName();
};