diff --git a/HPPA/HPPA.cpp b/HPPA/HPPA.cpp index a15a30a..27df1cf 100644 --- a/HPPA/HPPA.cpp +++ b/HPPA/HPPA.cpp @@ -271,6 +271,10 @@ sizePolicy1.setHeightForWidth(graphicsView_delete->sizePolicy().hasHeightForWidt gridLayout_toc->addWidget(m_layerTreeView, 0, 0, 1, 1); + // Connect TOC selection change to populate ImageControl + connect(m_layerTreeView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + this, SLOT(onLayerTreeSelectionChanged(QItemSelection,QItemSelection))); + dock_layers->setWidget(dock_layersWidgetContents); dock_layersWidgetContents->setStyleSheet(qss_DockWidget_contentWidget); @@ -479,6 +483,10 @@ sizePolicy1.setHeightForWidth(graphicsView_delete->sizePolicy().hasHeightForWidt initControlTabwidget(); m_tabManager = new TabManager(ui.controlTabWidget, this); + // Connect ImageControl band change to re-render (m_ic created in initControlTabwidget) + connect(m_ic, SIGNAL(bandSelectionChanged(double,double,double)), + this, SLOT(onBandSelectionChanged(double,double,double))); + //3D模型看板 ui.mDockWidgetSimulator->setTile(QString::fromLocal8Bit("3D模型")); //ui.mDockWidgetSimulator->show(); @@ -748,6 +756,11 @@ void HPPA::initControlTabwidget() connect(m_tmc, SIGNAL(sequenceComplete()), this, SLOT(onsequenceComplete())); m_tmc->setWindowFlags(Qt::Widget); ui.controlTabWidget->addTab(m_tmc, QString::fromLocal8Bit("2轴控制")); + + + // Connect ImageControl band change to re-render (m_ic created in initControlTabwidget) + connect(m_ic, SIGNAL(bandSelectionChanged(double,double,double)), + this, SLOT(onBandSelectionChanged(double,double,double))); } void HPPA::recordFromRobotArm(int fileCounter) @@ -839,7 +852,7 @@ void HPPA::createMoveplatformActionGroup() } else if (lastSelectedAction == "mAction_RobotArm") { - ui.mAction_RobotArm->setChecked(true); + ui.mAction_RobotArm->setChecked(true); } else if (lastSelectedAction == "mAction_1AxisMotor") { @@ -1014,8 +1027,8 @@ void HPPA::createScenarioActionGroup() } else if (lastSelectedAction == "mActionPlantPhenotypeScenario") { - ui.mActionPlantPhenotypeScenario->setChecked(true); - ui.mActionPlantPhenotypeScenario->trigger(); + ui.mActionPlantPhenotypeScenario->setChecked(true); + ui.mActionPlantPhenotypeScenario->trigger(); } } @@ -1771,7 +1784,7 @@ void HPPA::onReference() { QMessageBox msgBox; msgBox.setText(QString::fromLocal8Bit("请确保白板放置正确!")); - msgBox.exec(); + msgBox.exec(); QAction* checked = moveplatformActionGroup->checkedAction(); QString checkedName = checked->objectName(); @@ -2000,3 +2013,69 @@ void HPPA::onLayerCreatedFromFile(const QString& baseName, const QString& filePa qDebug() << "LayerFileCreated -> created layer:" << baseName << "path:" << filePath << "index:" << fileIndex; } + +void HPPA::onLayerTreeSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected) +{ + Q_UNUSED(deselected); + + if (selected.indexes().isEmpty()) { + m_ic->setActiveLayer(nullptr); + return; + } + + QModelIndex idx = selected.indexes().first(); + if (!idx.isValid()) { + m_ic->setActiveLayer(nullptr); + return; + } + + LayerTreeNode* node = static_cast(idx.internalPointer()); + if (!node || node->type() != LayerTreeNode::Type::Layer) { + m_ic->setActiveLayer(nullptr); + return; + } + + auto* layerNode = static_cast(node); + MapLayer* mapLayer = layerNode->mapLayer(); + if (!mapLayer || mapLayer->layerType() != MapLayer::LayerType::Raster) { + m_ic->setActiveLayer(nullptr); + return; + } + + RasterLayer* rl = static_cast(mapLayer); + m_ic->setActiveLayer(rl); + + // Also switch to the corresponding tab in the image viewer + if (m_MapLayerStore && m_imageViewerTabWidget) { + QWidget* widget = m_MapLayerStore->widgetForLayer(mapLayer); + if (widget) { + int tabIndex = m_imageViewerTabWidget->indexOf(widget); + if (tabIndex >= 0) { + m_imageViewerTabWidget->setCurrentIndex(tabIndex); + } + } + } +} + +void HPPA::onBandSelectionChanged(double rWave, double gWave, double bWave) +{ + RasterLayer* rl = m_ic->activeLayer(); + if (!rl) return; + + // Find the Mapcavas widget associated with this layer and re-render + if (!m_MapLayerStore) return; + + QWidget* container = m_MapLayerStore->widgetForLayer(rl); + if (!container) return; + + QList mapcavas = container->findChildren(); + if (mapcavas.isEmpty()) return; + + RasterLayer::RenderParams params = rl->currentRenderParams(); + params.rWave = rWave; + params.gWave = gWave; + params.bWave = bWave; + rl->setCurrentRenderParams(params); + + mapcavas[0]->freshmap(params); +} diff --git a/HPPA/HPPA.h b/HPPA/HPPA.h index 05b8ae2..03f983f 100644 --- a/HPPA/HPPA.h +++ b/HPPA/HPPA.h @@ -19,6 +19,7 @@ #include #include #include +#include #include "ui_HPPA.h" #include "resononImager.h" @@ -335,6 +336,8 @@ public Q_SLOTS: void removeLayerByTreeIndex(); void removeAllLayersInRasterGroup(); + void onLayerTreeSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected); + void onBandSelectionChanged(double rWave, double gWave, double bWave); signals: void StartFocusSignal(); void StartRecordSignal(); diff --git a/HPPA/imageControl.cpp b/HPPA/imageControl.cpp index ccd101f..4afc784 100644 --- a/HPPA/imageControl.cpp +++ b/HPPA/imageControl.cpp @@ -1,12 +1,186 @@ #include "imageControl.h" +#include "RasterLayer.h" ImageControl::ImageControl(QWidget* parent) : QDialog(parent) { ui.setupUi(this); + // Connect spinboxes + connect(ui.spinRed, QOverload::of(&QDoubleSpinBox::valueChanged), this, &ImageControl::onSpinRedChanged); + connect(ui.spinGreen, QOverload::of(&QDoubleSpinBox::valueChanged), this, &ImageControl::onSpinGreenChanged); + connect(ui.spinBlue, QOverload::of(&QDoubleSpinBox::valueChanged), this, &ImageControl::onSpinBlueChanged); + + // Connect sliders + connect(ui.sliderRed, &QSlider::valueChanged, this, &ImageControl::onSliderRedChanged); + connect(ui.sliderGreen, &QSlider::valueChanged, this, &ImageControl::onSliderGreenChanged); + connect(ui.sliderBlue, &QSlider::valueChanged, this, &ImageControl::onSliderBlueChanged); + + // Connect preset buttons + connect(ui.btnTrueColor, &QPushButton::clicked, this, &ImageControl::onTrueColorClicked); + connect(ui.btnColorInfrared, &QPushButton::clicked, this, &ImageControl::onColorInfraredClicked); } ImageControl::~ImageControl() { +} + +void ImageControl::setActiveLayer(RasterLayer* layer) +{ + m_activeLayer = layer; + + if (!layer) { + setEnabled(false); + return; + } + setEnabled(true); + + // Get wavelength range from the layer + double minW = 374.5, maxW = 948.1; + if (layer->wavelengthRange(minW, maxW)) { + m_minWave = minW; + m_maxWave = maxW; + } + + blockAllSignals(true); + + // Configure spinbox ranges + ui.spinRed->setMinimum(m_minWave); + ui.spinRed->setMaximum(m_maxWave); + ui.spinGreen->setMinimum(m_minWave); + ui.spinGreen->setMaximum(m_maxWave); + ui.spinBlue->setMinimum(m_minWave); + ui.spinBlue->setMaximum(m_maxWave); + + // Configure slider ranges (integer, multiply by 10 for 0.1 nm resolution) + int sliderMin = static_cast(m_minWave * 10.0); + int sliderMax = static_cast(m_maxWave * 10.0); + ui.sliderRed->setMinimum(sliderMin); + ui.sliderRed->setMaximum(sliderMax); + ui.sliderGreen->setMinimum(sliderMin); + ui.sliderGreen->setMaximum(sliderMax); + ui.sliderBlue->setMinimum(sliderMin); + ui.sliderBlue->setMaximum(sliderMax); + + // Set current values from layer's render params + auto params = layer->currentRenderParams(); + ui.spinRed->setValue(params.rWave); + ui.spinGreen->setValue(params.gWave); + ui.spinBlue->setValue(params.bWave); + + ui.sliderRed->setValue(static_cast(params.rWave * 10.0)); + ui.sliderGreen->setValue(static_cast(params.gWave * 10.0)); + ui.sliderBlue->setValue(static_cast(params.bWave * 10.0)); + + blockAllSignals(false); +} + +RasterLayer* ImageControl::activeLayer() const +{ + return m_activeLayer; +} + +void ImageControl::onSpinRedChanged(double val) +{ + ui.sliderRed->blockSignals(true); + ui.sliderRed->setValue(static_cast(val * 10.0)); + ui.sliderRed->blockSignals(false); + emitBandChange(); +} + +void ImageControl::onSpinGreenChanged(double val) +{ + ui.sliderGreen->blockSignals(true); + ui.sliderGreen->setValue(static_cast(val * 10.0)); + ui.sliderGreen->blockSignals(false); + emitBandChange(); +} + +void ImageControl::onSpinBlueChanged(double val) +{ + ui.sliderBlue->blockSignals(true); + ui.sliderBlue->setValue(static_cast(val * 10.0)); + ui.sliderBlue->blockSignals(false); + emitBandChange(); +} + +void ImageControl::onSliderRedChanged(int val) +{ + double wv = val / 10.0; + ui.spinRed->blockSignals(true); + ui.spinRed->setValue(wv); + ui.spinRed->blockSignals(false); + emitBandChange(); +} + +void ImageControl::onSliderGreenChanged(int val) +{ + double wv = val / 10.0; + ui.spinGreen->blockSignals(true); + ui.spinGreen->setValue(wv); + ui.spinGreen->blockSignals(false); + emitBandChange(); +} + +void ImageControl::onSliderBlueChanged(int val) +{ + double wv = val / 10.0; + ui.spinBlue->blockSignals(true); + ui.spinBlue->setValue(wv); + ui.spinBlue->blockSignals(false); + emitBandChange(); +} + +void ImageControl::onTrueColorClicked() +{ + blockAllSignals(true); + ui.spinRed->setValue(665.0); + ui.spinGreen->setValue(560.0); + ui.spinBlue->setValue(490.0); + ui.sliderRed->setValue(static_cast(665.0 * 10.0)); + ui.sliderGreen->setValue(static_cast(560.0 * 10.0)); + ui.sliderBlue->setValue(static_cast(490.0 * 10.0)); + blockAllSignals(false); + emitBandChange(); +} + +void ImageControl::onColorInfraredClicked() +{ + blockAllSignals(true); + ui.spinRed->setValue(800.0); + ui.spinGreen->setValue(665.0); + ui.spinBlue->setValue(560.0); + ui.sliderRed->setValue(static_cast(800.0 * 10.0)); + ui.sliderGreen->setValue(static_cast(665.0 * 10.0)); + ui.sliderBlue->setValue(static_cast(560.0 * 10.0)); + blockAllSignals(false); + emitBandChange(); +} + +void ImageControl::emitBandChange() +{ + double r = ui.spinRed->value(); + double g = ui.spinGreen->value(); + double b = ui.spinBlue->value(); + + // Update active layer's stored render params + if (m_activeLayer) { + auto params = m_activeLayer->currentRenderParams(); + params.rWave = r; + params.gWave = g; + params.bWave = b; + m_activeLayer->setCurrentRenderParams(params); + } + + emit bandSelectionChanged(r, g, b); +} + +void ImageControl::blockAllSignals(bool block) +{ + ui.spinRed->blockSignals(block); + ui.spinGreen->blockSignals(block); + ui.spinBlue->blockSignals(block); + ui.sliderRed->blockSignals(block); + ui.sliderGreen->blockSignals(block); + ui.sliderBlue->blockSignals(block); } \ No newline at end of file diff --git a/HPPA/imageControl.h b/HPPA/imageControl.h index b36d394..b7d60ba 100644 --- a/HPPA/imageControl.h +++ b/HPPA/imageControl.h @@ -7,6 +7,8 @@ #include "ui_imgControl.h" +class RasterLayer; + class ImageControl : public QDialog { Q_OBJECT @@ -15,9 +17,32 @@ public: ImageControl(QWidget* parent = nullptr); ~ImageControl(); + // Populate controls from a RasterLayer's wavelength info and current render params + void setActiveLayer(RasterLayer* layer); + RasterLayer* activeLayer() const; public Q_SLOTS: +Q_SIGNALS: + // Emitted when user changes any of the R/G/B wavelength values + void bandSelectionChanged(double rWave, double gWave, double bWave); + +private Q_SLOTS: + void onSpinRedChanged(double val); + void onSpinGreenChanged(double val); + void onSpinBlueChanged(double val); + void onSliderRedChanged(int val); + void onSliderGreenChanged(int val); + void onSliderBlueChanged(int val); + void onTrueColorClicked(); + void onColorInfraredClicked(); + private: + void emitBandChange(); + void blockAllSignals(bool block); + Ui::ImageControl ui; + RasterLayer* m_activeLayer = nullptr; + double m_minWave = 374.5; + double m_maxWave = 948.1; };