565 lines
17 KiB
C++
565 lines
17 KiB
C++
#include "CloudDataDlg.h"
|
||
#include <QPainter>
|
||
#include "ApiClient.h"
|
||
#include <QJsonArray>
|
||
#include "geometryutils.h"
|
||
#include "MemRdWt.h"
|
||
#include "qtprojectwidgets.h"
|
||
|
||
static QString joinUrl(const QString &base, const QString &path)
|
||
{
|
||
if (path.startsWith("http://") || path.startsWith("https://")) return path;
|
||
QString b = base;
|
||
QString p = path;
|
||
if (b.endsWith('/')) b.chop(1);
|
||
if (p.startsWith('/')) p.remove(0, 1);
|
||
if (b.isEmpty()) return p;
|
||
return b + '/' + p;
|
||
}
|
||
|
||
CloudDataDlg::CloudDataDlg(QWidget *parent)
|
||
: QDialog(parent),
|
||
ui(new Ui::CloudDataDlg)
|
||
{
|
||
ui->setupUi(this);
|
||
|
||
ApiClient::getInstance()->setBaseUrl("http://10.235.142.76:8090");
|
||
//setWindowTitle(QString::fromLocal8Bit("边框线形设置"));
|
||
connect(ui->btnAccess,SIGNAL(clicked()),this,SLOT(onEnter()));
|
||
|
||
ui->btn_back->setVisible(false);
|
||
ui->treeWidget->setColumnCount(1); //设置列数
|
||
ui->treeWidget->setHeaderHidden(true); // 隐藏表头
|
||
ui->treeWidget->setDragEnabled(false);
|
||
ui->treeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||
connect(ui->treeWidget, &QTreeWidget::itemDoubleClicked, this, &CloudDataDlg::onItemDoubleClicked);
|
||
}
|
||
|
||
CloudDataDlg::~CloudDataDlg()
|
||
{
|
||
|
||
}
|
||
|
||
void CloudDataDlg::setProjectWidgets(QtProjectWidgets* projectWidgets)
|
||
{
|
||
m_projectWidgets = projectWidgets;
|
||
}
|
||
|
||
void CloudDataDlg::initTreeProjects(QJsonObject jObj)
|
||
{
|
||
ui->btn_back->setVisible(false);
|
||
ui->treeWidget->clear();//清理数据
|
||
if (jObj.value("myProjects").isArray())
|
||
{
|
||
QJsonArray jarr = jObj.value("myProjects").toArray();
|
||
if (jarr.count() <= 0)
|
||
return;
|
||
|
||
QTreeWidgetItem *item = new QTreeWidgetItem();
|
||
item->setText(0, "我的项目");
|
||
item->setData(0, Qt::UserRole, "my_root"); // 存储额外数据,如ID
|
||
//item->setData(0, Qt::UserRole + 1, evaluationInfo.guid); // 存储额外数据,如ID
|
||
//
|
||
QIcon icon;
|
||
icon.addPixmap(QPixmap(GetImagePath() + "project.png"), QIcon::Selected);
|
||
icon.addPixmap(QPixmap(GetImagePath() + "project.png"), QIcon::Normal);
|
||
item->setIcon(0, icon);
|
||
// 这是一个根节点
|
||
ui->treeWidget->addTopLevelItem(item);
|
||
for (int i = 0; i < jarr.count(); i++)
|
||
{
|
||
if (!jarr[i].isObject())
|
||
continue;
|
||
QJsonObject obj = jarr[i].toObject();
|
||
|
||
QTreeWidgetItem *itemIndex = new QTreeWidgetItem();
|
||
itemIndex->setText(0, obj["projectName"].toString());
|
||
itemIndex->setData(0, Qt::UserRole, "project"); // 存储额外数据,如ID
|
||
itemIndex->setData(0, Qt::UserRole+1, obj["projectId"].toString()); // 存储额外数据,如ID
|
||
//
|
||
QIcon icon_wellfolder;
|
||
icon_wellfolder.addPixmap(QPixmap(GetImagePath() + "closeproject.png"), QIcon::Selected);
|
||
icon_wellfolder.addPixmap(QPixmap(GetImagePath() + "closeproject.png"), QIcon::Normal);
|
||
itemIndex->setIcon(0, icon_wellfolder);
|
||
item->addChild(itemIndex);//添加一级子节点
|
||
}
|
||
ui->treeWidget->expandItem(item);
|
||
|
||
}
|
||
if (jObj.value("shareProjects").isArray())
|
||
{
|
||
QJsonArray jarr = jObj.value("shareProjects").toArray();
|
||
|
||
QTreeWidgetItem *item = new QTreeWidgetItem();
|
||
item->setText(0, "与我共享项目");
|
||
item->setData(0, Qt::UserRole, "my_share_root"); // 存储额外数据,如ID
|
||
//item->setData(0, Qt::UserRole + 1, evaluationInfo.guid); // 存储额外数据,如ID
|
||
//
|
||
QIcon icon;
|
||
icon.addPixmap(QPixmap(GetImagePath() + "project.png"), QIcon::Selected);
|
||
icon.addPixmap(QPixmap(GetImagePath() + "project.png"), QIcon::Normal);
|
||
item->setIcon(0, icon);
|
||
// 这是一个根节点
|
||
ui->treeWidget->addTopLevelItem(item);
|
||
for (int i = 0; i < jarr.count(); i++)
|
||
{
|
||
if (!jarr[i].isObject())
|
||
continue;
|
||
QJsonObject obj = jarr[i].toObject();
|
||
|
||
QTreeWidgetItem *itemIndex = new QTreeWidgetItem();
|
||
itemIndex->setText(0, obj["projectName"].toString());
|
||
itemIndex->setData(0, Qt::UserRole, "project"); // 存储额外数据,如ID
|
||
itemIndex->setData(0, Qt::UserRole+1, obj["projectId"].toString()); // 存储额外数据,如ID
|
||
//
|
||
QIcon icon_wellfolder;
|
||
icon_wellfolder.addPixmap(QPixmap(GetImagePath() + "closeproject.png"), QIcon::Selected);
|
||
icon_wellfolder.addPixmap(QPixmap(GetImagePath() + "closeproject.png"), QIcon::Normal);
|
||
itemIndex->setIcon(0, icon_wellfolder);
|
||
item->addChild(itemIndex);//添加一级子节点
|
||
}
|
||
ui->treeWidget->expandItem(item);
|
||
}
|
||
|
||
//展开树图
|
||
//ui->treeWidget->expandItem(parent);
|
||
//itemIndex->setExpanded(true);
|
||
|
||
}
|
||
|
||
void CloudDataDlg::initTreeWells(QJsonObject jObj)
|
||
{
|
||
ui->btn_back->setVisible(true);
|
||
ui->label_pro->setText(jObj["projectName"].toString());
|
||
ui->treeWidget->clear();//清理数据
|
||
if (jObj.value("wells").isArray())
|
||
{
|
||
QTreeWidgetItem *item = new QTreeWidgetItem();
|
||
item->setText(0, "井组");
|
||
item->setData(0, Qt::UserRole, "root"); // 存储额外数据,如ID
|
||
item->setData(0, Qt::UserRole+1, jObj["projectId"].toString()); // 存储额外数据,如ID
|
||
//
|
||
QIcon icon;
|
||
icon.addPixmap(QPixmap(GetImagePath() + "wellfolder.png"), QIcon::Selected);
|
||
icon.addPixmap(QPixmap(GetImagePath() + "wellfolder.png"), QIcon::Normal);
|
||
item->setIcon(0, icon);
|
||
// 这是一个根节点
|
||
ui->treeWidget->addTopLevelItem(item);
|
||
|
||
QJsonArray jarr = jObj.value("wells").toArray();
|
||
for (int i = 0; i < jarr.count(); i++)
|
||
{
|
||
if (!jarr[i].isObject())
|
||
continue;
|
||
QJsonObject obj = jarr[i].toObject();
|
||
|
||
// 井
|
||
QTreeWidgetItem *itemJing = new QTreeWidgetItem();
|
||
itemJing->setText(0, obj["wellName"].toString());
|
||
itemJing->setData(0, Qt::UserRole + 1, obj["wellId"].toString()); // 存储额外数据,项目名
|
||
//
|
||
QIcon icon;
|
||
icon.addPixmap(QPixmap(GetImagePath() + "well.png"), QIcon::Selected);
|
||
icon.addPixmap(QPixmap(GetImagePath() + "well.png"), QIcon::Normal);
|
||
itemJing->setIcon(0, icon);
|
||
//
|
||
item->addChild(itemJing);//添加一级子节点
|
||
|
||
QJsonArray staArr = obj["stages"].toArray();
|
||
if (staArr.count()<=0)
|
||
continue;
|
||
QJsonObject staObj = staArr[0].toObject();
|
||
// QString staid = staObj["stageId"].toString();
|
||
// QString staname = staObj["stageName"].toString();
|
||
QJsonArray dataCat = staObj["dataCategories"].toArray();
|
||
if (dataCat.count() <= 0)
|
||
continue;
|
||
|
||
QTreeWidgetItem *itemJingCi = new QTreeWidgetItem();
|
||
itemJingCi->setText(0, staObj["stageName"].toString());
|
||
itemJingCi->setData(0, Qt::UserRole + 1, staObj["stageId"].toString()); // 存储额外数据,项目名
|
||
//
|
||
QIcon iconci;
|
||
iconci.addPixmap(QPixmap(GetImagePath() + "icon/WellRound.png"), QIcon::Selected);
|
||
iconci.addPixmap(QPixmap(GetImagePath() + "icon/WellRound.png"), QIcon::Normal);
|
||
itemJingCi->setIcon(0, iconci);
|
||
itemJing->addChild(itemJingCi);//添加一级子节点
|
||
|
||
for (int k =0;k < dataCat.count(); k++)
|
||
{
|
||
QJsonObject catObj = dataCat[k].toObject();
|
||
// QString s1 = catObj["categoryId"].toString();
|
||
// QString s2 = catObj["categoryName"].toString();
|
||
// QString s3 = catObj["dataType"].toString();
|
||
bool b = initTreeData(itemJingCi, staObj, catObj, "curve", "icon/AddLog.png", "icon/Log.png");
|
||
if (b)
|
||
continue;
|
||
initTreeData(itemJingCi, staObj, catObj, "array", "icon/tdt.png", "icon/tdt.png");
|
||
|
||
}
|
||
|
||
|
||
}
|
||
ui->treeWidget->expandItem(item);
|
||
}
|
||
}
|
||
|
||
bool CloudDataDlg::initTreeData(QTreeWidgetItem* itemJingCi, QJsonObject& jObjCi, QJsonObject catObj,
|
||
QString strDataType, QString strIcon1, QString strIcon2)
|
||
{
|
||
bool bret = false;
|
||
if (catObj["dataType"].toString() == strDataType)
|
||
{
|
||
QJsonArray sitem = catObj["items"].toArray();
|
||
// 曲线数量
|
||
int nCurveItem = sitem.count();
|
||
if (nCurveItem > 0)
|
||
{
|
||
//曲线
|
||
QTreeWidgetItem *itemCurve = new QTreeWidgetItem();
|
||
itemCurve->setText(0, "curve" == strDataType? "曲线":"波列数据");
|
||
itemCurve->setData(0, Qt::UserRole, strDataType); // 存储额外数据,如ID
|
||
QIcon iconCurve;
|
||
iconCurve.addPixmap(QPixmap(GetImagePath() + strIcon1), QIcon::Selected);
|
||
iconCurve.addPixmap(QPixmap(GetImagePath() + strIcon1), QIcon::Normal);
|
||
itemCurve->setIcon(0, iconCurve);
|
||
itemJingCi->addChild(itemCurve);
|
||
|
||
for (int m = 0; m < sitem.count(); m++)
|
||
{
|
||
QJsonObject tmpItem = sitem[m].toObject();
|
||
QString sName = "";
|
||
QString sTypeObj = "";
|
||
if ("curve" == strDataType)
|
||
{
|
||
sTypeObj = "curveObject";
|
||
sName = tmpItem["curveName"].toString();
|
||
}
|
||
else if ("array" == strDataType)
|
||
{
|
||
sTypeObj = "waveObject";
|
||
sName = tmpItem["arrayName"].toString();
|
||
}
|
||
|
||
QTreeWidgetItem *itemCurveLog = new QTreeWidgetItem();
|
||
itemCurveLog->setText(0, sName);
|
||
itemCurveLog->setData(0, Qt::UserRole, sTypeObj); // 存储额外数据,如ID
|
||
itemCurveLog->setData(0, Qt::UserRole + 1, tmpItem["metadataId"].toString()); // 存储额外数据,井次文件路径
|
||
//
|
||
QIcon iconLog;
|
||
iconLog.addPixmap(QPixmap(GetImagePath() + strIcon1), QIcon::Selected);
|
||
iconLog.addPixmap(QPixmap(GetImagePath() + strIcon2), QIcon::Normal);
|
||
itemCurveLog->setIcon(0, iconLog);
|
||
itemCurve->addChild(itemCurveLog);
|
||
}
|
||
}
|
||
bret = true;
|
||
}
|
||
return bret;
|
||
}
|
||
|
||
void CloudDataDlg::getList()
|
||
{
|
||
QString sapi = "/core/project/list";
|
||
ApiClient::getInstance()->get(sapi,
|
||
[this](const QJsonObject& response)
|
||
{
|
||
this->initTreeProjects(response);
|
||
},
|
||
[](const QString& error)
|
||
{
|
||
qDebug() << "Failed to allocate hours:" << error;
|
||
// 可以添加错误提示
|
||
});
|
||
}
|
||
|
||
void CloudDataDlg::getWells(QString projectId)
|
||
{
|
||
QString sapi = "/core/project/tree?projectId=" + projectId;
|
||
ApiClient::getInstance()->get(sapi,
|
||
[this](const QJsonObject& response)
|
||
{
|
||
this->initTreeWells(response);
|
||
},
|
||
[](const QString& error)
|
||
{
|
||
qDebug() << "Failed to allocate hours:" << error;
|
||
// 可以添加错误提示
|
||
});
|
||
}
|
||
|
||
void CloudDataDlg::on_btn_back_clicked()
|
||
{
|
||
this->getList();
|
||
}
|
||
|
||
void CloudDataDlg::on_btn_import_clicked()
|
||
{
|
||
if (!m_projectWidgets)
|
||
return;
|
||
|
||
QString strSlfName = "";
|
||
QString strWellName = "";
|
||
QString strLeft = m_projectWidgets->getLeftTreeString();
|
||
if (strLeft.length() > 0)
|
||
{
|
||
QStringList list = strLeft.split("#@@#");//QString字符串分割函数
|
||
if (list.size() > 3)
|
||
{
|
||
strSlfName = list[0];
|
||
strWellName = list[1];
|
||
}
|
||
}
|
||
else {
|
||
QMessageBox::warning(this, "提示", "请先选中导入到的目标井次!");
|
||
return;
|
||
}
|
||
if (strSlfName == "" || strWellName == "")
|
||
{
|
||
QMessageBox::warning(this, "提示", "请先选中导入到的目标井次!");
|
||
return;
|
||
}
|
||
QVector<QString> vecId;
|
||
QMap<QString, QVector<QString>> mapSelect;
|
||
// 同时记录名称,方便回调中使用
|
||
QMap<QString, QString> mapIdToName;
|
||
QMap<QString, QString> mapIdToType;
|
||
foreach(QTreeWidgetItem *pItem, ui->treeWidget->selectedItems())
|
||
{
|
||
QTreeWidgetItem *parentItem = pItem->parent()->parent(); // 上两层目录是井次
|
||
if (parentItem)
|
||
{
|
||
QString strType = pItem->data(0, Qt::UserRole).toString();
|
||
QString strId = pItem->data(0, Qt::UserRole + 1).toString();
|
||
QString strName = pItem->text(0);
|
||
vecId << strId;
|
||
mapIdToName[strId] = strName;
|
||
mapIdToType[strId] = strType;
|
||
qDebug() << "选择:" << strType << "," << strId << "," << strName;
|
||
if (mapSelect.contains(strType))
|
||
{
|
||
mapSelect[strType].push_back(strId);
|
||
}
|
||
else
|
||
{
|
||
QVector<QString> v;
|
||
v << strId;
|
||
mapSelect.insert(strType, v);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (vecId.isEmpty())
|
||
{
|
||
QMessageBox::warning(this, "提示", "请选择要导入的数据!");
|
||
return;
|
||
}
|
||
|
||
// 禁用按钮,防止重复点击
|
||
ui->btn_import->setEnabled(false);
|
||
ui->btn_import->setText("导入中...");
|
||
|
||
// 批量异步导入
|
||
importCloudData(vecId, mapSelect,
|
||
[this, strSlfName, strWellName, mapIdToName, mapIdToType](const QVector<CloudImportResult>& results)
|
||
{
|
||
// 恢复按钮状态
|
||
this->ui->btn_import->setEnabled(true);
|
||
this->ui->btn_import->setText("导入");
|
||
|
||
qDebug() << "===== 云端导入完成,共" << results.size() << "条数据 =====";
|
||
for (const auto& r : results)
|
||
{
|
||
qDebug() << " ID:" << r.id
|
||
<< "类型:" << r.dataType
|
||
<< "名称:" << r.dataName
|
||
<< "数据量:" << r.data.size() << "个float";
|
||
}
|
||
|
||
if (results.isEmpty())
|
||
{
|
||
QMessageBox::warning(this, "提示", "导入失败,未获取到有效数据!");
|
||
return;
|
||
}
|
||
|
||
// TODO: 在此将 results 写入 SLF 文件
|
||
// CMemRdWt* logio = new CMemRdWt();
|
||
// logio->Open(strSlfName.toStdString().c_str(), CSlfIO::modeReadWrite);
|
||
// ... 写入曲线/波列数据 ...
|
||
// delete logio;
|
||
|
||
QString msg = QString("导入完成!共 %1 条数据").arg(results.size());
|
||
QMessageBox::information(this, "提示", msg);
|
||
}
|
||
);
|
||
}
|
||
|
||
// 异步获取单个 metadataId 的数据
|
||
void CloudDataDlg::fetchCloudData(const QString& metadataId, const QString& dataType, const QString& dataName,
|
||
std::function<void(const CloudImportResult&)> onSuccess,
|
||
std::function<void(const QString&)> onFailed)
|
||
{
|
||
// 根据数据类型构造 API 路径
|
||
// curveObject: /core/metadata/{id}/curve-data
|
||
// waveObject: /core/metadata/{id}/array-data
|
||
QString apiPath;
|
||
if (dataType == "curveObject")
|
||
{
|
||
apiPath = "/core/metadata/" + metadataId + "/curve-data";
|
||
}
|
||
else if (dataType == "waveObject")
|
||
{
|
||
apiPath = "/core/metadata/" + metadataId + "/array-data";
|
||
}
|
||
else
|
||
{
|
||
// 未知类型,通用下载路径
|
||
apiPath = "/core/metadata/" + metadataId + "/data";
|
||
}
|
||
|
||
qDebug() << "fetchCloudData: id=" << metadataId << "type=" << dataType << "name=" << dataName;
|
||
|
||
ApiClient::getInstance()->getBinary(apiPath,
|
||
[metadataId, dataType, dataName, onSuccess, onFailed](const QByteArray& rawData)
|
||
{
|
||
// 将 QByteArray 转为 QVector<float>
|
||
int floatCount = rawData.size() / sizeof(float);
|
||
const float* pFloat = reinterpret_cast<const float*>(rawData.constData());
|
||
|
||
CloudImportResult result;
|
||
result.id = metadataId;
|
||
result.dataType = dataType;
|
||
result.dataName = dataName;
|
||
result.data.resize(floatCount);
|
||
memcpy(result.data.data(), pFloat, floatCount * sizeof(float));
|
||
|
||
qDebug() << "fetchCloudData 成功: id=" << metadataId
|
||
<< "bytes=" << rawData.size()
|
||
<< "floats=" << floatCount;
|
||
|
||
if (onSuccess) onSuccess(result);
|
||
},
|
||
[metadataId, onFailed](const QString& error)
|
||
{
|
||
qDebug() << "fetchCloudData 失败: id=" << metadataId << "error=" << error;
|
||
if (onFailed) onFailed(error);
|
||
}
|
||
);
|
||
}
|
||
|
||
// 批量异步导入
|
||
void CloudDataDlg::importCloudData(const QVector<QString>& vecId, const QMap<QString, QVector<QString>>& mapSelect,
|
||
std::function<void(const QVector<CloudImportResult>&)> onAllDone)
|
||
{
|
||
// 收集所有需要请求的 (id, type, name)
|
||
struct PendingItem { QString id; QString type; QString name; };
|
||
QVector<PendingItem> pendingList;
|
||
|
||
// 从 mapSelect 中提取 id 和 type
|
||
for (auto it = mapSelect.begin(); it != mapSelect.end(); ++it)
|
||
{
|
||
const QString& type = it.key();
|
||
for (const QString& id : it.value())
|
||
{
|
||
// 从 treeWidget 中查找对应的 name
|
||
QString name = "";
|
||
// 遍历 treeWidget 查找匹配的 item
|
||
QList<QTreeWidgetItem*> items = ui->treeWidget->findItems(
|
||
QString(), Qt::MatchContains | Qt::MatchRecursive, 0);
|
||
// 用 selectedItems 更直接
|
||
foreach(QTreeWidgetItem *pItem, ui->treeWidget->selectedItems())
|
||
{
|
||
QString itemId = pItem->data(0, Qt::UserRole + 1).toString();
|
||
QString itemType = pItem->data(0, Qt::UserRole).toString();
|
||
if (itemId == id && itemType == type)
|
||
{
|
||
name = pItem->text(0);
|
||
break;
|
||
}
|
||
}
|
||
pendingList.append({ id, type, name });
|
||
}
|
||
}
|
||
|
||
if (pendingList.isEmpty())
|
||
{
|
||
if (onAllDone) onAllDone(QVector<CloudImportResult>());
|
||
return;
|
||
}
|
||
|
||
// 使用共享状态跟踪进度
|
||
int totalCount = pendingList.size();
|
||
QVector<CloudImportResult>* results = new QVector<CloudImportResult>();
|
||
int* failCount = new int(0);
|
||
|
||
for (int i = 0; i < pendingList.size(); i++)
|
||
{
|
||
const auto& item = pendingList[i];
|
||
|
||
fetchCloudData(item.id, item.type, item.name,
|
||
[results, failCount, totalCount, onAllDone](const CloudImportResult& result)
|
||
{
|
||
results->append(result);
|
||
|
||
// 检查是否全部完成
|
||
if (results->size() + (*failCount) >= totalCount)
|
||
{
|
||
QVector<CloudImportResult> finalResults = *results;
|
||
delete results;
|
||
delete failCount;
|
||
if (onAllDone) onAllDone(finalResults);
|
||
}
|
||
},
|
||
[results, failCount, totalCount, onAllDone](const QString& error)
|
||
{
|
||
(*failCount)++;
|
||
|
||
qDebug() << "导入失败:" << error;
|
||
|
||
// 检查是否全部完成
|
||
if (results->size() + (*failCount) >= totalCount)
|
||
{
|
||
QVector<CloudImportResult> finalResults = *results;
|
||
delete results;
|
||
delete failCount;
|
||
if (onAllDone) onAllDone(finalResults);
|
||
}
|
||
}
|
||
);
|
||
}
|
||
}
|
||
|
||
void CloudDataDlg::onItemDoubleClicked(QTreeWidgetItem* item, int index)
|
||
{
|
||
QString strTag = item->data(0, Qt::UserRole).toString();
|
||
if ("project" == strTag)
|
||
{
|
||
QString strProId = item->data(0, Qt::UserRole+1).toString();
|
||
this->getWells(strProId);
|
||
}
|
||
}
|
||
|
||
void CloudDataDlg::OnSelectLineStyleChanged(int style,int lineWidth)
|
||
{
|
||
|
||
}
|
||
void CloudDataDlg::onEnter()
|
||
{
|
||
ApiClient::getInstance()->login("Test1", "Test123456",
|
||
[this](const QJsonObject& response)
|
||
{
|
||
this->getList();
|
||
},
|
||
[](const QString& error)
|
||
{
|
||
qDebug() << "Failed to allocate hours:" << error;
|
||
// 可以添加错误提示
|
||
});
|
||
|
||
}
|
||
|
||
void CloudDataDlg::paintEvent(QPaintEvent *pevt)
|
||
{
|
||
QDialog::paintEvent(pevt);
|
||
}
|