diff --git a/viewer/JFJochViewerSidePanel.cpp b/viewer/JFJochViewerSidePanel.cpp index b3c60a86..63cca255 100644 --- a/viewer/JFJochViewerSidePanel.cpp +++ b/viewer/JFJochViewerSidePanel.cpp @@ -134,7 +134,6 @@ JFJochViewerSidePanel::JFJochViewerSidePanel(QWidget *parent) : QWidget(parent) image_feature_grid->addLayout(legendLayout, 5, 0, 1, 2); featuresSection->setContentLayout(image_feature_grid); - featuresSection->setExpanded(false); layout->addWidget(featuresSection); auto *ringsSection = new CollapsibleSection("Resolution rings", this); @@ -152,7 +151,6 @@ JFJochViewerSidePanel::JFJochViewerSidePanel(QWidget *parent) : QWidget(parent) 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), @@ -186,7 +184,6 @@ JFJochViewerSidePanel::JFJochViewerSidePanel(QWidget *parent) : QWidget(parent) connect(roi_list, &JFJochViewerROIList::maskFromROI, this, &JFJochViewerSidePanel::maskFromROI); connect(roi_list, &JFJochViewerROIList::roisChanged, this, [this] { roiSection->setExpanded(true); }); roiSection->setContentLayout(roiLayout); - roiSection->setExpanded(false); layout->addWidget(roiSection); layout->addStretch(); diff --git a/viewer/widgets/CollapsibleSection.cpp b/viewer/widgets/CollapsibleSection.cpp index 86748d00..f6060208 100644 --- a/viewer/widgets/CollapsibleSection.cpp +++ b/viewer/widgets/CollapsibleSection.cpp @@ -14,9 +14,8 @@ CollapsibleSection::CollapsibleSection(const QString &title, QWidget *parent) : header_ = new QToolButton(this); header_->setText(title); header_->setCheckable(true); - header_->setChecked(true); header_->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - header_->setArrowType(Qt::DownArrow); + header_->setArrowType(Qt::RightArrow); header_->setCursor(Qt::PointingHandCursor); header_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); header_->setStyleSheet( @@ -25,6 +24,7 @@ CollapsibleSection::CollapsibleSection(const QString &title, QWidget *parent) : " border-left:3px solid #FA7268; border-bottom:1px solid #FA7268; background:transparent; }"); content_ = new QWidget(this); + content_->setVisible(false); v->addWidget(header_); v->addWidget(content_); diff --git a/viewer/widgets/CollapsibleSection.h b/viewer/widgets/CollapsibleSection.h index 5bbf746a..b66720ea 100644 --- a/viewer/widgets/CollapsibleSection.h +++ b/viewer/widgets/CollapsibleSection.h @@ -10,6 +10,7 @@ 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. +// Starts folded, so a panel opens as a list of headers and the user unfolds what they need. class CollapsibleSection : public QWidget { Q_OBJECT public: diff --git a/viewer/widgets/JFJochViewerSettingsDock.cpp b/viewer/widgets/JFJochViewerSettingsDock.cpp index 6bd9ef5c..8a7e52f0 100644 --- a/viewer/widgets/JFJochViewerSettingsDock.cpp +++ b/viewer/widgets/JFJochViewerSettingsDock.cpp @@ -123,17 +123,23 @@ JFJochViewerSettingsDock::JFJochViewerSettingsDock(const SpotFindingSettings &sp auto *stack = new QStackedWidget(this); stack->addWidget(BuildMXPage()); - stack->addWidget(BuildAzIntPage()); + stack->addWidget(new QWidget(stack)); // AzInt: the shared section below is the whole page stack->addWidget(BuildCalibrationPage()); connect(group, &QButtonGroup::idClicked, this, [this, stack](int id) { mode_ = id == 1 ? ProcessMode::AzimuthalIntegration : id == 2 ? ProcessMode::Calibration : ProcessMode::FullAnalysis; stack->setCurrentIndex(id); + azintSection_->setVisible(id != 0); }); - // Geometry is common to both communities, so it lives above the toggle rather than per page. + // Geometry is common to all three, so it lives above the toggle rather than per page. Azimuthal + // integration is common to two of them - a calibration by rings integrates the run in azimuthal + // sectors, and needs the same Q range and spacing - so it is shared the same way and hidden on MX. layout->addLayout(toggleRow); layout->addWidget(BuildGeometrySection()); + azintSection_ = BuildAzIntSection(); + azintSection_->setVisible(false); // MX is the page selected on start + layout->addWidget(azintSection_); layout->addWidget(stack); layout->addStretch(); } @@ -301,7 +307,6 @@ QWidget *JFJochViewerSettingsDock::BuildMXPage() { spot->addRow("Min pixels/spot", minPix); spot->addRow("Max spots/image", maxSpots); spotSection->setContentLayout(spot); - spotSection->setExpanded(false); layout->addWidget(spotSection); connect(snr, &SliderPlusBox::valueChanged, this, [this](double v) { spot_.signal_to_noise_threshold = static_cast(v); EmitSpotFinding(); }); @@ -372,7 +377,6 @@ QWidget *JFJochViewerSettingsDock::BuildMXPage() { idx->addRow("", algoDesc_); idx->addRow("Refinement", refine); idxSection->setContentLayout(idx); - idxSection->setExpanded(false); layout->addWidget(idxSection); connect(algo_, &QComboBox::currentIndexChanged, this, [this] { indexing_.Algorithm(static_cast(algo_->currentData().toInt())); @@ -580,7 +584,6 @@ QWidget *JFJochViewerSettingsDock::BuildReferenceSection() { form->addRow(refSummary_); form->addRow(refWarning_); section->setContentLayout(form); - section->setExpanded(false); // folded on start (only geometry + unit cell start open) connect(refButton_, &QPushButton::clicked, this, [this] { const QString path = QFileDialog::getOpenFileName(this, "Reference MTZ", refPath_, @@ -599,25 +602,21 @@ QWidget *JFJochViewerSettingsDock::BuildReferenceSection() { return section; } -QWidget *JFJochViewerSettingsDock::BuildAzIntPage() { - auto *page = new QWidget(this); - auto *layout = new QVBoxLayout(page); - layout->setContentsMargins(0, 0, 0, 0); - - auto *azSection = new CollapsibleSection("Azimuthal integration", page); +QWidget *JFJochViewerSettingsDock::BuildAzIntSection() { + auto *azSection = new CollapsibleSection("Azimuthal integration", this); auto *az = new QFormLayout(); az->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); - auto *lowQ = new SliderPlusBox(1e-5, 10.0, 0.001, 4, page); + auto *lowQ = new SliderPlusBox(1e-5, 10.0, 0.001, 4, this); lowQ->setValue(azint_.GetLowQ_recipA()); - auto *highQ = new SliderPlusBox(2e-5, 10.0, 0.001, 4, page); + auto *highQ = new SliderPlusBox(2e-5, 10.0, 0.001, 4, this); highQ->setValue(azint_.GetHighQ_recipA()); - auto *autoHighQ = new QCheckBox("To detector edge", page); + auto *autoHighQ = new QCheckBox("To detector edge", this); autoHighQ->setChecked(!azint_.GetRequestedHighQ_recipA().has_value()); autoHighQ->setToolTip("Integrate out to the highest Q the detector reaches. The high-Q value is not " "used while this is on."); - auto *spacing = new SliderPlusBox(1e-5, 1.0, 0.001, 5, page, SliderPlusBox::ScaleType::Logarithmic); + auto *spacing = new SliderPlusBox(1e-5, 1.0, 0.001, 5, this, SliderPlusBox::ScaleType::Logarithmic); spacing->setValue(azint_.GetQSpacing_recipA()); - auto *azimBins = new QComboBox(page); + auto *azimBins = new QComboBox(this); for (int b : {1, 2, 4, 8, 16, 32, 64, 128}) azimBins->addItem(QString::number(b), b); azimBins->setCurrentIndex(azimBins->findData(azint_.GetAzimuthalBinCount())); @@ -627,8 +626,6 @@ QWidget *JFJochViewerSettingsDock::BuildAzIntPage() { az->addRow("Q spacing [Å⁻¹]", spacing); az->addRow("Azimuthal bins", azimBins); azSection->setContentLayout(az); - azSection->setExpanded(false); - layout->addWidget(azSection); auto emitAz = [=, this] { azint_.QRange_recipA(static_cast(lowQ->value()), @@ -648,8 +645,7 @@ QWidget *JFJochViewerSettingsDock::BuildAzIntPage() { }); highQ->setEnabled(!autoHighQ->isChecked()); - layout->addStretch(); // anchor sections to the top so expanding an accordion grows downward - return page; + return azSection; } QWidget *JFJochViewerSettingsDock::BuildCalibrationPage() { @@ -667,22 +663,22 @@ QWidget *JFJochViewerSettingsDock::BuildCalibrationPage() { connect(powder_, &PowderCalibrationWidget::findBeamCenter, this, &JFJochViewerSettingsDock::findBeamCenter); connect(powder_, &PowderCalibrationWidget::ringsFromCalibration, this, &JFJochViewerSettingsDock::ringsFromCalibration); powderLayout->addWidget(powder_); - powderSection->setContentLayout(powderLayout); - layout->addWidget(powderSection); // The rings method reads the ring's position at every azimuth, so the run has to be integrated in - // azimuthal sectors; one sector is a plain radial profile and cannot locate the ring. The bin count - // is the AzInt page's single setting - say here what it is set to rather than duplicating it. + // azimuthal sectors; one sector is a plain radial profile and cannot locate the ring. The sector + // count is the azimuthal-integration section above - say here when it is set too low to fit with. auto *bins = new QLabel(page); bins->setWordWrap(true); bins->setStyleSheet("color: gray;"); - layout->addWidget(bins); + powderLayout->addWidget(bins); + powderSection->setContentLayout(powderLayout); + layout->addWidget(powderSection); + auto refreshBins = [this, bins] { - bins->setText(QStringLiteral("Rings method: azimuthal bins (AzInt page) = %1%2") - .arg(azint_.GetAzimuthalBinCount()) - .arg(azint_.GetAzimuthalBinCount() < 4 - ? QStringLiteral(" — too few to locate a ring; the run will use 32") - : QString())); + bins->setText(azint_.GetAzimuthalBinCount() < 4 + ? QStringLiteral("Rings method: too few azimuthal bins (%1) to locate a ring;" + " the run will use 32.").arg(azint_.GetAzimuthalBinCount()) + : QString()); }; refreshBins(); connect(this, &JFJochViewerSettingsDock::azintChanged, this, [refreshBins] { refreshBins(); }); @@ -765,7 +761,6 @@ QWidget *JFJochViewerSettingsDock::BuildBraggSection() { form->addRow("Radii r1/r2/r3", radii); form->addRow("", trimRow); section->setContentLayout(form); - section->setExpanded(false); // folded on start (only geometry + unit cell start open) auto emitBragg = [=, this] { bragg_.Integrator(gaussian->isChecked() ? IntegratorMode::ProfileGaussian : IntegratorMode::BoxSum); @@ -833,7 +828,6 @@ QWidget *JFJochViewerSettingsDock::BuildScalingSection() { lowResRow->addWidget(lowRes, 1); form->addRow("", lowResRow); section->setContentLayout(form); - section->setExpanded(false); // folded on start (only geometry + unit cell start open) auto emitScaling = [=, this] { scaling_.MergeFriedel(friedel->isChecked()); diff --git a/viewer/widgets/JFJochViewerSettingsDock.h b/viewer/widgets/JFJochViewerSettingsDock.h index fb7f658f..00761a4f 100644 --- a/viewer/widgets/JFJochViewerSettingsDock.h +++ b/viewer/widgets/JFJochViewerSettingsDock.h @@ -133,6 +133,9 @@ private: QString refPath_; PowderCalibrationWidget *powder_ = nullptr; + // Azimuthal integration: one section, shared by the AzInt and Calib pages (a calibration by rings + // integrates the run in azimuthal sectors), so it sits outside the page stack and is hidden on MX. + QWidget *azintSection_ = nullptr; QWidget *BuildGeometrySection(); QWidget *BuildMXPage(); @@ -140,7 +143,7 @@ private: QWidget *BuildBraggSection(); QWidget *BuildScalingSection(); QWidget *BuildReferenceSection(); - QWidget *BuildAzIntPage(); + QWidget *BuildAzIntSection(); QWidget *BuildCalibrationPage(); void SyncMinPix(); void EmitSpotFinding();