You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
PayloadAPP/Src/RescueLoad/rescueloadwidget.cpp

364 lines
13 KiB
C++

#include "rescueloadwidget.h"
#include <QQuickWidget>
#include "qjsonarray.h"
#include "ui_rescueloadwidget.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QQuickView>
#include <QUrl>
#include <QRandomGenerator>
#include <QTextBlock>
#include <QtQml>
#include <QQmlContext>
#include <QQmlApplicationEngine>
#include <QQmlComponent>
#include <QFileDialog>
#include <QMessageBox>
RescueLoadWidget::RescueLoadWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::RescueLoadWidget)
{
ui->setupUi(this);
initialModel(); // 初始化数据model
initialUi(); // 初始化表格样式
// 数据交互和视图设置
rescueLoad = new RescueLoad(this);
rescueLoad->startCommunication(); // todo: 转移到子线程中运行
// rescueLoad->sendMessage(QString("Hello"));
connect(rescueLoad, &RescueLoad::dataUpdate, rescueLoad, [=](ImsiData data){
imsiDataModel->updateData(data);
});
// 地图组件, 必须在RescueLoad和ImsiDataModel初始化后加载
openQLocationMap();
}
RescueLoadWidget::~RescueLoadWidget()
{
ui->deviceDetail->clearContents();
delete protoItem;
delete standardItem;
delete ui;
}
// 使用QLocation加载地图模块 (fixme: 能显示地图但是无法向qml传递数据
void RescueLoadWidget::openQLocationMap() {
QQuickView *qmlView = new QQuickView();
qmlView->rootContext()->setContextProperty("imsiDataModel", imsiDataModel); // 注意先绑定属性再设置qml
qmlView->rootContext()->setContextProperty("imsiSelectModel", ui->deviceview->selectionModel()); // 注意先绑定属性再设置qml
qmlView->setSource(QUrl("qrc:/places_map.qml"));
QWidget *container = QWidget::createWindowContainer(qmlView, this);
ui->mapGroup->setLayout(new QVBoxLayout);
ui->mapGroup->layout()->addWidget(container);
qDebug()<<"搜救地图开启"<<imsiDataModel->getDataMap().keys().size();
// 接收QML的信号
QObject* object = (QObject* )qmlView->rootObject();
// connect(object, SIGNAL(locationClicked(QString)), this, SLOT(updateDetailTable(QString)));
QObject::connect(object, SIGNAL(indexClicked(int)), this, SLOT(tableIndexClicked(int)));
}
void RescueLoadWidget::tableIndexClicked(int row){
// qDebug()<<row;
emit ui->deviceview->clicked(imsiDataModel->index(row));
}
void RescueLoadWidget::initialUi()
{
// 设备imsi列表样式
setTable(ui->deviceview);
setTable(ui->bnameview);
setTable(ui->wnameview);
// 单元格样式
protoItem = new QTableWidgetItem;
protoItem->setTextAlignment(Qt::AlignCenter);
standardItem = new QStandardItem;
standardItem->setTextAlignment(Qt::AlignCenter);
QFont font = QFont("Microsoft YaHei UI", 12);
protoItem->setFont(font);
standardItem->setFont(font);
setDeviceDetail(ui->deviceDetail);
}
void RescueLoadWidget::setTable(QTableView* tableView) {
// 设置样式表
tableView->setStyleSheet(
"QTableView::item {"
" background-color: transparent;"
" color: white;"
"}"
);
QFont font = QFont("Microsoft YaHei UI", 12);
tableView->horizontalHeader()->setFont(font);
tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); // 可拉伸填充
tableView->horizontalHeader()->setDefaultAlignment(Qt::AlignCenter); //表头信息显示居中
tableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Fixed);//对第2列单独设置固定宽度
tableView->setColumnWidth(1, 100);//设置固定宽度
tableView->verticalHeader()->setFont(font);
tableView->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
tableView->verticalHeader()->setDefaultAlignment(Qt::AlignCenter);
tableView->verticalHeader()->setFixedWidth(35); // 行表头(序号)设置固定宽度
// tableWidget->verticalHeader()->hide(); //将默认序号隐藏
tableView->setShowGrid(true);
tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); // 不可编辑
// 选中行更新详细信息
tableView->setSelectionBehavior(QAbstractItemView::SelectRows); // 选中行
// 单击后选中并显示详情,再次点击取消选中
connect(tableView, &QTableView::clicked, this, [=](QModelIndex index) {
static int preRow = -1; // 记录前一个点击事件所在行
int curRow = index.row();
QModelIndex imsiIndex = index.model()->index(curRow, 0); // note 第一列必须为imsi值
QString imsi =tableView->model()->data(imsiIndex).toString();
QItemSelectionModel* selectModel = tableView->selectionModel();
if (curRow == preRow) {
// 取消选中状态
if (selectModel->isSelected(index)) {
selectModel->select(index, QItemSelectionModel::Deselect | QItemSelectionModel::Rows);
preRow = -1; //取消后重置,否则无法选中
return;
}
}
selectModel->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
preRow = curRow;
if (tableView == ui->deviceview){
updateDetailTable(imsi);
}
});
// 选中行更新名单编辑区
connect(tableView->selectionModel(), &QItemSelectionModel::selectionChanged, tableView, [=]() {
QModelIndexList selectedIndexes = tableView->selectionModel()->selectedIndexes();
QAbstractItemModel* model = tableView->model();
ui->namelistEdit->clear();
QString selectedText;
for (const QModelIndex &index : selectedIndexes) {
if (index.column() == 0) {
selectedText = model->data(index).toString();
ui->namelistEdit->appendPlainText(selectedText.trimmed());
}
}
ui->namelistEdit->show();
// qDebug() << "选择状态变更: selcted: " << selectedIndexes;
});
}
void RescueLoadWidget::initialModel()
{
QStringList headers = QStringList()<<"IMSI"<<"运营商";
wnamelistModel = new QStandardItemModel(this);
wnamelistModel->setHorizontalHeaderLabels(headers);
wnamelistModel->setColumnCount(2);
ui->wnameview->setModel(wnamelistModel);
bnamelistModel = new QStandardItemModel(this);
bnamelistModel->setHorizontalHeaderLabels(headers);
bnamelistModel->setColumnCount(2);
ui->bnameview->setModel(bnamelistModel);
imsiDataModel = new ImsiTableModel(this);
ui->deviceview->setModel(imsiDataModel);
}
void RescueLoadWidget::setDeviceDetail(QTableWidget* deviceDetail) {
// 设备详情表样式
deviceDetail->setStyleSheet(
"QTableWidget::item {"
" background-color: transparent;"
" color: white;"
"}"
);
deviceDetail->verticalHeader()->setFont(QFont("Microsoft YaHei UI", 12));
deviceDetail->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
deviceDetail->verticalHeader()->setDefaultAlignment(Qt::AlignCenter);
deviceDetail->setEditTriggers(QAbstractItemView::NoEditTriggers); // 不可编辑
deviceDetail->setShowGrid(true);
// 初始化
for (int i=0; i<deviceDetail->rowCount(); i++) {
QTableWidgetItem *item = protoItem->clone();
deviceDetail->setItem(i, 0, item);
}
deviceDetail->show();
qDebug() << "设备详细信息初始化完成";
}
// 更新指定imsi的详细信息
void RescueLoadWidget::updateDetailTable(const QString imsi)
{
const QHash<QString, ImsiData>& dataMap = imsiDataModel->getDataMap();
if (!dataMap.contains(imsi)) return;
ImsiData data = imsiDataModel->getDataMap().value(imsi);
// qDebug()<<"更新详细信息start: " << imsi;
emit imsiDataModel->detailUpdated(imsi, data.longitude.toDouble(), data.latitude.toDouble());
ui->deviceDetail->item(0, 0)->setText(data.imsi);
ui->deviceDetail->item(1, 0)->setText(data.operatorName);
ui->deviceDetail->item(2, 0)->setText(data.longitude);
ui->deviceDetail->item(3, 0)->setText(data.latitude);
ui->deviceDetail->item(4, 0)->setText(QString::number(data.altitude));
ui->deviceDetail->item(5, 0)->setText(data.fcn);
ui->deviceDetail->item(6, 0)->setText(QString::number(data.rssi));
ui->deviceDetail->item(7, 0)->setText(data.createDate);
ui->deviceDetail->show();
// qDebug()<<"更新详细信息end: " << imsi;
}
slots void RescueLoadWidget::on_start4G_clicked()
{
// 开启4g功放
rescueLoad->sendMessage(QString("{\"cmd\": \"startCell\"}"));
rescueLoad->sendMessage(QString("{\"cmd\": \"heartbeat\"}"));
// 时间同步
rescueLoad->syncTime();
}
slots void RescueLoadWidget::on_stop4G_clicked()
{
rescueLoad->sendMessage(QString("{\"cmd\": \"stopCell\"}"));
}
slots void RescueLoadWidget::on_start5G_clicked()
{
// 开启5g功放
rescueLoad->sendMessage(QString("{\"cmd\": \"startCell_5g\"}"));
rescueLoad->sendMessage(QString("{\"cmd\": \"heartbeat\"}"));
// 时间同步
rescueLoad->syncTime();
}
slots void RescueLoadWidget::on_stop5G_clicked()
{
rescueLoad->sendMessage(QString("{\"cmd\": \"stopCell_5g\"}"));
}
slots void RescueLoadWidget::on_addblistBtn_clicked()
{
QList<QString> namelistToSend = getNameListEditList(); // 输入量用于更新namelist
QString type = ui->namelistConfigType->currentText().toUpper();
QString sendType;
if (type.startsWith("ADD")) {
sendType = "ADD";
} else if (type.startsWith("SUB")) {
sendType = "SUB";
} else if (type.startsWith("SAVE")) {
sendType = "SAVE";
} else {
return;
}
rescueLoad->sendNameList("block", sendType, QList<QString>(), namelistToSend);
updateWBnamelist("B", sendType, namelistToSend);
}
slots void RescueLoadWidget::on_addwlistBtn_clicked()
{
QList<QString> namelistToSend = getNameListEditList(); // 输入量用于更新namelist
QString type = ui->namelistConfigType->currentText().toUpper();
QString sendType;
if (type.startsWith("ADD")) {
sendType = "ADD";
} else if (type.startsWith("SUB")) {
sendType = "SUB";
} else if (type.startsWith("SAVE")) {
sendType = "SAVE";
} else {
return;
}
rescueLoad->sendNameList("block", sendType, namelistToSend, QList<QString>());
updateWBnamelist("W", sendType, namelistToSend);
}
/** 获取编辑区的imsi列表*/
QList<QString> RescueLoadWidget::getNameListEditList(){
QTextBlock block = ui->namelistEdit->document()->firstBlock();
QList<QString> namelist;
while (block.isValid()) {
QString tmp = block.text().trimmed();
if (! tmp.isEmpty()) {
namelist.append(tmp);
}
block = block.next();
}
return namelist;
}
// 更新黑名单和白名单的数据与显示
void RescueLoadWidget::updateWBnamelist(QString listType, QString sendType, QList<QString> &namelistToUpdate)
{
QStandardItemModel *namelistModel = listType=="W"? wnamelistModel: bnamelistModel;
QSet<QString> &namelistToShow = listType=="W"? wnamelist : bnamelist;
// 更新黑/白名单列表
if (sendType == "ADD") { // 新增
for(const QString &imsi: namelistToUpdate) {
namelistToShow.insert(imsi);
}
} else if (sendType == "SUB") { // 删除
for(const QString &imsi: namelistToUpdate) {
namelistToShow.remove(imsi);
}
} else if (sendType == "SAVE") { // 替换现有在列表
namelistToShow.clear();
for(const QString &imsi: namelistToUpdate) {
namelistToShow.insert(imsi);
}
}
// 列表显示更新
namelistModel->clear();
namelistModel->setColumnCount(2);
namelistModel->setRowCount(namelistToShow.size());
namelistModel->setHorizontalHeaderLabels(QStringList()<<"IMSI"<<"运营商");
int i = 0;
for (const QString &imsi : namelistToShow) {
QStandardItem *item1 =standardItem->clone();
QStandardItem *item2 =standardItem->clone();
item1->setText(imsi);
item2->setText(ImsiData::getOperatorNameByImsi(imsi));
namelistModel->setItem(i, 0, item1);
namelistModel->setItem(i, 1, item2);
i ++ ;
}
qDebug() << "名单数据更新end"<< namelistModel->rowCount();
}
void RescueLoadWidget::on_ipportBtn_clicked()
{
QString newIp = ui->ipEdit->text().trimmed();
int newPort = ui->portEdit->text().trimmed().toInt();
rescueLoad->remoteIp = newIp;
rescueLoad->remotePort = newPort;
}
void RescueLoadWidget::on_saveFileButton_clicked()
{
QString timeStr = QDateTime::currentDateTime().toString("yyyy-MM-ddThh-mm-ss");
QString defaultPath = QString("%1/搜救信息%2.csv").arg(imsiDataModel->getSaveDir(), timeStr);
QString filePath = QFileDialog::getSaveFileName(this, tr("保存文件"), defaultPath, tr("CSV 文件 (*.csv)"));
qDebug()<< filePath;
if (!filePath.isEmpty()) {
imsiDataModel->saveDataListToCsv(filePath);
}
}