2026-01-30 18:36:55 +08:00
|
|
|
|
#include "dataSourceDlg.h"
|
|
|
|
|
|
#include "ui_dataSourceDlg.h"
|
|
|
|
|
|
#include <QStandardItemModel>
|
2026-02-03 11:07:48 +08:00
|
|
|
|
#include <QStack>
|
2026-01-30 18:36:55 +08:00
|
|
|
|
#include "structDataSource.h"
|
|
|
|
|
|
#include "instance/extraPropertyManager.h"
|
2026-02-03 11:07:48 +08:00
|
|
|
|
#include "propertyType/dataSourceType.h"
|
|
|
|
|
|
#include <QTimer>
|
2026-01-30 18:36:55 +08:00
|
|
|
|
#include "global.h"
|
|
|
|
|
|
|
|
|
|
|
|
DataSourceDlg::DataSourceDlg(QWidget *parent)
|
|
|
|
|
|
: QDialog(parent)
|
|
|
|
|
|
, ui(new Ui::dataSourceDlg)
|
|
|
|
|
|
,_treeModel(nullptr)
|
|
|
|
|
|
,m_currentCategoryItem(nullptr)
|
|
|
|
|
|
,_pExtraProManager(nullptr)
|
2026-02-03 11:07:48 +08:00
|
|
|
|
,_curProperty(nullptr)
|
2026-01-30 18:36:55 +08:00
|
|
|
|
{
|
|
|
|
|
|
ui->setupUi(this);
|
2026-02-03 11:07:48 +08:00
|
|
|
|
setModal(true);
|
2026-01-30 18:36:55 +08:00
|
|
|
|
this->setWindowFlags(Qt::FramelessWindowHint | windowFlags());
|
2026-02-03 11:07:48 +08:00
|
|
|
|
//setAttribute(Qt::WA_DeleteOnClose);
|
2026-01-30 18:36:55 +08:00
|
|
|
|
initial();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DataSourceDlg::~DataSourceDlg()
|
|
|
|
|
|
{
|
|
|
|
|
|
delete ui;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DataSourceDlg::initial()
|
|
|
|
|
|
{
|
|
|
|
|
|
connect(ui->btn_ok,&QPushButton::clicked,this,&DataSourceDlg::onOkClicked);
|
|
|
|
|
|
connect(ui->btn_cancel,&QPushButton::clicked,this,&DataSourceDlg::onCancelClicked);
|
|
|
|
|
|
|
|
|
|
|
|
m_dataSource = new StructDataSource(this);
|
|
|
|
|
|
_treeModel = new QStandardItemModel(this);
|
|
|
|
|
|
_treeModel->setHorizontalHeaderLabels(QStringList() << "属性层级结构");
|
|
|
|
|
|
ui->treeView->setModel(_treeModel);
|
2026-02-03 11:07:48 +08:00
|
|
|
|
connect(ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged,
|
|
|
|
|
|
this, &DataSourceDlg::onTreeSelectionChanged);
|
|
|
|
|
|
|
|
|
|
|
|
connect(ui->listWidget, &QListWidget::itemClicked, this,&DataSourceDlg::onListWidgetClicked);
|
|
|
|
|
|
|
|
|
|
|
|
_pExtraProManager = new ExtraPropertyManager(this);
|
|
|
|
|
|
_pExtraProManager->initial();
|
|
|
|
|
|
|
|
|
|
|
|
loadData();
|
|
|
|
|
|
|
|
|
|
|
|
connect(this, &DataSourceDlg::listWidgetUpdated, this, [this]() {
|
|
|
|
|
|
if (!m_targetPropertyCode.isEmpty()) {
|
|
|
|
|
|
for (int i = 0; i < ui->listWidget->count(); ++i) {
|
|
|
|
|
|
QListWidgetItem* listItem = ui->listWidget->item(i);
|
|
|
|
|
|
if (listItem && listItem->text() == m_targetPropertyCode) {
|
|
|
|
|
|
ui->listWidget->setCurrentRow(i);
|
|
|
|
|
|
ui->listWidget->scrollToItem(listItem, QAbstractItemView::EnsureVisible);
|
|
|
|
|
|
emit ui->listWidget->itemClicked(listItem);
|
|
|
|
|
|
m_targetPropertyCode.clear();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-01-30 18:36:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DataSourceDlg::loadData()
|
|
|
|
|
|
{
|
|
|
|
|
|
if(_pExtraProManager)
|
|
|
|
|
|
m_dataSource->loadExtrapro(_pExtraProManager->geAlltProperty());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-03 11:07:48 +08:00
|
|
|
|
void DataSourceDlg::showDlg(DataSourceType tpe)
|
2026-01-30 18:36:55 +08:00
|
|
|
|
{
|
|
|
|
|
|
if(_pExtraProManager)
|
|
|
|
|
|
{
|
2026-02-03 11:07:48 +08:00
|
|
|
|
//show();
|
2026-01-30 18:36:55 +08:00
|
|
|
|
clearItems();
|
|
|
|
|
|
auto& mapExtra = m_dataSource->allProperties;
|
|
|
|
|
|
QStandardItem* root = _treeModel->invisibleRootItem();
|
|
|
|
|
|
for(auto& pro:mapExtra){
|
|
|
|
|
|
QStandardItem* propertyItem = new QStandardItem();
|
|
|
|
|
|
addItemToView(pro,"name",root,propertyItem);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ui->treeView->expandAll();
|
2026-02-03 11:07:48 +08:00
|
|
|
|
|
|
|
|
|
|
if(!tpe.sCode.isEmpty()){
|
|
|
|
|
|
expandToNodeByCode(tpe.sCode,_treeModel);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DataSourceType DataSourceDlg::getCurData()
|
|
|
|
|
|
{
|
|
|
|
|
|
DataSourceType type;
|
|
|
|
|
|
if(_curProperty){
|
|
|
|
|
|
type.sPara = _curProperty->data(Qt::UserRole).toString();
|
|
|
|
|
|
type.sCode = _curProperty->data(Qt::UserRole+1).toString();
|
2026-01-30 18:36:55 +08:00
|
|
|
|
}
|
2026-02-03 11:07:48 +08:00
|
|
|
|
return type;
|
2026-01-30 18:36:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DataSourceDlg::addItemToView(const ExtraProperty& property,
|
|
|
|
|
|
const QString& displayMode, // "name" 或 "tag"
|
|
|
|
|
|
QStandardItem* root,
|
|
|
|
|
|
QStandardItem* pItem)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 设置叶子节点的显示文本(使用name或tag)
|
|
|
|
|
|
if (displayMode == "name") {
|
|
|
|
|
|
pItem->setText(property.name.isEmpty() ? "未命名属性" : property.name);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
pItem->setText(property.tag.isEmpty() ? "unknown_property" : property.tag);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 在叶子节点存储完整的属性信息
|
|
|
|
|
|
QVariantMap propertyData;
|
|
|
|
|
|
propertyData["property"] = QVariant::fromValue(property);
|
|
|
|
|
|
propertyData["displayMode"] = displayMode;
|
|
|
|
|
|
propertyData["code"] = property.code;
|
|
|
|
|
|
pItem->setData(propertyData, Qt::UserRole + 1);
|
|
|
|
|
|
|
|
|
|
|
|
QVector<ExtraPropertyLevelInfo> levels = {
|
|
|
|
|
|
{(displayMode == "name") ? property.grid_name : property.grid_tag,
|
|
|
|
|
|
property.grid_name, property.grid_tag, true,
|
|
|
|
|
|
(displayMode == "name") ? "未命名电网" : "unknown_grid"},
|
|
|
|
|
|
|
|
|
|
|
|
{(displayMode == "name") ? property.zone_name : property.zone_tag,
|
|
|
|
|
|
property.zone_name, property.zone_tag, true,
|
|
|
|
|
|
(displayMode == "name") ? "未命名区域" : "unknown_zone"},
|
|
|
|
|
|
|
|
|
|
|
|
{(displayMode == "name") ? property.station_name : property.station_tag,
|
|
|
|
|
|
property.station_name, property.station_tag, true,
|
|
|
|
|
|
(displayMode == "name") ? "未命名站点" : "unknown_station"},
|
|
|
|
|
|
|
|
|
|
|
|
{property.currentLevel,
|
|
|
|
|
|
property.currentLevel, property.currentLevel, false,
|
|
|
|
|
|
(displayMode == "name") ? "通用层级" : "common_level"},
|
|
|
|
|
|
|
|
|
|
|
|
{(displayMode == "name") ? property.bay_name : property.bay_tag,
|
|
|
|
|
|
property.bay_name, property.bay_tag, false,
|
|
|
|
|
|
(displayMode == "name") ? "间隔" : "bay"},
|
|
|
|
|
|
|
|
|
|
|
|
{property.component_name.isEmpty() ?
|
|
|
|
|
|
(displayMode == "name") ? "未命名设备" : property.component_uuid.toString() :
|
|
|
|
|
|
(displayMode == "name") ? property.component_name : property.component_uuid.toString(),
|
|
|
|
|
|
property.component_name, property.component_uuid.toString(), true,
|
|
|
|
|
|
(displayMode == "name") ? "未命名设备" : "unknown_component"}
|
|
|
|
|
|
};
|
2026-02-03 11:07:48 +08:00
|
|
|
|
|
|
|
|
|
|
QStandardItem* currentParent = root;
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < levels.size(); ++i) {
|
|
|
|
|
|
const auto& level = levels[i];
|
|
|
|
|
|
bool isRequired = level.isRequired;
|
|
|
|
|
|
bool isEmpty = (displayMode == "name") ?
|
|
|
|
|
|
(level.nameValue.isEmpty() && level.displayText.isEmpty()) :
|
|
|
|
|
|
(level.tagValue.isEmpty() && level.displayText.isEmpty());
|
|
|
|
|
|
|
|
|
|
|
|
if (!isRequired && isEmpty) {
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 确定显示文本
|
|
|
|
|
|
QString displayText = level.displayText;
|
|
|
|
|
|
bool isMissing = false;
|
|
|
|
|
|
|
|
|
|
|
|
if (displayText.isEmpty()) {
|
|
|
|
|
|
if (isRequired) {
|
|
|
|
|
|
displayText = level.placeholder;
|
|
|
|
|
|
isMissing = true;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 可选层级为空,跳过
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 查找当前层级是否已存在
|
|
|
|
|
|
QStandardItem* foundChild = nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
for (int row = 0; row < currentParent->rowCount(); ++row) {
|
|
|
|
|
|
QStandardItem* child = currentParent->child(row, 0);
|
|
|
|
|
|
if (child && child->text() == displayText) {
|
|
|
|
|
|
// 检查是否为同一层级
|
|
|
|
|
|
QVariantMap childData = child->data(Qt::UserRole + 1).toMap();
|
|
|
|
|
|
int childLevelIndex = childData["levelIndex"].toInt();
|
|
|
|
|
|
|
|
|
|
|
|
if (childLevelIndex == static_cast<int>(i)) {
|
|
|
|
|
|
foundChild = child;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (foundChild) {
|
|
|
|
|
|
currentParent = foundChild;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
QStandardItem* newNode = new QStandardItem(displayText);
|
|
|
|
|
|
QVariantMap levelData;
|
|
|
|
|
|
levelData["levelIndex"] = static_cast<int>(i);
|
|
|
|
|
|
levelData["levelType"] = getLevelType(i);
|
|
|
|
|
|
|
|
|
|
|
|
newNode->setData(levelData, Qt::UserRole + 1);
|
|
|
|
|
|
currentParent->appendRow(newNode);
|
|
|
|
|
|
currentParent = newNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 现在currentParent是component节点
|
|
|
|
|
|
// 处理group层级(第7层)
|
|
|
|
|
|
QStandardItem* groupItem = processGroupLevel(currentParent, property);
|
|
|
|
|
|
|
|
|
|
|
|
// 处理category层级(在group下)
|
|
|
|
|
|
processCategoryLevel(groupItem, property);
|
2026-01-30 18:36:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DataSourceDlg::onOkClicked()
|
|
|
|
|
|
{
|
2026-02-03 11:07:48 +08:00
|
|
|
|
/*if(_curTargetHandel){
|
|
|
|
|
|
if(_curProperty){
|
|
|
|
|
|
DataSourceType type;
|
|
|
|
|
|
_curTargetHandel->setVar(QVariant::fromValue(type));
|
|
|
|
|
|
}
|
|
|
|
|
|
}*/
|
|
|
|
|
|
accept();
|
2026-01-30 18:36:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DataSourceDlg::onCancelClicked()
|
|
|
|
|
|
{
|
2026-02-03 11:07:48 +08:00
|
|
|
|
reject();
|
2026-01-30 18:36:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DataSourceDlg::onTreeSelectionChanged(const QModelIndex& current, const QModelIndex& previous) {
|
|
|
|
|
|
Q_UNUSED(previous);
|
|
|
|
|
|
|
2026-02-03 11:07:48 +08:00
|
|
|
|
clearPropertyList();
|
|
|
|
|
|
|
2026-01-30 18:36:55 +08:00
|
|
|
|
if (!current.isValid()) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QStandardItem* item = _treeModel->itemFromIndex(current);
|
|
|
|
|
|
if (!item) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QVariantMap itemData = item->data(Qt::UserRole + 1).toMap();
|
|
|
|
|
|
QString levelType = itemData.value("levelType", "").toString();
|
|
|
|
|
|
|
|
|
|
|
|
if (levelType == "category") {
|
|
|
|
|
|
// 点击分类节点,从category节点获取属性
|
|
|
|
|
|
loadCategoryProperties(item);
|
2026-02-03 11:07:48 +08:00
|
|
|
|
|
|
|
|
|
|
// 检查是否需要选中特定的listWidgetItem
|
|
|
|
|
|
if (!m_targetPropertyCode.isEmpty()) {
|
|
|
|
|
|
// 在listWidget中查找并选中对应的item
|
|
|
|
|
|
for (int i = 0; i < ui->listWidget->count(); ++i) {
|
|
|
|
|
|
QListWidgetItem* listItem = ui->listWidget->item(i);
|
|
|
|
|
|
if (listItem && listItem->text() == m_targetPropertyCode) {
|
|
|
|
|
|
ui->listWidget->setCurrentRow(i);
|
|
|
|
|
|
ui->listWidget->scrollToItem(listItem, QAbstractItemView::EnsureVisible);
|
|
|
|
|
|
|
|
|
|
|
|
// 触发listWidget的itemClicked信号
|
|
|
|
|
|
emit ui->listWidget->itemClicked(listItem);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
m_targetPropertyCode.clear(); // 清空目标code
|
2026-01-30 18:36:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-03 11:07:48 +08:00
|
|
|
|
void DataSourceDlg::onListWidgetClicked(QListWidgetItem* pItem)
|
|
|
|
|
|
{
|
|
|
|
|
|
QString sPara = pItem->data(Qt::UserRole).toString();
|
|
|
|
|
|
ui->listWidget_select->clear();
|
|
|
|
|
|
QListWidgetItem* pCur = new QListWidgetItem(pItem->text()+":"+sPara);
|
|
|
|
|
|
pCur->setData(Qt::UserRole,sPara);
|
|
|
|
|
|
pCur->setData(Qt::UserRole+1,pItem->text());
|
|
|
|
|
|
ui->listWidget_select->addItem(pCur);
|
|
|
|
|
|
_curProperty = pCur;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-30 18:36:55 +08:00
|
|
|
|
void DataSourceDlg::clearPropertyList()
|
|
|
|
|
|
{
|
|
|
|
|
|
ui->listWidget->clear();
|
2026-02-03 11:07:48 +08:00
|
|
|
|
ui->listWidget_select->clear();
|
2026-01-30 18:36:55 +08:00
|
|
|
|
m_currentCategoryItem = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DataSourceDlg::loadCategoryProperties(QStandardItem* categoryItem) {
|
|
|
|
|
|
m_currentCategoryItem = categoryItem;
|
|
|
|
|
|
|
|
|
|
|
|
// 从category节点获取属性列表
|
|
|
|
|
|
QVariantMap categoryData = categoryItem->data(Qt::UserRole + 1).toMap();
|
|
|
|
|
|
QVector<ExtraProperty> properties = categoryData["properties"].value<QVector<ExtraProperty>>();
|
|
|
|
|
|
|
|
|
|
|
|
if (properties.isEmpty()) {
|
|
|
|
|
|
// 如果没有属性,从DataManager重新获取
|
|
|
|
|
|
properties = getCategoryPropertiesFromDataManager(categoryData);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (properties.isEmpty()) {
|
|
|
|
|
|
clearItems();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-03 11:07:48 +08:00
|
|
|
|
QTimer::singleShot(50, this, [this,properties]() {
|
|
|
|
|
|
updatePropertyList(properties);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-01-30 18:36:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QVector<ExtraProperty> DataSourceDlg::getCategoryPropertiesFromDataManager(const QVariantMap& categoryData) {
|
|
|
|
|
|
QString groupTag = categoryData.value("groupTag").toString();
|
|
|
|
|
|
QString modelName = categoryData.value("modelName").toString();
|
|
|
|
|
|
QString paraType = categoryData.value("paraType").toString();
|
|
|
|
|
|
QString sourceType = categoryData.value("sourceType").toString();
|
|
|
|
|
|
QString componentUuid = categoryData.value("component_uuid").toString();
|
|
|
|
|
|
|
|
|
|
|
|
QVector<ExtraProperty> result;
|
|
|
|
|
|
|
|
|
|
|
|
for (auto it = m_dataSource->allProperties.begin();
|
|
|
|
|
|
it != m_dataSource->allProperties.end(); ++it) {
|
|
|
|
|
|
const ExtraProperty& prop = it.value();
|
|
|
|
|
|
|
|
|
|
|
|
bool match = (prop.group_tag == groupTag) &&
|
|
|
|
|
|
(prop.sourceType == sourceType) &&
|
|
|
|
|
|
(prop.type_tag == paraType) &&
|
|
|
|
|
|
(prop.component_uuid.toString() == componentUuid);
|
|
|
|
|
|
|
|
|
|
|
|
if (sourceType == "property") {
|
|
|
|
|
|
match = match && (prop.sourceConfig.value("modelName").toString() == modelName);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (match) {
|
|
|
|
|
|
result.append(prop);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-03 11:07:48 +08:00
|
|
|
|
void DataSourceDlg::updateCategoryProperties(QStandardItem* categoryItem,
|
|
|
|
|
|
const ExtraProperty& property) {
|
|
|
|
|
|
QVariantMap categoryData = categoryItem->data(Qt::UserRole + 1).toMap();
|
|
|
|
|
|
QVector<ExtraProperty> properties = categoryData["properties"].value<QVector<ExtraProperty>>();
|
|
|
|
|
|
|
|
|
|
|
|
// 检查属性是否已存在
|
|
|
|
|
|
bool exists = false;
|
|
|
|
|
|
for (const auto& prop : properties) {
|
|
|
|
|
|
if (prop.code == property.code) {
|
|
|
|
|
|
exists = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!exists) {
|
|
|
|
|
|
properties.append(property);
|
|
|
|
|
|
categoryData["properties"] = QVariant::fromValue(properties);
|
|
|
|
|
|
|
|
|
|
|
|
int newCount = properties.size();
|
|
|
|
|
|
categoryData["propertyCount"] = newCount;
|
|
|
|
|
|
|
|
|
|
|
|
// 更新显示文本
|
|
|
|
|
|
QString baseName = property.type_name;
|
|
|
|
|
|
categoryItem->setText(QString("%1 (%2)").arg(baseName).arg(newCount));
|
|
|
|
|
|
|
|
|
|
|
|
// 更新工具提示
|
|
|
|
|
|
QString tooltip = QString("属性数量: %1")
|
|
|
|
|
|
.arg(newCount);
|
|
|
|
|
|
categoryItem->setToolTip(tooltip);
|
|
|
|
|
|
|
|
|
|
|
|
categoryItem->setData(categoryData, Qt::UserRole + 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QStandardItem* DataSourceDlg::processGroupLevel(QStandardItem* componentItem,
|
|
|
|
|
|
const ExtraProperty& property) {
|
|
|
|
|
|
QString groupDisplayText = (property.group_name.isEmpty() ?
|
|
|
|
|
|
property.group_tag : property.group_name);
|
|
|
|
|
|
|
|
|
|
|
|
if (groupDisplayText.isEmpty()) {
|
|
|
|
|
|
groupDisplayText = "未命名分组";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 查找group节点
|
|
|
|
|
|
for (int row = 0; row < componentItem->rowCount(); ++row) {
|
|
|
|
|
|
QStandardItem* child = componentItem->child(row, 0);
|
|
|
|
|
|
if (child) {
|
|
|
|
|
|
QVariantMap childData = child->data(Qt::UserRole + 1).toMap();
|
|
|
|
|
|
QString levelType = childData.value("levelType").toString();
|
|
|
|
|
|
|
|
|
|
|
|
if (levelType == "group") {
|
|
|
|
|
|
// 检查是否是同一个group
|
|
|
|
|
|
QString existingGroupTag = childData.value("groupTag", "").toString();
|
|
|
|
|
|
QString existingModelName = childData.value("modelName", "").toString();
|
|
|
|
|
|
QString propertyModelName = property.sourceConfig.value("modelName").toString();
|
|
|
|
|
|
|
|
|
|
|
|
if (existingGroupTag == property.group_tag) {
|
|
|
|
|
|
if (property.sourceType == "property") {
|
|
|
|
|
|
// 对于property类型,还需要检查modelName
|
|
|
|
|
|
if (existingModelName == propertyModelName) {
|
|
|
|
|
|
return child;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 对于measurement类型,只需要groupTag匹配
|
|
|
|
|
|
return child;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建新的group节点
|
|
|
|
|
|
QStandardItem* groupItem = new QStandardItem(groupDisplayText);
|
|
|
|
|
|
QVariantMap groupData;
|
|
|
|
|
|
groupData["levelIndex"] = 6; // 第7层
|
|
|
|
|
|
groupData["levelType"] = "group";
|
|
|
|
|
|
groupData["groupName"] = property.group_name;
|
|
|
|
|
|
groupData["groupTag"] = property.group_tag;
|
|
|
|
|
|
groupData["sourceType"] = property.sourceType;
|
|
|
|
|
|
|
|
|
|
|
|
if (property.sourceType == "property") {
|
|
|
|
|
|
groupData["modelName"] = property.sourceConfig.value("modelName");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
groupData["properties"] = QVariant::fromValue(QVector<ExtraProperty>());
|
|
|
|
|
|
groupItem->setData(groupData, Qt::UserRole + 1);
|
|
|
|
|
|
|
|
|
|
|
|
// 设置工具提示
|
|
|
|
|
|
QString tooltip = QString("分组: %1\n类型: %2")
|
|
|
|
|
|
.arg(groupDisplayText)
|
|
|
|
|
|
.arg(property.sourceType == "property" ? "属性" : "量测");
|
|
|
|
|
|
groupItem->setToolTip(tooltip);
|
|
|
|
|
|
|
|
|
|
|
|
componentItem->appendRow(groupItem);
|
|
|
|
|
|
return groupItem;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理category层级
|
|
|
|
|
|
void DataSourceDlg::processCategoryLevel(QStandardItem* groupItem,
|
|
|
|
|
|
const ExtraProperty& property) {
|
|
|
|
|
|
QString categoryName = property.type_name;
|
|
|
|
|
|
QString paraType = property.type_tag;
|
|
|
|
|
|
|
|
|
|
|
|
if (categoryName.isEmpty() || paraType.isEmpty()) {
|
|
|
|
|
|
qWarning() << "Invalid category or paraType for property:" << property.code;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 查找category节点
|
|
|
|
|
|
for (int row = 0; row < groupItem->rowCount(); ++row) {
|
|
|
|
|
|
QStandardItem* child = groupItem->child(row, 0);
|
|
|
|
|
|
if (child) {
|
|
|
|
|
|
QVariantMap childData = child->data(Qt::UserRole + 1).toMap();
|
|
|
|
|
|
QString levelType = childData.value("levelType").toString();
|
|
|
|
|
|
QString childParaType = childData.value("paraType", "").toString();
|
|
|
|
|
|
|
|
|
|
|
|
if (levelType == "category" && childParaType == paraType) {
|
|
|
|
|
|
// 找到对应的category节点,更新属性列表
|
|
|
|
|
|
updateCategoryProperties(child, property);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建新的category节点
|
|
|
|
|
|
QStandardItem* categoryItem = new QStandardItem(categoryName);
|
|
|
|
|
|
QVariantMap categoryData;
|
|
|
|
|
|
categoryData["levelType"] = "category";
|
|
|
|
|
|
categoryData["paraType"] = paraType;
|
|
|
|
|
|
categoryData["sourceType"] = property.sourceType;
|
|
|
|
|
|
categoryData["groupTag"] = property.group_tag;
|
|
|
|
|
|
categoryData["groupName"] = property.group_name;
|
|
|
|
|
|
|
|
|
|
|
|
if (property.sourceType == "property") {
|
|
|
|
|
|
categoryData["modelName"] = property.sourceConfig.value("modelName");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化属性列表
|
|
|
|
|
|
QVector<ExtraProperty> properties;
|
|
|
|
|
|
properties.append(property);
|
|
|
|
|
|
categoryData["properties"] = QVariant::fromValue(properties);
|
|
|
|
|
|
categoryData["propertyCount"] = 1;
|
|
|
|
|
|
|
|
|
|
|
|
categoryItem->setData(categoryData, Qt::UserRole + 1);
|
|
|
|
|
|
|
|
|
|
|
|
// 设置显示文本(包含数量)
|
|
|
|
|
|
categoryItem->setText(QString("%1 (1)").arg(categoryName));
|
|
|
|
|
|
|
|
|
|
|
|
// 设置工具提示
|
|
|
|
|
|
QString tooltip = QString("分类: %1\n参量类型: %2\n属性数量: 1")
|
|
|
|
|
|
.arg(categoryName)
|
|
|
|
|
|
.arg(categoryName);
|
|
|
|
|
|
categoryItem->setToolTip(tooltip);
|
|
|
|
|
|
|
|
|
|
|
|
groupItem->appendRow(categoryItem);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-30 18:36:55 +08:00
|
|
|
|
void DataSourceDlg::updatePropertyList(QVector<ExtraProperty> vec)
|
|
|
|
|
|
{
|
2026-02-03 11:07:48 +08:00
|
|
|
|
ui->listWidget->clear();
|
|
|
|
|
|
|
2026-01-30 18:36:55 +08:00
|
|
|
|
for(auto& pro:vec){
|
|
|
|
|
|
QListWidgetItem* pItem = new QListWidgetItem(pro.code);
|
2026-02-03 11:07:48 +08:00
|
|
|
|
pItem->setData(Qt::UserRole, pro.connect_para);
|
2026-01-30 18:36:55 +08:00
|
|
|
|
ui->listWidget->addItem(pItem);
|
|
|
|
|
|
}
|
2026-02-03 11:07:48 +08:00
|
|
|
|
|
|
|
|
|
|
QTimer::singleShot(50, this, [this]() {
|
|
|
|
|
|
emit listWidgetUpdated();
|
|
|
|
|
|
});
|
2026-01-30 18:36:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-03 11:07:48 +08:00
|
|
|
|
void DataSourceDlg::expandToNodeByCode(const QString& code, QStandardItemModel* model)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!model || code.isEmpty()) {
|
|
|
|
|
|
return;
|
2026-01-30 18:36:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-03 11:07:48 +08:00
|
|
|
|
// 设置目标code
|
|
|
|
|
|
m_targetPropertyCode = code;
|
2026-01-30 18:36:55 +08:00
|
|
|
|
|
2026-02-03 11:07:48 +08:00
|
|
|
|
// 查找节点
|
|
|
|
|
|
QStandardItem* targetNode = findCategoryNodeByPropertyCode(model->invisibleRootItem(), code);
|
2026-01-30 18:36:55 +08:00
|
|
|
|
|
2026-02-03 11:07:48 +08:00
|
|
|
|
if (!targetNode) {
|
|
|
|
|
|
qDebug() << "未找到code为" << code << "的节点";
|
|
|
|
|
|
m_targetPropertyCode.clear();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 展开路径
|
|
|
|
|
|
QList<QStandardItem*> path;
|
|
|
|
|
|
QStandardItem* current = targetNode;
|
|
|
|
|
|
|
|
|
|
|
|
while (current && current != model->invisibleRootItem()) {
|
|
|
|
|
|
path.prepend(current);
|
|
|
|
|
|
current = current->parent();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (QStandardItem* item : path) {
|
|
|
|
|
|
QModelIndex index = model->indexFromItem(item);
|
|
|
|
|
|
if (index.isValid()) {
|
|
|
|
|
|
ui->treeView->expand(index);
|
2026-01-30 18:36:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-03 11:07:48 +08:00
|
|
|
|
// 🔴 关键:阻塞currentChanged信号
|
|
|
|
|
|
QItemSelectionModel* selectionModel = ui->treeView->selectionModel();
|
|
|
|
|
|
if (selectionModel) {
|
|
|
|
|
|
selectionModel->blockSignals(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QModelIndex targetIndex = model->indexFromItem(targetNode);
|
2026-01-30 18:36:55 +08:00
|
|
|
|
|
2026-02-03 11:07:48 +08:00
|
|
|
|
// 设置当前项(这会触发currentChanged,但信号被阻塞了)
|
|
|
|
|
|
selectionModel->setCurrentIndex(targetIndex, QItemSelectionModel::ClearAndSelect);
|
|
|
|
|
|
|
|
|
|
|
|
// 手动调用处理函数
|
|
|
|
|
|
onTreeSelectionChanged(targetIndex, QModelIndex());
|
|
|
|
|
|
|
|
|
|
|
|
// 恢复信号
|
|
|
|
|
|
if (selectionModel) {
|
|
|
|
|
|
selectionModel->blockSignals(false);
|
2026-01-30 18:36:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-03 11:07:48 +08:00
|
|
|
|
// 滚动
|
|
|
|
|
|
ui->treeView->scrollTo(targetIndex, QAbstractItemView::EnsureVisible);
|
|
|
|
|
|
}
|
2026-01-30 18:36:55 +08:00
|
|
|
|
|
2026-02-03 11:07:48 +08:00
|
|
|
|
void DataSourceDlg::selectListItemByCode(const QString& code)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = 0; i < ui->listWidget->count(); ++i) {
|
|
|
|
|
|
QListWidgetItem* listItem = ui->listWidget->item(i);
|
|
|
|
|
|
if (listItem && listItem->text() == code) {
|
|
|
|
|
|
ui->listWidget->setCurrentRow(i);
|
|
|
|
|
|
ui->listWidget->scrollToItem(listItem, QAbstractItemView::EnsureVisible);
|
|
|
|
|
|
return;
|
2026-01-30 18:36:55 +08:00
|
|
|
|
}
|
2026-02-03 11:07:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-01-30 18:36:55 +08:00
|
|
|
|
|
2026-02-03 11:07:48 +08:00
|
|
|
|
QStandardItem* DataSourceDlg::findCategoryNodeByPropertyCode(QStandardItem* item, const QString& code)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!item) {
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QVariant itemData = item->data(Qt::UserRole + 1);
|
2026-01-30 18:36:55 +08:00
|
|
|
|
|
2026-02-03 11:07:48 +08:00
|
|
|
|
if (itemData.isValid() && itemData.canConvert<QVariantMap>()) {
|
|
|
|
|
|
QVariantMap dataMap = itemData.toMap();
|
|
|
|
|
|
|
|
|
|
|
|
// 检查当前节点是否是category节点
|
|
|
|
|
|
QString levelType = dataMap.value("levelType", "").toString();
|
|
|
|
|
|
|
|
|
|
|
|
if (levelType == "category") {
|
|
|
|
|
|
// 检查category节点的properties列表
|
|
|
|
|
|
if (dataMap.contains("properties")) {
|
|
|
|
|
|
QVector<ExtraProperty> properties = dataMap["properties"].value<QVector<ExtraProperty>>();
|
|
|
|
|
|
for (int i = 0; i < properties.size(); ++i) {
|
|
|
|
|
|
if (properties[i].code == code) {
|
|
|
|
|
|
return item; // 找到包含该属性的category节点
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-01-30 18:36:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-03 11:07:48 +08:00
|
|
|
|
// 递归搜索子节点
|
|
|
|
|
|
for (int row = 0; row < item->rowCount(); ++row) {
|
|
|
|
|
|
QStandardItem* child = item->child(row, 0);
|
|
|
|
|
|
QStandardItem* found = findCategoryNodeByPropertyCode(child, code);
|
|
|
|
|
|
if (found) {
|
|
|
|
|
|
return found;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
2026-01-30 18:36:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DataSourceDlg::clearItems()
|
|
|
|
|
|
{
|
|
|
|
|
|
if(_treeModel){
|
|
|
|
|
|
QStandardItem *root = _treeModel->invisibleRootItem(); //先清空model
|
|
|
|
|
|
int rowCount = root->rowCount();
|
|
|
|
|
|
if (rowCount > 0) {
|
|
|
|
|
|
_treeModel->removeRows(0, rowCount);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-02-03 11:07:48 +08:00
|
|
|
|
|
|
|
|
|
|
QString DataSourceDlg::getLevelType(int index) {
|
|
|
|
|
|
switch (index) {
|
|
|
|
|
|
case 0: return "电网";
|
|
|
|
|
|
case 1: return "区域";
|
|
|
|
|
|
case 2: return "站点";
|
|
|
|
|
|
case 3: return "电压等级";
|
|
|
|
|
|
case 4: return "间隔";
|
|
|
|
|
|
case 5: return "设备";
|
|
|
|
|
|
case 6: return "分组";
|
|
|
|
|
|
default: return "未知层级";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|