尝试合并

wangjing
nanjirenwahaha 7 months ago
parent fc3aa2a842
commit e9949b98fc

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -25,7 +25,7 @@
#include <cmath>
#include "mapbridge.h"
MapPage::MapPage(QWidget *parent) : QWidget(parent),
MapPage::MapPage(QWidget *parent) : QWidget(parent),
mapArea_(nullptr),
heightCombo_(nullptr),
downloadMapBtn_(nullptr),
@ -77,7 +77,7 @@ void MapPage::setupUI() {
mainLayout->setSpacing(8);
mainLayout->setContentsMargins(0, 0, 0, 0);
auto* title = new QLabel("地图监控");
auto* title = new QLabel("路径监控");
title->setProperty("class", "section");
mainLayout->addWidget(title);
@ -240,7 +240,7 @@ void MapPage::setupMapArea() {
window.map.setZoom(15); // 更高缩放级别以显示街道
console.log("GPS定位成功: 经度 " + position.lng + ", 纬度 " + position.lat + ", 精度 " + result.accuracy);
// 添加 GPS 定位成功标记 (蓝色)
// 添加定位成功标记 (蓝色)
var marker = new AMap.Marker({
position: lnglat,
title: 'GPS Position',
@ -249,7 +249,7 @@ void MapPage::setupMapArea() {
});
marker.setMap(window.map);
// 添加 GPS 信息窗口
// 添加定位信息窗口
var infoContent = '<div>GPS<br>: ' + position.lng + '<br>: ' + position.lat;
if (result.accuracy) infoContent += '<br>: ' + result.accuracy + '';
if (result.info) infoContent += '<br>: ' + result.info;
@ -299,26 +299,6 @@ void MapPage::setupMapArea() {
});
}
});
// 辅助函数:使用默认位置
function useDefaultPosition() {
var defaultPos = new AMap.LngLat(116.397428, 39.90923);
window.map.setCenter(defaultPos);
window.map.setZoom(10);
var marker = new AMap.Marker({
position: defaultPos,
title: '',
content: '<div style="background:#FF9800; color:white; padding:4px 8px; border-radius:50%%; font-size:12px;"></div>'
});
marker.setMap(window.map);
var infoWindow = new AMap.InfoWindow({
content: '<div>使<br>: 116.397428<br>: 39.90923</div>',
offset: new AMap.Pixel(0, -30)
});
infoWindow.open(window.map, defaultPos);
}
});
}
</script>
@ -386,11 +366,15 @@ QWidget* MapPage::createControlBarWidget() {
connect(areaCoverageBtn_, &QPushButton::clicked, this, &MapPage::onAreaCoverageClicked);
layout->addWidget(areaCoverageBtn_);
// Clear path button moved to PathPlanningDialog
return bar;
}
#ifdef INCLUDE_AREA_SEARCH
void MapPage::onAreaSearchClicked() {
searchDialog_->exec();
}
#endif
void MapPage::enableGeolocation() {
if (mapView_) {
QWebEngineSettings* settings = mapView_->settings();
@ -514,398 +498,3 @@ void MapPage::clearPathOverlays() {
console.log('Map not available for clearing');
}
)").arg(pathOverlayId_, startMarkerId_, endMarkerId_);
runMapJavaScript(js);
qDebug() << "路径覆盖物清除完成";
}
void MapPage::visualizeCoveragePath(const QString& pathData) {
QString js = QString(R"(
if (window.map) {
var pathCoords = JSON.parse("%1");
console.log('Visualizing coverage path with ' + pathCoords.length + ' points');
// Remove existing coverage overlay if any
if (window.%2) {
window.map.remove(window.%2);
window.%2 = null;
}
// Create new polyline for coverage path (green, dashed)
var polyline = new AMap.Polyline({
path: pathCoords,
strokeColor: "#4CAF50",
strokeOpacity: 0.8,
strokeWeight: 4,
strokeStyle: "dashed",
strokeDasharray: [8, 4],
zIndex: 2
});
polyline.setMap(window.map);
window.%2 = polyline;
// Clear existing coverage intermediates
if (!window.coverageIntermediates) {
window.coverageIntermediates = [];
}
for (var i = 0; i < window.coverageIntermediates.length; i++) {
if (window.coverageIntermediates[i]) {
window.map.remove(window.coverageIntermediates[i]);
}
}
window.coverageIntermediates = [];
// Add intermediate markers for coverage points
for (var i = 0; i < pathCoords.length; i += 5) { // Every 5th point for visibility
var marker = new AMap.Marker({
position: pathCoords[i],
content: '<div style="background:#4CAF50; color:white; padding:2px 6px; border-radius:50%%; font-size:10px; font-weight:bold;">C' + (i/5 + 1) + '</div>',
zIndex: 15
});
marker.setMap(window.map);
window.coverageIntermediates.push(marker);
}
// Fit view
var allOverlays = [polyline].concat(window.coverageIntermediates);
if (allOverlays.length > 0) {
window.map.setFitView(allOverlays, {padding: [50, 50, 50, 50]});
}
console.log('Coverage path visualization completed');
}
)").arg(pathData, coverageOverlayId_);
runMapJavaScript(js);
currentCoveragePathData_ = pathData;
qDebug() << "区域覆盖路径可视化完成";
}
void MapPage::clearCoverageOverlays() {
QString js = QString(R"(
if (window.map) {
console.log('Clearing all coverage overlays...');
// Remove coverage polyline
if (window.%1) {
window.map.remove(window.%1);
window.%1 = null;
console.log('Removed coverage polyline');
}
// Remove area overlay if exists
if (window.%2) {
window.map.remove(window.%2);
window.%2 = null;
console.log('Removed area overlay');
}
// Clear coverage intermediates
if (!window.coverageIntermediates) {
window.coverageIntermediates = [];
}
for (var i = 0; i < window.coverageIntermediates.length; i++) {
if (window.coverageIntermediates[i]) {
window.map.remove(window.coverageIntermediates[i]);
}
}
window.coverageIntermediates = [];
console.log('All coverage overlays cleared successfully');
} else {
console.log('Map not available for clearing');
}
)").arg(coverageOverlayId_, areaOverlayId_);
runMapJavaScript(js);
qDebug() << "区域覆盖覆盖物清除完成";
}
double MapPage::parseLng(const QString& coord) const {
// Handle both "[lng, lat]" and "lng, lat"
QRegExp rx("^\\s*\\[?\\s*([\\d.-]+)\\s*,");
if (rx.indexIn(coord) != -1) {
return rx.cap(1).toDouble();
}
return 0.0;
}
double MapPage::parseLat(const QString& coord) const {
// Handle both "[lng, lat]" and "lng, lat"
QRegExp rx(",\\s*([\\d.-]+)\\s*\\]?\\s*$");
if (rx.indexIn(coord) != -1) {
return rx.cap(1).toDouble();
}
return 0.0;
}
void MapPage::showMarker(double lng, double lat, const QString& label, const QString& color, int index) {
QString markerId = (index == 0) ? startMarkerId_ : endMarkerId_;
QString js = QString(R"(
if (window.map) {
// Only remove if it's a different position
if (window.%1 && (window.%1.getPosition().lng != %2 || window.%1.getPosition().lat != %3)) {
window.map.remove(window.%1);
}
if (!window.%1 || (window.%1.getPosition().lng != %2 || window.%1.getPosition().lat != %3)) {
var marker = new AMap.Marker({
position: new AMap.LngLat(%2, %3),
content: '<div style="background:%4; color:white; padding:2px 6px; border-radius:50%%; font-size:12px;">%5</div>',
zIndex: 100 + (%6 === 0 ? 10 : 5) // Start marker gets higher z-index
});
marker.setMap(window.map);
window.%1 = marker;
}
}
)").arg(markerId, QString::number(lng), QString::number(lat), color, label, QString::number(index));
runMapJavaScript(js);
}
void MapPage::addClickListener() {
QString js = R"(
console.log('Adding click listener...');
function addListener() {
if (window.map && window.bridge && window.mapReady) {
// Remove existing listener if any
if (window.clickListener) {
window.clickListener.remove();
console.log('Removed existing listener');
}
window.clickListener = window.map.on('click', function(e) {
console.log('Map clicked at: ' + e.lnglat.getLng() + ', ' + e.lnglat.getLat());
window.bridge.onClick(e.lnglat.getLng(), e.lnglat.getLat());
});
console.log('Click listener added successfully');
return true;
}
return false;
}
if (addListener()) {
// Already ready
} else {
console.log('Map or bridge not ready - polling...');
var attempts = 0;
var maxAttempts = 100; // 10 seconds at 100ms intervals
var interval = setInterval(function() {
attempts++;
if (addListener()) {
clearInterval(interval);
} else if (attempts >= maxAttempts) {
clearInterval(interval);
console.error('Failed to add listener after ' + maxAttempts + ' attempts');
}
}, 100);
}
)";
runMapJavaScript(js);
}
void MapPage::removeClickListener() {
QString js = R"(
if (window.clickListener) {
window.clickListener.remove();
window.clickListener = null;
}
)";
runMapJavaScript(js);
}
void MapPage::visualizePath(const QString& pathData) {
QString js = QString(R"(
if (window.map) {
var pathCoords = JSON.parse("%1");
console.log('Visualizing path with ' + pathCoords.length + ' points');
// Remove existing path overlay if any
if (window.%2) {
window.map.remove(window.%2);
window.%2 = null;
}
// Create new polyline
var polyline = new AMap.Polyline({
path: pathCoords,
strokeColor: "#3366FF",
strokeOpacity: 1,
strokeWeight: 5,
strokeStyle: "solid",
strokeDasharray: [10, 5],
zIndex: 1
});
polyline.setMap(window.map);
window.%2 = polyline;
// Clear existing intermediate markers
if (!window.intermediates) {
window.intermediates = [];
}
for (var i = 0; i < window.intermediates.length; i++) {
if (window.intermediates[i]) {
window.map.remove(window.intermediates[i]);
}
}
window.intermediates = [];
// Add intermediate markers (excluding start and end)
for (var i = 1; i < pathCoords.length - 1; i++) {
var marker = new AMap.Marker({
position: pathCoords[i],
content: '<div style="background:#9C27B0; color:white; padding:2px 6px; border-radius:50%%; font-size:12px; font-weight:bold;">' + (i + 1) + '</div>',
zIndex: 10
});
marker.setMap(window.map);
window.intermediates.push(marker);
console.log('Added intermediate marker ' + (i + 1) + ' at: ' + pathCoords[i]);
}
// Fit view to show all elements
var allOverlays = [];
if (window.startMarker) allOverlays.push(window.startMarker);
if (window.endMarker) allOverlays.push(window.endMarker);
allOverlays.push(polyline);
allOverlays = allOverlays.concat(window.intermediates);
if (allOverlays.length > 0) {
window.map.setFitView(allOverlays, {padding: [50, 50, 50, 50]});
}
console.log('Path visualization completed with ' + window.intermediates.length + ' intermediate points');
}
)").arg(pathData, pathOverlayId_);
runMapJavaScript(js);
qDebug() << "路径可视化完成";
}
void MapPage::onPageLoaded(bool ok) {
if (ok) {
qDebug() << "Page loaded successfully";
// Ensure bridge is properly registered with WebChannel
if (channel_ && bridge_) {
channel_->registerObject("bridge", bridge_);
qDebug() << "Bridge registered with WebChannel";
// Check readiness after a short delay
QTimer::singleShot(500, this, [this]() {
runMapJavaScript("console.log('Readiness check: mapReady=' + !!window.mapReady + ', bridge exists=' + !!window.bridge);");
// 如果地图已就绪且bridge可用添加点击监听器JS侧会处理
runMapJavaScript("if (window.mapReady && window.bridge) { addClickListener(); } else { console.log('Waiting for map and bridge to be ready...'); }");
});
} else {
qDebug() << "ERROR: Channel or bridge is null!";
}
} else {
qDebug() << "Page load failed";
}
}
// Implement ThreatAreaDialog methods
ThreatAreaDialog::ThreatAreaDialog(QWidget *parent, MapPage* mapPage) : QDialog(parent), mapPage_(mapPage), drawingPoints_() {
setWindowTitle("设置威胁区域");
setMinimumSize(600, 500);
auto* layout = new QVBoxLayout(this);
layout->setSpacing(15);
layout->setContentsMargins(20, 20, 20, 20);
// 威胁区域基本信息组
auto* basicGroup = new QGroupBox("基本信息");
basicGroup->setStyleSheet("QGroupBox { font-weight: bold; margin-top: 10px; }");
auto* basicLayout = new QGridLayout(basicGroup);
basicLayout->setSpacing(10);
// 威胁类型
basicLayout->addWidget(new QLabel("威胁类型:"), 0, 0);
typeCombo_ = new QComboBox();
typeCombo_->addItems({"导弹威胁", "雷达干扰", "防空火力", "禁飞区域", "其他"});
typeCombo_->setStyleSheet("QComboBox { padding: 5px; border: 1px solid #ccc; border-radius: 4px; }");
basicLayout->addWidget(typeCombo_, 0, 1);
// 威胁等级
basicLayout->addWidget(new QLabel("威胁等级:"), 0, 2);
levelCombo_ = new QComboBox();
levelCombo_->addItems({"", "", ""});
levelCombo_->setStyleSheet("QComboBox { padding: 5px; border: 1px solid #ccc; border-radius: 4px; }");
basicLayout->addWidget(levelCombo_, 0, 3);
layout->addWidget(basicGroup);
// 添加形状选择
basicLayout->addWidget(new QLabel("形状:"), 1, 0);
shapeCombo_ = new QComboBox();
shapeCombo_->addItems({"圆形", "矩形"});
shapeCombo_->setStyleSheet("QComboBox { padding: 5px; border: 1px solid #ccc; border-radius: 4px; }");
connect(shapeCombo_, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ThreatAreaDialog::onShapeChanged);
basicLayout->addWidget(shapeCombo_, 1, 1);
// 添加颜色选择(假设用于 overlay 颜色)
basicLayout->addWidget(new QLabel("颜色:"), 1, 2);
colorCombo_ = new QComboBox();
colorCombo_->addItems({"红色", "黄色", "蓝色"});
basicLayout->addWidget(colorCombo_, 1, 3);
layout->addWidget(basicGroup);
// 时间设置组 (保持不变)
auto* timeGroup = new QGroupBox("威胁区域存在时间");
timeGroup->setStyleSheet("QGroupBox { font-weight: bold; margin-top: 10px; }");
auto* timeLayout = new QVBoxLayout(timeGroup);
// 开始时间
auto* startTimeLayout = new QHBoxLayout();
startTimeLayout->addWidget(new QLabel("开始时间:"));
startTimeEdit_ = new QDateTimeEdit(QDateTime::currentDateTime());
startTimeEdit_->setDisplayFormat("yyyy-MM-dd hh:mm:ss");
startTimeEdit_->setCalendarPopup(true);
startTimeEdit_->setStyleSheet("QDateTimeEdit { padding: 5px; border: 1px solid #ccc; border-radius: 4px; }");
startTimeLayout->addWidget(startTimeEdit_);
startTimeLayout->addStretch();
timeLayout->addLayout(startTimeLayout);
// 结束时间
auto* endTimeLayout = new QHBoxLayout();
endTimeLayout->addWidget(new QLabel("结束时间:"));
endTimeEdit_ = new QDateTimeEdit(QDateTime::currentDateTime().addSecs(3600)); // 默认1小时后
endTimeEdit_->setDisplayFormat("yyyy-MM-dd hh:mm:ss");
endTimeEdit_->setCalendarPopup(true);
endTimeEdit_->setStyleSheet("QDateTimeEdit { padding: 5px; border: 1px solid #ccc; border-radius: 4px; }");
endTimeLayout->addWidget(endTimeEdit_);
endTimeLayout->addStretch();
timeLayout->addLayout(endTimeLayout);
layout->addWidget(timeGroup);
// 动态输入 widget
circleInputWidget_ = new QWidget();
auto* circleLayout = new QFormLayout(circleInputWidget_);
centerLngInput_ = new QLineEdit();
centerLngInput_->setPlaceholderText("中心经度");
circleLayout->addRow("中心经度:", centerLngInput_);
centerLatInput_ = new QLineEdit();
centerLatInput_->setPlaceholderText("中心纬度");
circleLayout->addRow("中心纬度:", centerLatInput_);
radiusInput_ = new QLineEdit();
radiusInput_->setPlaceholderText("半径 (米)");
circleLayout->addRow("半径 (米):", radiusInput_);
layout->addWidget(circleInputWidget_);
rectangleInputWidget_ = new QWidget();
auto* rectLayout = new QVBoxLayout(rectangleInputWidget_);
rectPointsTable_ = new QTableWidget(4, 2);
rectPointsTable_->setHorizontalHeaderLabels({"经度", "纬度"});
for (int i = 0; i < 4; ++i) {
rectPointsTable_->setItem(i, 0, new QTableWidgetItem(""));
rectPointsTable_->setItem(i, 1, new QTableWidgetItem(""));
}
rectLayout->addWidget(rectPointsTable_);
layout->addWidget(rectangleInputWidget_);
rectangleInputWidget_->setVisible(false);
// 按钮 (保持 drawOnMapBtn_ 等)
auto* buttonLayout = new QHBoxLayout();
buttonLayout->addStretch();
drawOnMapBtn_ = new QPushButton("在地图上绘制");
drawOnMapBtn_->setStyleSheet("QPushButton { padding: 8px 20px; background: #4CAF50; color: white; border-radius: 4px; }");
connect(drawOnMapBtn_, &QPushButton::clicked, this, &ThreatAreaDialog::startDrawingThreatArea);
buttonLayout->addWidget(drawOnMapBtn_);
auto* addBtn = new QPushButton("添加区域");
addBtn->setProperty("primary", true);
addBtn->setStyleSheet("QPushButton { padding: 8px 20px; background: #2196f3; color: white

@ -42,15 +42,18 @@ protected:
}
};
// 移除前向声明
// class ThreatAreaDialog;
// class AreaSearchDialog;
// class PathPlanningDialog;
// 前向声明
class MapPage;
class MapPage; // 确保MapPage在所有对话框类之前声明
class ThreatAreaDialog;
class PathPlanningDialog;
class AreaCoverageDialog;
#ifdef INCLUDE_AREA_SEARCH
class AreaSearchDialog;
#endif
// 定义类
// 定义类时需要确保MapPage的声明已完成
class ThreatAreaDialog : public QDialog {
Q_OBJECT
public:
@ -91,7 +94,6 @@ private:
int selectedRow_ = -1; // 跟踪选中行
};
class MapPage;
class PathPlanningDialog : public QDialog {
@ -168,20 +170,6 @@ private:
QList<QPair<double, double>> vertices_;
};
// 添加AreaSearchDialog类定义
class AreaSearchDialog : public QDialog {
Q_OBJECT
public:
AreaSearchDialog(QWidget* parent = nullptr);
private slots:
void onConfirm();
private:
QLineEdit* minLngInput_;
QLineEdit* minLatInput_;
QLineEdit* maxLngInput_;
QLineEdit* maxLatInput_;
};
// 添加LocateDialog类定义
class LocateDialog : public QDialog {
Q_OBJECT
@ -198,6 +186,23 @@ private:
double lat_;
};
// 条件编译添加AreaSearchDialog确保兼容性
#ifdef INCLUDE_AREA_SEARCH
// 添加AreaSearchDialog类定义
class AreaSearchDialog : public QDialog {
Q_OBJECT
public:
AreaSearchDialog(QWidget* parent = nullptr);
private slots:
void onConfirm();
private:
QLineEdit* minLngInput_;
QLineEdit* minLatInput_;
QLineEdit* maxLngInput_;
QLineEdit* maxLatInput_;
};
#endif
/**
*
*
@ -205,14 +210,6 @@ private:
class MapPage : public QWidget {
Q_OBJECT
// 增加绘图模式成员
bool isDrawing_ = false;
QString drawingShape_; // "circle" or "rectangle"
QList<QPair<double, double>> drawingPoints_; // 临时绘制点
QList<QVariantMap> threatAreas_; // 新增:存储已添加的威胁区域
public:
const QList<QVariantMap>& getThreatAreas() const { return threatAreas_; } // 新增 getter
public:
explicit MapPage(QWidget* parent = nullptr);
~MapPage();
@ -238,7 +235,11 @@ private slots:
void onSetThreatClicked();
void onPathPlanningClicked();
void onAreaCoverageClicked();
// 条件编译区域搜索功能
#ifdef INCLUDE_AREA_SEARCH
void onAreaSearchClicked();
#endif
// 添加新槽
void onSearchMapClicked(); // 新增声明
@ -262,6 +263,12 @@ public slots:
void addThreatOverlay(const QString& shape, const QVariantMap& params); // 添加威胁 overlay
void removeThreatOverlay(int index); // 新增:移除特定 overlay
private:
void setupUI();
void setupMapControls();
void setupMapArea();
void setupControlBar();
// 添加新方法
void enableGeolocation();
@ -277,10 +284,14 @@ public slots:
// 添加新按钮成员
QPushButton* setThreatBtn_;
QPushButton* areaSearchBtn_;
QPushButton* pathPlanningBtn_;
QPushButton* areaCoverageBtn_;
// 条件编译区域搜索按钮
#ifdef INCLUDE_AREA_SEARCH
QPushButton* areaSearchBtn_;
#endif
// 添加新组件
QLineEdit* coordInput_;
QPushButton* locateBtn_;
@ -288,10 +299,14 @@ public slots:
// 添加对话框成员
ThreatAreaDialog* threatDialog_;
AreaSearchDialog* searchDialog_;
PathPlanningDialog* planningDialog_;
AreaCoverageDialog* coverageDialog_;
LocateDialog* locateDialog_;
// 条件编译区域搜索对话框
#ifdef INCLUDE_AREA_SEARCH
AreaSearchDialog* searchDialog_;
#endif
// 添加基字体大小(用于缩放)
int baseFontSize_ = 10; // 默认基字体大小,根据您的样式调整
@ -321,6 +336,4 @@ public:
const QList<QVariantMap>& getThreatAreas() const { return threatAreas_; } // 新增 getter
};
// 移除所有类定义从h文件移出
#endif // MAPPAGE_H

File diff suppressed because it is too large Load Diff

@ -0,0 +1,308 @@
#ifndef MAPPAGE_H
#define MAPPAGE_H
#include <QWidget>
#include <QPushButton>
#include <QLabel>
#include <QComboBox>
#include <QLineEdit>
#include <QFrame>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QWebEngineView>
#include <QWebEnginePage>
#include <QDebug>
#include <QWebEngineSettings>
#include <QDialog> // 添加
#include <QComboBox>
#include <QDateTimeEdit>
#include <QPushButton>
#include <QTableWidget>
#include <QFormLayout>
#include <QLineEdit>
#include <QMessageBox> // 添加以支持输入验证警告
#include <QGroupBox> // 添加QGroupBox支持
#include <QRadioButton> // 添加QRadioButton支持
#include <QSpinBox>
#include <QButtonGroup>
#include <QList>
#include <QPair>
#include "mapbridge.h"
class CustomWebEnginePage : public QWebEnginePage {
Q_OBJECT
signals:
void consoleMessage(QWebEnginePage::JavaScriptConsoleMessageLevel level, const QString &message, int lineNumber, const QString &sourceID);
public:
CustomWebEnginePage(QObject* parent = nullptr) : QWebEnginePage(parent) {}
protected:
void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) override {
qDebug() << "JS 消息 (级别:" << level << "):" << message << " (行:" << lineNumber << ", 来源:" << sourceID << ")";
emit consoleMessage(level, message, lineNumber, sourceID);
}
};
// 移除前向声明
// class ThreatAreaDialog;
// class AreaSearchDialog;
// class PathPlanningDialog;
// 前向声明
class MapPage;
// 定义类
class ThreatAreaDialog : public QDialog {
Q_OBJECT
public:
ThreatAreaDialog(QWidget* parent = nullptr, MapPage* mapPage = nullptr); // 添加 MapPage 参数
private slots:
void addArea();
void updateThreatStats();
void startDrawingThreatArea();
void onShapeChanged(int index); // 新增槽函数,处理形状变化
void handleDrawingClick(double lng, double lat); // 新增
void finishDrawing(); // 新增
void editArea(); // 新增:编辑选中区域
void deleteArea(); // 新增:删除选中区域
private:
QComboBox* typeCombo_;
QDateTimeEdit* startTimeEdit_;
QDateTimeEdit* endTimeEdit_;
QComboBox* shapeCombo_; // 已存在,但确保用于圆形/矩形
QComboBox* colorCombo_;
QTableWidget* areaTable_;
QLineEdit* coordInput_;
QPushButton* drawOnMapBtn_;
// 新增输入字段
QWidget* circleInputWidget_;
QWidget* rectangleInputWidget_;
QLineEdit* centerLngInput_;
QLineEdit* centerLatInput_;
QLineEdit* radiusInput_;
QTableWidget* rectPointsTable_;
MapPage* mapPage_; // 添加 MapPage 引用
QString currentShape_; // 当前形状
QList<QPair<double, double>> drawingPoints_; // 新增临时绘制点
QComboBox* levelCombo_; // 新增,存储威胁等级
QPushButton* editBtn_; // 新增编辑按钮
QPushButton* deleteBtn_; // 新增删除按钮
int selectedRow_ = -1; // 跟踪选中行
};
class MapPage;
class PathPlanningDialog : public QDialog {
Q_OBJECT
public:
PathPlanningDialog(QWidget* parent = nullptr, MapPage* mapPage = nullptr);
QString getStartCoord() const { return startInput_->text(); }
QString getEndCoord() const { return endInput_->text(); }
QString getPathData() const;
private slots:
void planPath();
void applyStartPoint();
void applyEndPoint();
void onMapClick(double lng, double lat);
void clearPath();
private:
QLineEdit* startInput_;
QLineEdit* endInput_;
QTableWidget* pathTable_;
QPushButton* planBtn_;
QPushButton* clearBtn_;
QPushButton* applyStartBtn_;
QPushButton* applyEndBtn_;
QPushButton* selectStartBtn_;
QPushButton* selectEndBtn_;
MapPage* mapPage_;
QString pathData_;
bool selectingStart_ = false;
bool selectingEnd_ = false;
};
class AreaCoverageDialog : public QDialog {
Q_OBJECT
public:
AreaCoverageDialog(QWidget* parent = nullptr, MapPage* mapPage = nullptr);
QString getCoveragePathData() const { return coveragePathData_; }
private slots:
void onShapeChanged(int index);
void addVertex();
void removeVertex();
void selectVertexOnMap();
void planCoveragePath();
void clearCoverage();
void onMapClick(double lng, double lat);
private:
QWidget* setupCircleInputs();
QWidget* setupPolygonInputs();
void generateMockCoveragePath();
QComboBox* shapeCombo_;
// Circle inputs
QLineEdit* centerLngInput_;
QLineEdit* centerLatInput_;
QLineEdit* radiusInput_;
// Polygon inputs
QTableWidget* verticesTable_;
QPushButton* addVertexBtn_;
QPushButton* removeVertexBtn_;
QPushButton* selectVertexBtn_;
// Mode and drones
QButtonGroup* modeGroup_;
QRadioButton* efficiencyRadio_;
QRadioButton* fullRangeRadio_;
QSpinBox* droneCountSpin_;
// Path
QTableWidget* pathTable_;
QPushButton* planBtn_;
QPushButton* clearBtn_;
QWidget* circleWidget_;
QWidget* polygonWidget_;
MapPage* mapPage_;
QString coveragePathData_;
bool selectingVertex_ = false;
int currentVertexRow_ = -1;
QList<QPair<double, double>> vertices_;
};
// 添加LocateDialog类定义
class LocateDialog : public QDialog {
Q_OBJECT
public:
LocateDialog(QWidget* parent = nullptr);
double getLongitude() const;
double getLatitude() const;
private slots:
void onConfirm();
private:
QLineEdit* lngInput_;
QLineEdit* latInput_;
double lng_;
double lat_;
};
/**
*
*
*/
class MapPage : public QWidget {
Q_OBJECT
public:
explicit MapPage(QWidget* parent = nullptr);
~MapPage();
// 获取组件引用
QComboBox* getHeightCombo() const { return heightCombo_; }
QPushButton* getDownloadMapBtn() const { return downloadMapBtn_; }
// 添加新信号
signals:
void heightChanged(const QString& height);
void downloadMapRequested();
void setThreatRequested();
void pathPlanningRequested();
void areaCoverageRequested();
void mapClicked(double lng, double lat);
private slots:
void onHeightChanged();
void onDownloadMapClicked();
// 添加新槽函数
void onSetThreatClicked();
void onPathPlanningClicked();
void onAreaCoverageClicked();
// 添加新槽
void onSearchMapClicked(); // 新增声明
void onConsoleMessage(QWebEnginePage::JavaScriptConsoleMessageLevel level, const QString &message, int lineNumber, const QString &sourceID);
void onPageLoaded(bool ok);
public slots:
void addClickListener();
void removeClickListener();
void handleMapClick(double lng, double lat);
void visualizePath(const QString& pathData);
void clearPathOverlays(); // 清除路径覆盖物
void runMapJavaScript(const QString& js); // 添加公共方法运行JS
double parseLng(const QString& coord) const;
double parseLat(const QString& coord) const;
void showMarker(double lng, double lat, const QString& label, const QString& color, int index);
void visualizeCoveragePath(const QString& pathData);
void clearCoverageOverlays();
void enableDrawingMode(const QString& shape);
void disableDrawingMode();
void addThreatOverlay(const QString& shape, const QVariantMap& params); // 添加威胁 overlay
void removeThreatOverlay(int index); // 新增:移除特定 overlay
private:
void setupUI();
void setupMapControls();
void setupMapArea();
void setupControlBar();
// 添加新方法
void enableGeolocation();
// 创建UI组件的辅助方法
QWidget* createMapControlsWidget();
QWidget* createControlBarWidget();
// UI组件
QFrame* mapArea_;
QComboBox* heightCombo_;
QPushButton* downloadMapBtn_;
QWebEngineView* mapView_;
// 添加新按钮成员
QPushButton* setThreatBtn_;
QPushButton* pathPlanningBtn_;
QPushButton* areaCoverageBtn_;
// 添加新组件
QLineEdit* coordInput_;
QPushButton* locateBtn_;
QPushButton* searchMapBtn_;
// 添加对话框成员
ThreatAreaDialog* threatDialog_;
PathPlanningDialog* planningDialog_;
AreaCoverageDialog* coverageDialog_;
LocateDialog* locateDialog_;
// 添加基字体大小(用于缩放)
int baseFontSize_ = 10; // 默认基字体大小,根据您的样式调整
// 路径规划相关成员
QString pathOverlayId_ = "pathOverlay";
QString startMarkerId_ = "startMarker";
QString endMarkerId_ = "endMarker";
QString currentPathData_; // 存储当前路径数据
// Bridge members
MapBridge* bridge_;
QWebChannel* channel_;
// Coverage related
QString coverageOverlayId_ = "coverageOverlay";
QString areaOverlayId_ = "areaOverlay";
QString currentCoveragePathData_;
// 绘制模式
bool isDrawing_ = false;
QString drawingShape_; // "circle" or "rectangle"
QList<QPair<double, double>> drawingPoints_; // 临时绘制点
QList<QVariantMap> threatAreas_; // 新增:存储已添加的威胁区域
public:
const QList<QVariantMap>& getThreatAreas() const { return threatAreas_; } // 新增 getter
};
// 移除所有类定义从h文件移出
#endif // MAPPAGE_H

Binary file not shown.
Loading…
Cancel
Save