#include "ManualLabelToolWidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "WidgetSettingClass.h" #include "LAMPDataManagerDialog.h" #include #include //#include #include #include #include "QBatchStaticEchoDialog.h" #include "QImageCursorWidget.h" #include #include #include #include "CustomCursorTool.h" #include "qgslayerpropertiesdialog.h" #include "windLayerTreeViewMenuProvider.h" //QgsUnitTypes ManualLabelToolWidget::ManualLabelToolWidget(QWidget* parent) : QMainWindow(parent) { this->init_UI(); } ManualLabelToolWidget::~ManualLabelToolWidget() { } void ManualLabelToolWidget::init_UI() { // 初始大小 { this->setWindowTitle(tr(u8"微波风能分析软件")); // 获取主屏幕的可用区域(不包含任务栏) QRect availableGeometry = QApplication::primaryScreen()->availableGeometry(); // 计算期望的窗口大小,例如屏幕可用区域的80% int width = availableGeometry.width() * 0.8; int height = availableGeometry.height() * 0.8; // 调整窗口大小 resize(width, height); // 可选:将窗口移动到屏幕中央 move(availableGeometry.center() - rect().center()); } { datamanagerDialog = new LampDataManager(this); onshowDatamanagerActionTriggered(); } //地图控制 { // 1. inti map canvas this->map_canvas = new QgsMapCanvas(this); this->setCentralWidget((this->map_canvas)); // 2. map tool pan this->map_tool_pan = new QgsMapToolPan(this->map_canvas); this->map_canvas->setMapTool(this->map_tool_pan); // 关键缓存与渲染配置 map_canvas->setCachingEnabled(true); // 启用缓存,这是实现分块加载效果的关键[citation:6][citation:8] map_canvas->setParallelRenderingEnabled(true); // 启用并行渲染以提高性能[citation:6] // 3. map layer manager this->map_layerTreeView = new QgsLayerTreeView(this); // 4. create map model this->map_layerModel = new QgsLayerTreeModel(QgsProject::instance()->layerTreeRoot(), this); this->map_layerModel->setFlag(QgsLayerTreeModel::AllowNodeRename); // 允许重命名 this->map_layerModel->setFlag(QgsLayerTreeModel::AllowNodeReorder); // 允许调整顺序 this->map_layerModel->setFlag(QgsLayerTreeModel::AllowNodeChangeVisibility); // 允许改变可见性 this->map_layerModel->setFlag(QgsLayerTreeModel::ShowLegendAsTree); // 以树状图显示图例 this->map_layerModel->setAutoCollapseLegendNodes(10); // 自动折叠过多图例项 this->map_layerTreeView->setModel(this->map_layerModel); this->map_layer_Bridge = new QgsLayerTreeMapCanvasBridge(QgsProject::instance()->layerTreeRoot(), this->map_canvas, this); this->layerTreeDock = new QDockWidget(tr(u8"图层管理器"), this); this->layerTreeDock->setWidget(this->map_layerTreeView); layerTreeDock->setWidget(this->map_layerTreeView); layerTreeDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); this->addDockWidget(Qt::LeftDockWidgetArea, this->layerTreeDock); windLayerTreeViewMenuProvider* mLayerTreeViewMenuProvider = new windLayerTreeViewMenuProvider(map_layerTreeView, map_canvas, this); this->map_layerTreeView->setMenuProvider(mLayerTreeViewMenuProvider); } // 状态工具栏 { appStatusBar = this->statusBar(); // 获取或创建状态栏 scaleLabel = new QLabel(tr(u8"比例尺:")); CoordinaryTextLabel = new QLabel(tr(u8"坐标系:")); PointXYLabel = new QLabel(tr(u8"坐标:")); UnitLabel = new QLabel(tr(u8"单位:")); appStatusBar->addPermanentWidget(PointXYLabel); // appStatusBar->addPermanentWidget(scaleLabel); // appStatusBar->addPermanentWidget(UnitLabel); // appStatusBar->addPermanentWidget(CoordinaryTextLabel); // // 连接比例尺变化信号 connect(map_canvas, SIGNAL(scaleChanged(double)), this, SLOT(updateScaleLabel(double))); connect(map_canvas, SIGNAL(xyCoordinates(const QgsPointXY&)), this, SLOT(updateCoordinateLabel(const QgsPointXY&))); connect(map_canvas, SIGNAL(extentsChanged()), this, SLOT(onMapExtentsChanged())); } // 菜单栏 { menubar = this->menuBar(); // 在菜单栏上添加"文件"和"编辑"菜单 fileMenu = menubar->addMenu(tr(u8"文件")); // 向"文件"菜单中添加菜单项(QAction) newAction = fileMenu->addAction(tr(u8"新建")); fileMenu->addSeparator(); // 添加分割线[1,5](@ref) openMenu = fileMenu->addMenu(tr(u8"打开")); openRasterFolderAction = openMenu->addAction(tr(u8"打开影像文件夹")); openRasterAction = openMenu->addAction(tr(u8"打开影像")); openSLCRasterAction = openMenu->addAction(tr(u8"SLC影像")); openLampWindDataAction = openMenu->addAction(tr(u8"风场数据")); // 事件绑定 QObject::connect(this->openRasterAction, SIGNAL(triggered()), this, SLOT(openRaster())); QObject::connect(this->openLampWindDataAction, SIGNAL(triggered()), this->datamanagerDialog, SLOT(openLampWindDataFile())); editMenu = menubar->addMenu(tr(u8"编辑")); SARWindInversionMenu = menubar->addMenu(tr(u8"SAR风场反演")); SARImageImportAction = SARWindInversionMenu->addAction(tr(u8"SAR数据导入")); SARInversionAtion = SARWindInversionMenu->addAction(tr(u8"SAR风场分析工具")); SARInversionResulutShowAtion = SARWindInversionMenu->addAction(tr(u8"风场数据结果展示")); //SARWindAysysMenu = SARWindInversionMenu->addMenu(tr(u8"风场分析")); //SARImageAysysAction = SARWindAysysMenu->addAction(tr(u8"目标时间序列分析")); QObject::connect(SARInversionAtion, SIGNAL(triggered()), this, SLOT(onshowSARInversionAtionTriggered())); } // 图像工具 { datatoolbar = new QToolBar(tr(u8"工具")); showDatamanagerAction = datatoolbar->addAction(tr(u8"数据管理")); mapToolActionGroup = new QActionGroup(this); ZoomInToolbtn = new QAction(tr(u8"放大")); ZoomInToolbtn->setCheckable(true); mapToolActionGroup->addAction(ZoomInToolbtn); ZoomOutToolbtn = new QAction(tr(u8"缩小")); ZoomOutToolbtn->setCheckable(true); mapToolActionGroup->addAction(ZoomOutToolbtn); MapPanToolbtn = new QAction(tr(u8"平移")); MapPanToolbtn->setCheckable(true); MapPanToolbtn->setChecked(true); mapToolActionGroup->addAction(MapPanToolbtn); IdentifyToolbtn = new QAction(tr(u8"识别")); IdentifyToolbtn->setCheckable(true); mapToolActionGroup->addAction(IdentifyToolbtn); cursorAction = new QAction(tr(u8"游标")); cursorAction->setCheckable(true); mapToolActionGroup->addAction(cursorAction); datatoolbar->addAction(ZoomInToolbtn); datatoolbar->addAction(ZoomOutToolbtn); datatoolbar->addAction(MapPanToolbtn); datatoolbar->addAction(cursorAction); m_mapToolPan = new QgsMapToolPan(this->map_canvas); m_mapToolZoomIn = new QgsMapToolZoom(this->map_canvas, false); m_mapToolZoomOut = new QgsMapToolZoom(this->map_canvas, true); m_mapIdentifyToolPan = new QgsMapToolIdentify(this->map_canvas); m_CustomCursorTool = new CustomCursorTool(this->map_canvas); ZoomInToolbtn->setText(u8"放大"); ZoomOutToolbtn->setText(u8"缩小"); MapPanToolbtn->setText(u8"平移"); IdentifyToolbtn->setText(u8"识别"); connect(mapToolActionGroup, &QActionGroup::triggered, this, &ManualLabelToolWidget::onMapToolActionTriggered); //QObject::connect(cursorAction, SIGNAL(triggered()), this, SLOT(onCursorImageToolTriggered())); QObject::connect(showDatamanagerAction, SIGNAL(triggered()), this, SLOT(onshowDatamanagerActionTriggered())); this->addToolBar(Qt::TopToolBarArea, datatoolbar); } // AI标注工具栏 { AiLabelToolBar = new QToolBar(tr(u8"AI标注工具栏"), this); this->addToolBar(Qt::LeftToolBarArea, AiLabelToolBar); } // 检查插件 { QString qgisPrefixPath = WidgetSettingClass::instance().getExeDirectionApplicationPath(); // 3. 显式设置插件目录,确保QGIS能找到动态提供者 QString pluginPath = qgisPrefixPath + "/plugins"; QgsApplication::setPluginPath(pluginPath); // 4. 设置QGIS的共享数据目录(包含proj.db等) QString pkgDataPath = qgisPrefixPath + "/share/qgis"; QgsApplication::setPkgDataPath(pkgDataPath); QgsApplication::initQgis(); QStringList providers = QgsProviderRegistry::instance()->providerList(); qDebug() << u8"已注册的提供者:" << providers; // 检查 "mesh_memory" 或相关的 "mdal" 提供者是否存在 if (providers.contains("mesh_memory")) { qDebug() << u8"'mesh_memory' 提供者可用。"; } else { qDebug() << u8"警告:未找到相关的网格数据提供者。"; } if (providers.contains("mdal")) { qDebug() << u8"'mdal' 提供者可用,它可能包含在 'mdal' 中。"; } else { qDebug() << u8"警告:未找到相关的网格数据提供者。"; } } } void ManualLabelToolWidget::open() { } void ManualLabelToolWidget::openRaster() { QString lastFileDialogPath = WidgetSettingClass::instance().getLastFileDialogPath(); if (lastFileDialogPath.isEmpty()) { lastFileDialogPath = "."; } // 打开影像 // 2. 选择多个文件 QString lampwindPath = QFileDialog::getOpenFileName( this, tr(u8"请选择影像文件"), lastFileDialogPath, tr(LAMPWINDDATAFILEFILTER) ); QString filename = QFileInfo(lampwindPath).fileName(); QgsRasterLayer* rasterLayer = new QgsRasterLayer(lampwindPath, filename); if (!rasterLayer->isValid()) { qDebug() << "Failed to load raster layer!"; // 错误处理 return; } this->AddLayers(rasterLayer); } void ManualLabelToolWidget::updateCoordinateLabel(const QgsPointXY& point) { QString coordText = QString(tr(u8"坐标:X:%1 Y:%2")).arg(QString::number(point.x(), 'f', 2)).arg(QString::number(point.y(), 'f', 2)); PointXYLabel->setText(coordText); } void ManualLabelToolWidget::onMapExtentsChanged() { QgsRectangle currentExtent = map_canvas->extent(); //// 现在你可以使用这个范围信息了,例如: //// 1. 打印范围坐标 //qDebug() << "新范围 - Xmin:" << currentExtent.xMinimum() // << "Ymin:" << currentExtent.yMinimum() // << "Xmax:" << currentExtent.xMaximum() // << "Ymax:" << currentExtent.yMaximum(); } void ManualLabelToolWidget::AddLayers(QgsMapLayer* layer) { if (!layer || !layer->isValid()) { qDebug() << "无效图层,无法添加!"; return; } if (QgsProject::instance()->mapLayers().size() == 0) { // 检查图层是否有效且拥有定义的坐标系 if (layer && layer->isValid() && layer->crs().isValid()) { // 将地图画布的目标坐标系设置为与图层一致 map_canvas->mapSettings().setDestinationCrs(layer->crs()); // 可选:将地图范围缩放至该图层的全范围,提供更好的初始视图 map_canvas->setExtent(layer->extent()); // 刷新画布,使更改生效 map_canvas->refresh(); qDebug() << "图层数量为1,已同步画布坐标系至:" << layer->crs().description(); } } QgsProject::instance()->addMapLayer(layer); } void ManualLabelToolWidget::updateScaleLabel(double scale) { QString scaleText = QString(tr(u8"比例尺:1:%1")).arg(QString::number(scale, 'f', 0)); scaleLabel->setText(scaleText); Qgis::DistanceUnit unit = map_canvas->mapUnits(); QString unitString; if (unit == Qgis::DistanceUnit::Meters) { unitString = tr(u8"米"); } else if (unit == Qgis::DistanceUnit::Degrees) { unitString = tr(u8"度"); } else if (unit == Qgis::DistanceUnit::Feet) { unitString = tr(u8"英尺"); } else { unitString = tr(u8"未知"); } UnitLabel->setText(QString(tr(u8"单位:%1")).arg(unitString)); QgsCoordinateReferenceSystem currentCrs = map_canvas->mapSettings().destinationCrs(); QString description = currentCrs.description(); QString authid = currentCrs.authid(); if (description == "") { CoordinaryTextLabel->setText(QString(tr(u8"坐标系:未知"))); } else { CoordinaryTextLabel->setText(QString(tr(u8"坐标系:%1")).arg(description)); } } void ManualLabelToolWidget::onshowDatamanagerActionTriggered() { if (nullptr == datamanagerDialog) { datamanagerDialog = new LampDataManager(this); } else {} QRect parentGeometry = this->geometry(); QSize dialogSize = datamanagerDialog->size(); // 计算居中位置 int x = parentGeometry.x() + (parentGeometry.width() - dialogSize.width()) / 2; int y = parentGeometry.y() + (parentGeometry.height() - dialogSize.height()) / 2; // 设置对话框位置 datamanagerDialog->move(x, y); datamanagerDialog->show(); datamanagerDialog->raise(); // 确保对话框在最前面 datamanagerDialog->activateWindow(); // 激活对话框获取焦点 } void ManualLabelToolWidget::setupLayerTreeContextMenu() { // 启用图层树视图的默认上下文菜单 this->map_layerTreeView->setMenuProvider(this->map_layerTreeView->menuProvider()); // 或者自定义菜单 this->map_layerTreeView->setContextMenuPolicy(Qt::CustomContextMenu); connect(this->map_layerTreeView, &QgsLayerTreeView::customContextMenuRequested, this, &ManualLabelToolWidget::onLayerTreeContextMenu); } void ManualLabelToolWidget::onLayerTreeContextMenu(const QPoint& pos) { QModelIndex index = map_layerTreeView->indexAt(pos); if (!index.isValid()) return; QgsLayerTreeNode* node = map_layerTreeView->layerTreeModel()->index2node(index); if (!node) return; QMenu* menu = new QMenu(this); if (QgsLayerTree::isLayer(node)) { QgsMapLayer* layer = QgsLayerTree::toLayer(node)->layer(); if (layer) { // 添加属性表菜单项 QAction* attributeTableAction = menu->addAction(tr("打开属性表")); // 添加图层属性菜单项 QAction* layerPropertiesAction = menu->addAction(tr("图层属性")); } } menu->exec(map_layerTreeView->mapToGlobal(pos)); delete menu; } void ManualLabelToolWidget::onshowSARInversionAtionTriggered() { QBatchStaticEchoDialog* d = new QBatchStaticEchoDialog(this); d->show(); } void ManualLabelToolWidget::onMapToolActionTriggered(QAction* action) { if (action == ZoomInToolbtn) { this->map_canvas->setMapTool(m_mapToolZoomIn); } else if (action == ZoomOutToolbtn) { this->map_canvas->setMapTool(m_mapToolZoomOut); } else if (action == MapPanToolbtn) { this->map_canvas->setMapTool(m_mapToolPan); } else if (action == IdentifyToolbtn) { this->map_canvas->setMapTool(m_mapIdentifyToolPan); } else if (action == cursorAction) { this->map_canvas->setMapTool(m_CustomCursorTool); if (!cursorInfoDialog) { cursorInfoDialog = new QImageCursorWidget(this); // 游标显示窗口 } QObject::connect(m_CustomCursorTool, &CustomCursorTool::identifyResultChange, cursorInfoDialog, &QImageCursorWidget::showCursor, Qt::ConnectionType::AutoConnection); cursorInfoDialog->show(); map_canvas->setCursor(Qt::CrossCursor); } else { map_canvas->setCursor(Qt::CursorShape::ArrowCursor); } }