void DrauiiMultiSelect::AddItem(const QString &text, const QString &colorName, BorderType type)
{
auto *item = new QListWidgetItem(listWidget);
item->setFlags(item->flags() & ~Qt::ItemIsSelectable);

auto *widget = new QWidget(listWidget);
auto *layout = new QHBoxLayout(widget);
layout->setContentsMargins(5, 0, 5, 0); // 5: 设置左右边距; 0: 设置上下边距
layout->setSpacing(6); // 6: 设置间距

auto *checkBox = new QCheckBox();
checkBox->setChecked(false);
checkBox->setProperty("itemText", text);
checkBox->setProperty("borderType", type);

auto *labelColor = new QLabel();
const int labelSize = 16;
labelColor->setFixedSize(labelSize, labelSize);
QString borderStyle = (type == DOTTED_LINE) ? "dotted" : "solid";
QString style = QString("QLabel { border: 2px %1 %2;}")
.arg(borderStyle).arg(colorName);
labelColor->setStyleSheet(style);

auto *labelText = new QLabel(text);
labelText->setStyleSheet("font-size: 12px; color: palette(text);");

layout->addWidget(checkBox);
layout->addWidget(labelColor);
layout->addWidget(labelText);
layout->addStretch();
listWidget->setItemWidget(item, widget);
(void)connect(checkBox, &QCheckBox::stateChanged, this, &DrauiiMultiSelect::StateChanged);
}

void DrauiiMultiSelect::StateChanged(int state)
{
auto *checkBox = qobject_cast<QCheckBox*>(sender());
if (!checkBox) {
return;
}
QString text = checkBox->property("itemText").toString();
bool checked = (state == Qt::Checked);
emit ItemToggled(text, checked);
}

void DrauiiMultiSelect::SetAllChecked(bool checked, BorderType type)
{
for (int i = 0; i < listWidget->count(); ++i) {
QListWidgetItem *item = listWidget->item(i);
auto *widget = listWidget->itemWidget(item);
if (!widget) {
continue;
}
auto *checkBox = widget->findChild<QCheckBox*>();
if (checkBox) {
auto borderType = static_cast<BorderType>(checkBox->property("borderType").toInt());
if (type == borderType) {
checkBox->setChecked(checked);
}
}
}
}
}


===== ./src/plots/DrauiiNilsPlotView.cpp =====
/*
* Copyright (c) SiCARRIER Technologies Co., Ltd. 2026-2026. All rights reserved.
* Created: 2026/01/06
*/

#include <XY_PushButton.h>
#include <XY_LineEdit.h>
#include <XY_Fonts.h>
#include <GetQssFile.h>
#include <QRegExpValidator>
#include <QProcessEnvironment>
#include <QSlider>
#include <iostream>
#include <ostream>
#include <thread>
#include "ui_DrauiiNilsPlotView.h"
#include "DrauiiNilsPlotView.h"

using namespace commonWidget;

namespace Mc::Drauii::View {

namespace {
constexpr int NUM_MULTIPLE = 100;
constexpr int NUM_OFFSET = 10;
constexpr int NUM_MAX_VAL_SLIDER = 300;
}

DrauiiNilsPlotView::DrauiiNilsPlotView(QWidget *parent)
: QWidget(parent), ui(new Ui::DrauiiNilsPlotView)
{
ui->setupUi(this);
InitStyle();

ui->horizontalSlider->setRange(0, NUM_MAX_VAL_SLIDER);
ui->horizontalSlider->setSingleStep(1);
ui->horizontalSlider->setValue(0);
ui->lineEdit_slider->setText(QString::number(0, 'f', 1));

(void)connect(ui->horizontalSlider, &QSlider::valueChanged, this, &DrauiiNilsPlotView::OnSliderValueChanged);
(void)connect(ui->btn_sliderAdd, &XY_PushButton::clicked, this, &DrauiiNilsPlotView::OnBtnSilderAdd);
(void)connect(ui->btn_sliderSub, &XY_PushButton::clicked, this, &DrauiiNilsPlotView::OnBtnSilderSub);
(void)connect(ui->lineEdit_slider, &QLineEdit::returnPressed, this, &DrauiiNilsPlotView::OnLineEditReturnPressed);
(void)connect(ui->widgetChart, &DrauiiDefRefCurveView::SingleTipLineChange, this, &DrauiiNilsPlotView::ReciveSingleTipLineChanged);
(void)connect(ui->lineEdit_slider, &QLineEdit::textChanged, this, &DrauiiNilsPlotView::OnSilderValueChange);
}

DrauiiNilsPlotView::~DrauiiNilsPlotView()
{
delete ui;
}

void DrauiiNilsPlotView::InitStyle()
{
QString env = QProcessEnvironment::systemEnvironment().value("XY_PATH");
QString lineEditPath = env + "/include/qtcom/qss/XY_LineEdit.qss";
ui->lineEdit_slider->setAlignment(Qt::AlignLeft);
ui->lineEdit_slider->setFont(QFontStyles::QFontRegular12());
QRegExp regExp("^(?:[0-2](?:\\.\\d?)?|3(?:\\.0?)?)$");
ui->lineEdit_slider->setValidator(new QRegExpValidator(regExp, this));
}

void DrauiiNilsPlotView::OnSliderValueChanged(int value)
{
double slider = (1.0 * value) / NUM_MULTIPLE;
ui->lineEdit_slider->setText(QString::number(slider, 'f', 1));
SendSliderValueChanged(slider);
}

void DrauiiNilsPlotView::ReciveSingleTipLineChanged(double value)
{
ui->lineEdit_slider->setText(QString::number(value, 'f', 1));
int val = static_cast<int>(value * NUM_MULTIPLE);
ui->horizontalSlider->blockSignals(true);
ui->horizontalSlider->setValue(val);
ui->horizontalSlider->blockSignals(false);
}

void DrauiiNilsPlotView::OnSilderValueChange()
{
double value = ui->lineEdit_slider->text().toDouble();
std::vector<LineSeriesDataSt> lineSeriesData {};
LineSeriesDataSt lineDefSt {};
LineSeriesDataSt lineRefSt {};
QList<QPointF> ptsDef;
QList<QPointF> ptsRef;
for (const auto &item : m_lineSeriesData) {
auto& targetList = (item.type == DEF_CURVE_TYPE) ? ptsDef : ptsRef;
for (const auto& point : item.points) {
if (qFuzzyCompare(value, point.x())) {
targetList.append(QPointF(item.index, point.y()));
break;
}
}
}
if (ptsDef.empty() || ptsRef.empty()) {
return;
}
lineDefSt.index = 0;
lineDefSt.type = DEF_CURVE_TYPE;
lineDefSt.points = ptsDef;
lineRefSt.index = 0;
lineRefSt.type = REF_CURVE_TYPE;
lineRefSt.points = ptsRef;

lineSeriesData.push_back(lineDefSt);
lineSeriesData.push_back(lineRefSt);
ui->widgetChartSlider->RecivelineSeriesData(lineSeriesData);
}

void DrauiiNilsPlotView::OnLineEditReturnPressed()
{
double value = ui->lineEdit_slider->text().toDouble();
int val = static_cast<int>(value * NUM_MULTIPLE);
ui->horizontalSlider->setValue(val);
}

void DrauiiNilsPlotView::OnBtnSilderAdd()
{
int val = ui->horizontalSlider->value() + NUM_OFFSET;
ui->horizontalSlider->setValue(val);
}

void DrauiiNilsPlotView::OnBtnSilderSub()
{
int val = ui->horizontalSlider->value() - NUM_OFFSET;
ui->horizontalSlider->setValue(val);
}

void DrauiiNilsPlotView::SendSliderValueChanged(double value)
{
DRAUII_LOG_DEBUG() << "Send Slider value " << value;
ui->widgetChart->SetTipLineSinglePosition(value);
}

void DrauiiNilsPlotView::UpdateNilsData(const std::vector<LineSeriesDataSt>& lineSeriesData)
{
m_lineSeriesData = lineSeriesData;
ViewDataSt st;
st.textTitleActive = false;
st.nameAxisX = "Pixels";
st.nameAxisY = "NILS";
st.checkType = VERTICAL_CHECK_TYPE;
st.tipType = TIP_LINE_SINGLE;
ui->widgetChart->InitDrauiiDefRefCurveView(st);
UpdateNilsSliderData();
ui->widgetChart->RecivelineSeriesData(lineSeriesData);
UpdateSliderRange();
}

void DrauiiNilsPlotView::UpdateNilsSliderData()
{
ViewDataSt st;
st.nameAxisX = "Defocus";
st.nameAxisY = "NILS";
st.textTitleActive = false;
st.checkType = HORIZONTAL_CHECK_TYPE;
st.tipType = TIP_LINE_NONE;
ui->widgetChartSlider->InitDrauiiDefRefCurveView(st);
}

void DrauiiNilsPlotView::UpdateSliderRange()
{
double xMin = ui->widgetChart->GetAxisXMin();
double xMax = ui->widgetChart->GetAxisXMax();

int sliderMin = static_cast<int>(xMin * NUM_MULTIPLE);
int sliderMax = static_cast<int>(xMax * NUM_MULTIPLE);

ui->horizontalSlider->setRange(sliderMin, sliderMax);
if (sliderMax - sliderMin > 0) {
ui->horizontalSlider->setSingleStep((sliderMax - sliderMin) / 100); // slider is split 100
}
ui->planeSliderLabel->setText(QString("Focal Plane Slider [%1~%2]").arg(xMin).arg(xMax));
}
}


===== ./src/pw/DrauiiPwBossungLegend.cpp =====
/*
* Copyright (c) SiCARRIER Technologies Co., Ltd. 2026-2026. All rights reserved.
* Created: 2026/04/01
*/

#include "DrauiiPwBossungLegend.h"

namespace Mc::Drauii::View {

DrauiiPwBossungLegend::DrauiiPwBossungLegend(QWidget* parent)
: QWidget(parent)
{
m_checkBox = new commonWidget::XY_CheckBox(this);
m_checkBox->IndicatorResizeByRatio(26); // 26 大小

m_labelColor = new QLabel(this);
m_labelColor->setFixedSize(20, 20); // 20 大小

m_labelValue = new QLabel(this);
m_labelValue->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
m_labelValue->setStyleSheet(
"font-family: HarmonyOS Sans;"
"font-size: 16px;"
);

auto layout = new QHBoxLayout(this);
layout->setContentsMargins(2, 2, 4, 2); // 2 4,间隙
layout->setSpacing(2); // 2 空白

layout->addWidget(m_checkBox);
layout->addWidget(m_labelColor);
layout->addSpacing(3); // 3 空白
layout->addWidget(m_labelValue);
layout->addStretch();

connect(m_checkBox, &QCheckBox::toggled, this, &DrauiiPwBossungLegend::SigCheckedChanged);
}

void DrauiiPwBossungLegend::SetLabelColor(const QColor& color, Model::PwCurveType type)
{
if (type == Model::PwCurveType::Def) {
m_labelColor->setStyleSheet(
QString(
"background-color:white;"
"border:2px dashed %1;"
).arg(color.name()));
} else {
m_labelColor->setStyleSheet(
QString(
"background-color:%1;"
"border:none;"
"border-radius:2px;"
).arg(color.name()));
}
}

void DrauiiPwBossungLegend::SetText(const QString& text)
{
m_labelValue->setText(text);
}

void DrauiiPwBossungLegend::SetChecked(bool checked)
{
m_checkBox->setChecked(checked);
}

bool DrauiiPwBossungLegend::IsChecked() const
{
return m_checkBox->isChecked();
}

}


===== ./src/pw/DrauiiPwBossungPlot.cpp =====
/*
* Copyright (c) SiCARRIER Technologies Co., Ltd. 2026-2026. All rights reserved.
* Created: 2026/04/01
*/
#include "DrauiiPwBossungPlot.h"

#include <QComboBox>
#include <QPainter>
#include <QPalette>
#include <QPainterPath>
#include <QPen>

#include "DrauiiLog.h"
#include "DrauiiUtil.h"
#include "StyleHelper.h"

#include "ui_DrauiiPwBossungPlot.h"

using namespace Mc::Drauii::View;

namespace Mc::Drauii::View {

DrauiiPwBossungPlot::DrauiiPwBossungPlot(QWidget* parent)
: QWidget(parent), ui(new Ui::DrauiiPwBossungPlot)
{
ui->setupUi(this);

m_xAxisTitle = "Defocus(nm)";
m_yAxisTitle = "CD";
}

DrauiiPwBossungPlot::~DrauiiPwBossungPlot()
{
delete ui;
}

void DrauiiPwBossungPlot::resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);

m_drawRect = QRectF(m_leftMargin, m_topMargin,
width() - m_leftMargin - m_rightMargin,
height() - m_topMargin - m_bottomMargin
);
}

void DrauiiPwBossungPlot::paintEvent(QPaintEvent* event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);

DrawGrid(painter);
DrawAxis(painter);

if (m_vecCurve.isEmpty()) {
DRAUII_LOG_WARN() << "no curves found";
return;
}

DRAUII_LOG_DEBUG() << m_vecCurve.size();
DrawCurve(painter);
}

void DrauiiPwBossungPlot::BuildBossungCurve(const Model::ExecuteDefocusExposureMatrixSolvingRsp& rsp, int index)
{
auto convert = [&](const QList<Model::BossungCurveWithSpecialAxisMode>& list, Model::PwCurveType type) -> QVector<BossungCurve> {
QVector<BossungCurve> vecCurve;
int idx = 0; // 每组颜色相同
for (const auto& item: list) {
BossungCurve curve;
for (const auto& pt: item.curveCoord) {
QPointF newPt(DrauiiUtil::M2Nm(pt.x), DrauiiUtil::M2Nm(pt.y));
curve.vecPoint.append(newPt);
}

for (const auto& pt: item.curveCoordRaw) {
QPointF newPt(DrauiiUtil::M2Nm(pt.x), DrauiiUtil::M2Nm(pt.y));
curve.vecPointRaw.append(newPt);
}

curve.type = type;
curve.show = true;
curve.labelData = QString::asprintf("%#.4g", item.curveLabelData);
curve.color = DrauiiUtil::GetColor(idx);
if (type == Model::PwCurveType::Def) {
curve.style = Qt::DashLine;
} else {
curve.style = Qt::SolidLine;
}

curve.width = 1;

vecCurve.append(curve);
++idx;
}
return vecCurve;
};

m_mapAllCurve.clear();
m_mapAllCurve[Model::PwCurveType::Def].defocusVsCd = convert(rsp.defBossungCurve.defocusVsCd, Model::PwCurveType::Def);
m_mapAllCurve[Model::PwCurveType::Def].cdVsDefocus = convert(rsp.defBossungCurve.cdVsDefocus, Model::PwCurveType::Def);
m_mapAllCurve[Model::PwCurveType::Def].exposureVsCd = convert(rsp.defBossungCurve.exposureVsCd, Model::PwCurveType::Def);
m_mapAllCurve[Model::PwCurveType::Def].cdVsExposure = convert(rsp.defBossungCurve.cdVsExposure, Model::PwCurveType::Def);

m_mapAllCurve[Model::PwCurveType::Ref].defocusVsCd = convert(rsp.refBossungCurve.defocusVsCd, Model::PwCurveType::Ref);
m_mapAllCurve[Model::PwCurveType::Ref].cdVsDefocus = convert(rsp.refBossungCurve.cdVsDefocus, Model::PwCurveType::Ref);
m_mapAllCurve[Model::PwCurveType::Ref].exposureVsCd = convert(rsp.refBossungCurve.exposureVsCd, Model::PwCurveType::Ref);
m_mapAllCurve[Model::PwCurveType::Ref].cdVsExposure = convert(rsp.refBossungCurve.cdVsExposure, Model::PwCurveType::Ref);

ChangeBossungCurve(index);
}

bool DrauiiPwBossungPlot::ChangeBossungCurve(int index)
{
if (m_mapAllCurve.size() < 2) { // 2为元素个数
DRAUII_LOG_WARN() << "size=" << m_mapAllCurve.size();

ChangeAxisTitle(index); // 无数据
update();
return false;
}

switch (index) {
case 0:
m_vecDefCurve = m_mapAllCurve[Model::PwCurveType::Def].defocusVsCd;
m_vecRefCurve = m_mapAllCurve[Model::PwCurveType::Ref].defocusVsCd;
break;
case 1:
m_vecDefCurve = m_mapAllCurve[Model::PwCurveType::Def].cdVsDefocus;
m_vecRefCurve = m_mapAllCurve[Model::PwCurveType::Ref].cdVsDefocus;
break;
case 2: // 下拉框第2个
m_vecDefCurve = m_mapAllCurve[Model::PwCurveType::Def].exposureVsCd;
m_vecRefCurve = m_mapAllCurve[Model::PwCurveType::Ref].exposureVsCd;
break;
case 3: // 下拉框第3个
m_vecDefCurve = m_mapAllCurve[Model::PwCurveType::Def].cdVsExposure;
m_vecRefCurve = m_mapAllCurve[Model::PwCurveType::Ref].cdVsExposure;
break;
default:
DRAUII_LOG_WARN() << "invalid curve index";
return false;
}

m_vecCurve.clear();
m_vecCurve += m_vecDefCurve;
m_vecCurve += m_vecRefCurve;

ChangeAxisTitle(index);
CalcWorldRect();

update();
return true;
}

posted on 2026-06-27 15:08  maxweii  阅读(0)  评论(0)    收藏  举报