logplus/logPlus/CloudDataDlg.cpp

565 lines
17 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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);
}