// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #include #include #include #include #include #include #include #include "JFJochViewerSidePanel.h" #include "widgets/TitleLabel.h" JFJochViewerSidePanel::JFJochViewerSidePanel(JFJochReader &in_reader, QWidget *parent) : reader(in_reader), QWidget(parent) { setFixedWidth(250); auto layout = new QVBoxLayout(this); layout->addWidget(new TitleLabel("Image statistics", this)); image_stats = new QLabel(); SetImageStats({}); layout->addWidget(image_stats); layout->addWidget(new TitleLabel("Image features", this)); auto spotToggleCheckBox = new QCheckBox("Show spots", this); spotToggleCheckBox->setCheckState(Qt::CheckState::Checked); layout->addWidget(spotToggleCheckBox); // Add checkbox to the grid layout connect(spotToggleCheckBox, &QCheckBox::toggled, this, &JFJochViewerSidePanel::spotsToggled); resRingsCheckBox = new QCheckBox("Show resolution rings", this); resRingsCheckBox->setCheckState(Qt::Checked); layout->addWidget(resRingsCheckBox); autoResRingsCheckBox = new QCheckBox("Resolution rings auto.", this); res_rings_edit = new QLineEdit(this); res_rings_edit->setPlaceholderText("Enter non-negative floats, e.g., 1.0,2.5,3.7"); res_rings_edit->setEnabled(false); // Initially disabled as "Auto Res Rings" is checked by default layout->addWidget(autoResRingsCheckBox); // Add the checkbox to the grid layout layout->addWidget(res_rings_edit); // Add the line edit to the grid layout auto highestPixelsComboBox = new QComboBox(this); highestPixelsComboBox->addItem("0 highest pixels", 0); highestPixelsComboBox->addItem("1 highest pixel", 1); highestPixelsComboBox->addItem("2 highest pixels", 2); highestPixelsComboBox->addItem("3 highest pixels", 3); highestPixelsComboBox->addItem("5 highest pixels", 5); highestPixelsComboBox->addItem("10 highest pixels", 10); highestPixelsComboBox->setCurrentIndex(0); layout->addWidget(highestPixelsComboBox); connect(highestPixelsComboBox, &QComboBox::currentIndexChanged, this, [this, highestPixelsComboBox](int index) { int value = highestPixelsComboBox->itemData(index).toInt(); emit showHighestPixels(value); }); auto saturatedPixelsCheckBox = new QCheckBox("Show saturated pixels", this); layout->addWidget(saturatedPixelsCheckBox); connect(saturatedPixelsCheckBox, &QCheckBox::toggled, this, &JFJochViewerSidePanel::saturatedPixelsToggled); auto colorSelectButton = new QPushButton("Select feature color", this); layout->addWidget(colorSelectButton); connect(colorSelectButton, &QPushButton::clicked, this, [this]() { QColor color = QColorDialog::getColor(Qt::magenta, this, "Select Feature Color"); if (color.isValid()) { emit setFeatureColor(color); } }); auto spotColorSelectButton = new QPushButton("Select spot color", this); layout->addWidget(spotColorSelectButton); connect(spotColorSelectButton, &QPushButton::clicked, this, [this]() { QColor color = QColorDialog::getColor(Qt::green, this, "Select Spot Color"); if (color.isValid()) { emit setSpotColor(color); } }); connect(autoResRingsCheckBox, &QCheckBox::toggled, this, &JFJochViewerSidePanel::enableAutoResRings); connect(res_rings_edit, &QLineEdit::editingFinished, this, &JFJochViewerSidePanel::editingFinished); connect(resRingsCheckBox, &QCheckBox::toggled, this, &JFJochViewerSidePanel::enableResRings); layout->addStretch(); setLayout(layout); // Set the layout to the widget } void JFJochViewerSidePanel::enableAutoResRings(bool input) { res_rings_edit->setEnabled(!input); // Enable line edit only if "Auto Res Rings" is unchecked if (input) { emit autoResRings(); } else { editingFinished(); } } void JFJochViewerSidePanel::SetImageStats(const std::shared_ptr &image) { QString text; if (image != nullptr) { text = "Detector: %1
" "Error pixels: %2
" "Saturated pixels: %3
" "Spots: %4
" "Valid values: %5 - %6"; text = text.arg(QString::fromStdString(image->dataset->detector_name)) .arg(image->error_pixel.size()) .arg(image->saturated_pixel.size()) .arg(image->spots.size()) .arg(image->valid_pixel.begin()->first) .arg(image->valid_pixel.rbegin()->first); } else text="No file loaded



"; image_stats->setText(text); } void JFJochViewerSidePanel::spotsToggled(bool input) { emit showSpots(input); } void JFJochViewerSidePanel::editingFinished() { QString text = res_rings_edit->text(); QStringList stringList = text.split(',', Qt::SkipEmptyParts); QVector manualResRings; bool validInput = true; for (const QString &str: stringList) { bool ok; float value = str.toFloat(&ok); if (ok && value >= 0) { manualResRings.append(value); } else { validInput = false; break; } } if (!validInput) { res_rings_edit->setStyleSheet("border: 1px solid red;"); // Highlight error } else { res_rings_edit->setStyleSheet(""); // Reset to default style emit setResRings(manualResRings); // Update resolution ring vector } } void JFJochViewerSidePanel::loadImage() { auto image = reader.CopyImage(); SetImageStats(image); } void JFJochViewerSidePanel::enableResRings(bool input) { if (!input) { autoResRingsCheckBox->setEnabled(false); res_rings_edit->setEnabled(false); emit setResRings({}); } else { autoResRingsCheckBox->setEnabled(true); enableAutoResRings(autoResRingsCheckBox->isChecked()); } } void JFJochViewerSidePanel::saturatedPixelsToggled(bool input) { emit showSaturatedPixels(input); }