diff --git a/diagramCavas/CMakeLists.txt b/diagramCavas/CMakeLists.txt index 679bddb..e7b8c61 100644 --- a/diagramCavas/CMakeLists.txt +++ b/diagramCavas/CMakeLists.txt @@ -131,7 +131,9 @@ set(DIAGRAMCAVAS_HEADER_FILES include/propertyType/CustomGadget.h include/propertyType/CustomType.h + include/propertyType/dataSourceType.h include/propertyType/PropertyTypeCustomization_CustomType.h + include/propertyType/propertyTypeCustomization_DataSourceType.h include/propertyType/pannelColorGadget.h ../common/include/httpInterface.h ../common/include/tools.h @@ -271,6 +273,7 @@ set(DIAGRAMCAVAS_SOURCE_FILES source/instance/extraPropertyManager.cpp source/propertyType/PropertyTypeCustomization_CustomType.cpp + source/propertyType/propertyTypeCustomization_DataSourceType.cpp source/propertyType/pannelColorGadget.cpp ../common/source/httpInterface.cpp ../common/source/baseProperty.cpp diff --git a/diagramCavas/include/baseDrawingPanel.h b/diagramCavas/include/baseDrawingPanel.h index 90d8094..66efcdf 100644 --- a/diagramCavas/include/baseDrawingPanel.h +++ b/diagramCavas/include/baseDrawingPanel.h @@ -62,7 +62,7 @@ protected: DesignerScene* m_pGraphicsScene; SelectorManager* m_pSelectorManager; StatusBar* m_pStatusBar; - FixedPortsModel* _pModel; + QPointer _pModel; DiagramMode _mode; QString _name; PowerEntity* _pEntity; //组态图拓扑对象 diff --git a/diagramCavas/include/dataSourceDlg.h b/diagramCavas/include/dataSourceDlg.h index 61b30f7..ccdb28a 100644 --- a/diagramCavas/include/dataSourceDlg.h +++ b/diagramCavas/include/dataSourceDlg.h @@ -13,6 +13,9 @@ class QStandardItem; struct ExtraProperty; class StructDataSource; class ExtraPropertyManager; +class QPropertyHandle; +struct DataSourceType; +class QListWidgetItem; class DataSourceDlg : public QDialog { @@ -24,31 +27,41 @@ public: void initial(); void loadData(); - void setExtraPropertyManager(ExtraPropertyManager* p) {_pExtraProManager = p;} - void showDlg(); + void showDlg(DataSourceType); + DataSourceType getCurData(); +signals: + void listWidgetUpdated(); public slots: void onOkClicked(); void onCancelClicked(); void onTreeSelectionChanged(const QModelIndex& current, const QModelIndex& previous); + void onListWidgetClicked(QListWidgetItem*); void addItemToView(const ExtraProperty& property, const QString& displayMode, // "name" 或 "tag" QStandardItem* root, QStandardItem* pItem); private: + QString getLevelType(int index); void clearItems(); void clearPropertyList(); void loadCategoryProperties(QStandardItem* categoryItem); QVector getCategoryPropertiesFromDataManager(const QVariantMap& categoryData); + void updateCategoryProperties(QStandardItem* categoryItem,const ExtraProperty& property); // 更新category节点的属性列表 + QStandardItem* processGroupLevel(QStandardItem* componentItem,const ExtraProperty& property); // 处理group层级 + void processCategoryLevel(QStandardItem* groupItem,const ExtraProperty& property); // 处理category层级 void updatePropertyList(QVector); - bool expandToPropertyByCode(const QString& propertyCode,const QString& displayMode); //根据编码展开到属性节点 - bool expandToNodeByNames(QStandardItem* rootItem,const QStringList& nodeNames); //根据已知名称展开到对应节点 + void expandToNodeByCode(const QString& code,QStandardItemModel* model); //根据属性code展开树到指定节点 + void selectListItemByCode(const QString& code); //在listWidget中选中指定code的项 + QStandardItem* findCategoryNodeByPropertyCode(QStandardItem* item, const QString& code); private: Ui::dataSourceDlg *ui; QStandardItemModel* _treeModel; QStandardItem* m_currentCategoryItem; //当前操作对象 ExtraPropertyManager* _pExtraProManager; //使用外部的manager StructDataSource* m_dataSource; + QListWidgetItem* _curProperty; //当前属性 + QString m_targetPropertyCode; //打开的目标code }; #endif diff --git a/diagramCavas/include/diagramCavas.h b/diagramCavas/include/diagramCavas.h index 44bd1cb..9f044f5 100644 --- a/diagramCavas/include/diagramCavas.h +++ b/diagramCavas/include/diagramCavas.h @@ -42,7 +42,6 @@ public: void passRecommmandHttpData(HttpRecommandInfo); //传递推荐列表数据 DiagramConnectSetting* getConnectSettingDlg() {return _connectSetting;} ExtraPropertyManager* getExtraPropertyManager() {return _extraPropertyManager;} - DataSourceDlg* getDataSourceDlg() {return _dataSourceDlg;} public: void initial(); signals: @@ -125,7 +124,6 @@ private: DataAccessor* _dataAccessor; StructDataPreviewDlg* _structDataPreviewDlg; ExtraPropertyManager* _extraPropertyManager; - DataSourceDlg* _dataSourceDlg; }; #endif diff --git a/diagramCavas/include/graphicsDataModel/fixedPortsModel.h b/diagramCavas/include/graphicsDataModel/fixedPortsModel.h index 01cd74c..984c6d0 100644 --- a/diagramCavas/include/graphicsDataModel/fixedPortsModel.h +++ b/diagramCavas/include/graphicsDataModel/fixedPortsModel.h @@ -7,6 +7,7 @@ #include #include #include +#include class BaseDrawingPanel; class DrawingPanel; @@ -138,8 +139,8 @@ public: QString pageName() const {return _pageName;} void activateModel() {Q_EMIT activatePage(_pageName);} //发送激活信号(点击) void startHttpRequest(); //开始请求数据(运行时) - void setCavas(DiagramCavas* p) {_cavas = p;} //设置所属顶层容器 - DiagramCavas* getCavas() {return _cavas;} + void setCavas(QPointer p) {_cavas = p;} //设置所属顶层容器 + DiagramCavas* getCavas(); QMap getProjectItems(){return _nodeItem;} QMap getBaseModelItems(){return _baseItem;} @@ -167,7 +168,7 @@ private: QMap _bayItem; //间隔对象 QString _pageName; - DiagramCavas* _cavas; + QPointer _cavas; DesignerScene* _scene; BaseDrawingPanel* _widget; //顶层widget HttpInterface* _Interface; diff --git a/diagramCavas/include/graphicsItem/graphicsBaseItem.h b/diagramCavas/include/graphicsItem/graphicsBaseItem.h index 0954c41..bd09dbf 100644 --- a/diagramCavas/include/graphicsItem/graphicsBaseItem.h +++ b/diagramCavas/include/graphicsItem/graphicsBaseItem.h @@ -11,6 +11,7 @@ #include #include #include +#include "propertyType/dataSourceType.h" //#include "graphicsItem/itemPort.h" enum ShapeType @@ -545,6 +546,7 @@ public: Q_PROPERTY(QString Name READ getName WRITE setName) Q_PROPERTY(QPointF Position READ getPosition WRITE setPosition) Q_PROPERTY(QRectF Size READ getSize WRITE setSize) + Q_PROPERTY(DataSourceType DataSourceType READ getDataSourceType WRITE setDataSourceType) public: GraphicsProjectModelItem(QGraphicsItem *parent); GraphicsProjectModelItem(const GraphicsProjectModelItem&); @@ -599,6 +601,8 @@ public: void setPosition(QPointF); QRectF getSize() const; void setSize(QRectF); + DataSourceType getDataSourceType() const; + void setDataSourceType(DataSourceType); protected: virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange, const QVariant&) override; virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent*) override; @@ -635,6 +639,8 @@ protected: QByteArray _curMonitorStateSvg; bool _curMonitorStateEnable; QMap _displaySetting; //显示设置 + + DataSourceType _sourceType; }; class GraphicsProjectModelGroup : public GraphicsProjectModelItem //工程模group diff --git a/diagramCavas/include/propertyType/dataSourceType.h b/diagramCavas/include/propertyType/dataSourceType.h new file mode 100644 index 0000000..6aa0bba --- /dev/null +++ b/diagramCavas/include/propertyType/dataSourceType.h @@ -0,0 +1,18 @@ +#ifndef DATASOURCETYPE_H +#define DATASOURCETYPE_H + +#include +#include + +struct DataSourceType { + QString sCode; + QString sPara; +}; + +static QDebug operator<<(QDebug debug, const DataSourceType& it) { + return debug << it.sCode <<":"<(new FixedPortsModel(pEntity)); _pModel->setTopWidget(this); m_pSelectorManager = new SelectorManager(_pModel,this); m_pGraphicsScene = new DesignerScene(_pModel,this); @@ -38,12 +38,17 @@ BaseDrawingPanel::BaseDrawingPanel(PowerEntity* pEntity,QWidget *parent,DiagramM _pModel->setScene(m_pGraphicsScene); connect(m_pGraphicsScene, &DesignerScene::selectionChanged, this, [&](){ QList selectedItems = m_pGraphicsScene->selectedItems(); - if(selectedItems.count() != 1) { - _pModel->getCavas()->onTargetSelected(_pPropertyProxy); - return; + if(_pModel){ + auto pCavas = _pModel->getCavas(); + if(pCavas){ + if(selectedItems.count() != 1) { + _pModel->getCavas()->onTargetSelected(_pPropertyProxy); + return; + } + GraphicsBaseItem *item = static_cast(selectedItems.first()); + _pModel->getCavas()->onTargetSelected(item); + } } - GraphicsBaseItem *item = static_cast(selectedItems.first()); - _pModel->getCavas()->onTargetSelected(item); }); m_pStatusBar = new StatusBar(this); diff --git a/diagramCavas/source/dataSourceDlg.cpp b/diagramCavas/source/dataSourceDlg.cpp index 4230f09..67e9a96 100644 --- a/diagramCavas/source/dataSourceDlg.cpp +++ b/diagramCavas/source/dataSourceDlg.cpp @@ -1,8 +1,11 @@ #include "dataSourceDlg.h" #include "ui_dataSourceDlg.h" #include +#include #include "structDataSource.h" #include "instance/extraPropertyManager.h" +#include "propertyType/dataSourceType.h" +#include #include "global.h" DataSourceDlg::DataSourceDlg(QWidget *parent) @@ -11,9 +14,12 @@ DataSourceDlg::DataSourceDlg(QWidget *parent) ,_treeModel(nullptr) ,m_currentCategoryItem(nullptr) ,_pExtraProManager(nullptr) + ,_curProperty(nullptr) { ui->setupUi(this); + setModal(true); this->setWindowFlags(Qt::FramelessWindowHint | windowFlags()); + //setAttribute(Qt::WA_DeleteOnClose); initial(); } @@ -31,6 +37,31 @@ void DataSourceDlg::initial() _treeModel = new QStandardItemModel(this); _treeModel->setHorizontalHeaderLabels(QStringList() << "属性层级结构"); ui->treeView->setModel(_treeModel); + 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; + } + } + } + }); + } void DataSourceDlg::loadData() @@ -39,11 +70,11 @@ void DataSourceDlg::loadData() m_dataSource->loadExtrapro(_pExtraProManager->geAlltProperty()); } -void DataSourceDlg::showDlg() +void DataSourceDlg::showDlg(DataSourceType tpe) { if(_pExtraProManager) { - show(); + //show(); clearItems(); auto& mapExtra = m_dataSource->allProperties; QStandardItem* root = _treeModel->invisibleRootItem(); @@ -53,9 +84,23 @@ void DataSourceDlg::showDlg() } ui->treeView->expandAll(); + + 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(); + } + return type; +} + void DataSourceDlg::addItemToView(const ExtraProperty& property, const QString& displayMode, // "name" 或 "tag" QStandardItem* root, @@ -102,29 +147,100 @@ void DataSourceDlg::addItemToView(const ExtraProperty& property, property.component_name, property.component_uuid.toString(), true, (displayMode == "name") ? "未命名设备" : "unknown_component"} }; + + 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(i)) { + foundChild = child; + break; + } + } + } + + if (foundChild) { + currentParent = foundChild; + } else { + QStandardItem* newNode = new QStandardItem(displayText); + QVariantMap levelData; + levelData["levelIndex"] = static_cast(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); } void DataSourceDlg::onOkClicked() { - hide(); + /*if(_curTargetHandel){ + if(_curProperty){ + DataSourceType type; + _curTargetHandel->setVar(QVariant::fromValue(type)); + } + }*/ + accept(); } void DataSourceDlg::onCancelClicked() { - hide(); + reject(); } void DataSourceDlg::onTreeSelectionChanged(const QModelIndex& current, const QModelIndex& previous) { Q_UNUSED(previous); + clearPropertyList(); + if (!current.isValid()) { - clearPropertyList(); return; } QStandardItem* item = _treeModel->itemFromIndex(current); if (!item) { - clearPropertyList(); return; } @@ -134,14 +250,42 @@ void DataSourceDlg::onTreeSelectionChanged(const QModelIndex& current, const QMo if (levelType == "category") { // 点击分类节点,从category节点获取属性 loadCategoryProperties(item); - }else{ - clearPropertyList(); + + // 检查是否需要选中特定的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 } } +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; +} + void DataSourceDlg::clearPropertyList() { ui->listWidget->clear(); + ui->listWidget_select->clear(); m_currentCategoryItem = nullptr; } @@ -162,7 +306,10 @@ void DataSourceDlg::loadCategoryProperties(QStandardItem* categoryItem) { return; } - updatePropertyList(properties); + QTimer::singleShot(50, this, [this,properties]() { + updatePropertyList(properties); + }); + } QVector DataSourceDlg::getCategoryPropertiesFromDataManager(const QVariantMap& categoryData) { @@ -195,122 +342,284 @@ QVector DataSourceDlg::getCategoryPropertiesFromDataManager(const return result; } +void DataSourceDlg::updateCategoryProperties(QStandardItem* categoryItem, + const ExtraProperty& property) { + QVariantMap categoryData = categoryItem->data(Qt::UserRole + 1).toMap(); + QVector properties = categoryData["properties"].value>(); + + // 检查属性是否已存在 + 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()); + 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 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); +} + void DataSourceDlg::updatePropertyList(QVector vec) { + ui->listWidget->clear(); + for(auto& pro:vec){ QListWidgetItem* pItem = new QListWidgetItem(pro.code); - pItem->setData(Qt::UserRole,pro.connect_para); + pItem->setData(Qt::UserRole, pro.connect_para); ui->listWidget->addItem(pItem); } + + QTimer::singleShot(50, this, [this]() { + emit listWidgetUpdated(); + }); } -bool DataSourceDlg::expandToPropertyByCode(const QString& propertyCode, - const QString& displayMode) { - // 在树中搜索对应编码的节点 - QStandardItemModel* model = qobject_cast(ui->treeView->model()); - if (!model) { - return false; +void DataSourceDlg::expandToNodeByCode(const QString& code, QStandardItemModel* model) +{ + if (!model || code.isEmpty()) { + return; } - QModelIndexList matches = model->match( - model->index(0, 0), - Qt::UserRole + 1, // 搜索用户数据 - QVariant(), // 任意值 - -1, // 搜索所有 - Qt::MatchRecursive | Qt::MatchContains - ); + // 设置目标code + m_targetPropertyCode = code; - for (const QModelIndex& index : matches) { - QStandardItem* item = model->itemFromIndex(index); - if (item) { - QVariantMap itemData = item->data(Qt::UserRole + 1).toMap(); + // 查找节点 + QStandardItem* targetNode = findCategoryNodeByPropertyCode(model->invisibleRootItem(), code); - // 检查是否是属性节点 - if (itemData.contains("property")) { - ExtraProperty property = itemData["property"].value(); - if (property.code == propertyCode) { - // 构建从根节点到该节点的路径 - QStringList nodeNames; - QModelIndex currentIndex = index; + if (!targetNode) { + qDebug() << "未找到code为" << code << "的节点"; + m_targetPropertyCode.clear(); + return; + } - while (currentIndex.isValid()) { - QStandardItem* currentItem = model->itemFromIndex(currentIndex); - if (currentItem) { - nodeNames.prepend(currentItem->text()); - } - currentIndex = currentIndex.parent(); + // 展开路径 + QList 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); + } + } + + // 🔴 关键:阻塞currentChanged信号 + QItemSelectionModel* selectionModel = ui->treeView->selectionModel(); + if (selectionModel) { + selectionModel->blockSignals(true); + } + + QModelIndex targetIndex = model->indexFromItem(targetNode); + + // 设置当前项(这会触发currentChanged,但信号被阻塞了) + selectionModel->setCurrentIndex(targetIndex, QItemSelectionModel::ClearAndSelect); + + // 手动调用处理函数 + onTreeSelectionChanged(targetIndex, QModelIndex()); + + // 恢复信号 + if (selectionModel) { + selectionModel->blockSignals(false); + } + + // 滚动 + ui->treeView->scrollTo(targetIndex, QAbstractItemView::EnsureVisible); +} + +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; + } + } +} + +QStandardItem* DataSourceDlg::findCategoryNodeByPropertyCode(QStandardItem* item, const QString& code) +{ + if (!item) { + return nullptr; + } + + QVariant itemData = item->data(Qt::UserRole + 1); + + if (itemData.isValid() && itemData.canConvert()) { + QVariantMap dataMap = itemData.toMap(); + + // 检查当前节点是否是category节点 + QString levelType = dataMap.value("levelType", "").toString(); + + if (levelType == "category") { + // 检查category节点的properties列表 + if (dataMap.contains("properties")) { + QVector properties = dataMap["properties"].value>(); + for (int i = 0; i < properties.size(); ++i) { + if (properties[i].code == code) { + return item; // 找到包含该属性的category节点 } - - // 去掉根节点 - if (!nodeNames.isEmpty()) { - nodeNames.removeFirst(); - } - - // 展开到该节点 - QStandardItem* rootItem = model->invisibleRootItem(); - return expandToNodeByNames(rootItem, nodeNames); } } } } - return false; -} - -bool DataSourceDlg::expandToNodeByNames(QStandardItem* rootItem, - const QStringList& nodeNames) { - if (!rootItem || nodeNames.isEmpty()) { - return false; - } - - QStandardItem* currentItem = rootItem; - QTreeView* treeView = ui->treeView; - - for (int i = 0; i < nodeNames.size(); ++i) { - const QString& targetName = nodeNames[i]; - bool found = false; - - // 在当前节点的子节点中查找 - for (int row = 0; row < currentItem->rowCount(); ++row) { - QStandardItem* childItem = currentItem->child(row, 0); - if (childItem && childItem->text() == targetName) { - // 展开当前节点 - QModelIndex currentIndex = currentItem->index(); - treeView->expand(currentIndex); - - // 如果是最后一层,选中该节点 - if (i == nodeNames.size() - 1) { - QModelIndex childIndex = childItem->index(); - treeView->scrollTo(childIndex); - treeView->selectionModel()->select( - childIndex, - QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows - ); - return true; - } - - // 继续查找下一层 - currentItem = childItem; - found = true; - break; - } - } - - if (!found) { - // 没有找到对应的节点 - qWarning() << "Node not found at level" << i << ":" << targetName; - - // 展开到已找到的层级 - if (currentItem != rootItem) { - QModelIndex currentIndex = currentItem->index(); - treeView->expand(currentIndex); - treeView->scrollTo(currentIndex); - } - return false; + // 递归搜索子节点 + for (int row = 0; row < item->rowCount(); ++row) { + QStandardItem* child = item->child(row, 0); + QStandardItem* found = findCategoryNodeByPropertyCode(child, code); + if (found) { + return found; } } - return true; + return nullptr; } void DataSourceDlg::clearItems() @@ -323,3 +632,17 @@ void DataSourceDlg::clearItems() } } } + +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 "未知层级"; + } +} + diff --git a/diagramCavas/source/diagramCavas.cpp b/diagramCavas/source/diagramCavas.cpp index 5ec4a7b..b4ed259 100644 --- a/diagramCavas/source/diagramCavas.cpp +++ b/diagramCavas/source/diagramCavas.cpp @@ -27,7 +27,10 @@ #include "monitorConfigDlg.h" #include "structDataPreviewDlg.h" #include "instance/extraPropertyManager.h" -#include "dataSourceDlg.h" + +#include "QQuickDetailsViewMananger.h" +#include "propertyType/propertyTypeCustomization_DataSourceType.h" +#include "propertyType/dataSourceType.h" DiagramCavas::DiagramCavas(QWidget *parent) : QMdiArea(parent) @@ -37,7 +40,6 @@ DiagramCavas::DiagramCavas(QWidget *parent) ,_dataAccessor(nullptr) ,_structDataPreviewDlg(nullptr) ,_extraPropertyManager(nullptr) - ,_dataSourceDlg(nullptr) { _pageIndex = 0; } @@ -176,9 +178,7 @@ void DiagramCavas::initial() _structDataPreviewDlg->setExtraPropertyManager(_extraPropertyManager); _structDataPreviewDlg->loadData(); - _dataSourceDlg = new DataSourceDlg(this); - _dataSourceDlg->setExtraPropertyManager(_extraPropertyManager); - _dataSourceDlg->loadData(); + QQuickDetailsViewManager::Get()->registerPropertyTypeCustomization(); } void DiagramCavas::onSignal_addDrawingPanel(PowerEntity* pItem,DiagramMode mode,QString parent) @@ -193,7 +193,7 @@ void DiagramCavas::onSignal_addDrawingPanel(PowerEntity* pItem,DiagramMode mode, pPanel->show(); FixedPortsModel* pModel = pPanel->getModelController(); - pModel->setCavas(this); + pModel->setCavas(QPointer(this)); connect(pModel,&FixedPortsModel::activatePage,this,&DiagramCavas::onSignal_activatePage); connect(pModel,&FixedPortsModel::updateCurrentItems,this,&DiagramCavas::onSignal_updateCurItems); connect(pModel,&FixedPortsModel::itemSelected,this,&DiagramCavas::onSignal_selectedItems); @@ -210,7 +210,7 @@ void DiagramCavas::onSignal_addDrawingPanel(PowerEntity* pItem,DiagramMode mode, pPanel->show(); FixedPortsModel* pModel = pPanel->getModelController(); - pModel->setCavas(this); + pModel->setCavas(QPointer(this)); connect(pModel,&FixedPortsModel::activatePage,this,&DiagramCavas::onSignal_activatePage); connect(pPanel,&MonitorPanel::panelDelete,this,&DiagramCavas::onSignal_panelDelete); connect(pModel,&FixedPortsModel::monitorCreated,this,&DiagramCavas::onSignal_monitorCreated); diff --git a/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp b/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp index 53e1eff..f1f52d0 100644 --- a/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp +++ b/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp @@ -1619,6 +1619,13 @@ void FixedPortsModel::startHttpRequest() } } +DiagramCavas* FixedPortsModel::getCavas() +{ + if(_cavas) + return _cavas.data();; + return nullptr; +} + void FixedPortsModel::addPortsToItem_json(PortState sta,QJsonArray jArr,GraphicsProjectModelItem* pItem) { for(QJsonValueRef portJson:jArr) diff --git a/diagramCavas/source/graphicsItem/graphicsBaseItem.cpp b/diagramCavas/source/graphicsItem/graphicsBaseItem.cpp index 975bbfa..8129a5a 100644 --- a/diagramCavas/source/graphicsItem/graphicsBaseItem.cpp +++ b/diagramCavas/source/graphicsItem/graphicsBaseItem.cpp @@ -615,6 +615,16 @@ void GraphicsProjectModelItem::setSize(QRectF rec) update(); } +DataSourceType GraphicsProjectModelItem::getDataSourceType() const +{ + return _sourceType; +} + +void GraphicsProjectModelItem::setDataSourceType(DataSourceType type) +{ + _sourceType = type; +} + QVariant GraphicsProjectModelItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant& value) { if (change == QGraphicsItem::ItemSelectedHasChanged) diff --git a/diagramCavas/source/propertyType/propertyTypeCustomization_DataSourceType.cpp b/diagramCavas/source/propertyType/propertyTypeCustomization_DataSourceType.cpp new file mode 100644 index 0000000..4f9c0bf --- /dev/null +++ b/diagramCavas/source/propertyType/propertyTypeCustomization_DataSourceType.cpp @@ -0,0 +1,120 @@ +#include "propertyType/propertyTypeCustomization_DataSourceType.h" +#include "QQuickDetailsViewLayoutBuilder.h" +#include "QPropertyHandle.h" +#include +#include +#include "propertyType/dataSourceType.h" +#include "QQuickFunctionLibrary.h" +#include "dataSourceDlg.h" + +void PropertyTypeCustomization_DataSourceType::customizeHeaderRow(QPropertyHandle* inPropertyHandle, QQuickDetailsViewRowBuilder* inBuilder) +{ + auto editorSlot = inBuilder->makeNameValueSlot(); + inPropertyHandle->setupNameEditor(editorSlot.first); + auto buttonItem = inBuilder->setupItem(editorSlot.second, R"( + import QtQuick + import QtQuick.Controls + + Item { + // 仅设置隐式大小 + implicitWidth: 180 + implicitHeight: 25 + + // 自定义信号 + signal customButtonClicked() + + // 让父容器控制宽度 + anchors.left: parent ? parent.left : undefined + anchors.right: parent ? parent.right : undefined + + // 设置文本的函数 + function setDisplayText(newText) { + displayText.text = newText; + } + + // 获取当前文本的函数 + function getDisplayText() { + return displayText.text; + } + + // 右侧功能按钮 + Button { + id: button + width: 25 + height: 25 + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + } + + text: "..." + font.pixelSize: 9 + font.bold: true + + // 自定义按钮样式 + background: Rectangle { + color: button.down ? "#d0d0d0" : + button.hovered ? "#e0e0e0" : "#f0f0f0" + border.color: "#888" + border.width: 1 + radius: 4 + } + + // 点击时触发自定义信号 + onClicked: { + parent.customButtonClicked() + } + } + + // 文字显示区域 + Rectangle { + id: textArea + anchors { + left: parent.left + right: button.left + rightMargin: 5 + verticalCenter: parent.verticalCenter + } + height: 25 + + border.color: "#ccc" + border.width: 1 + radius: 4 + + Text { + id: displayText + anchors.fill: parent + anchors.margins: 5 + text: "datasource" + color: "#333" + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } + } + } + )"); + DataSourceType curVal = inPropertyHandle->getVar().value(); + QVariant curStr = QVariant(curVal.sPara); + QMetaObject::invokeMethod(buttonItem, "setDisplayText", + Q_ARG(QVariant, curStr)); + + QQuickFunctionLibrary::connect(buttonItem, SIGNAL(customButtonClicked()), inPropertyHandle, [inPropertyHandle,buttonItem]() { + DataSourceDlg dlg; + DataSourceType customType = inPropertyHandle->getVar().value(); + dlg.showDlg(customType); + if (dlg.exec() == QDialog::Accepted) { + DataSourceType setType = dlg.getCurData(); + inPropertyHandle->setVar(QVariant::fromValue(setType)); + + QVariant displayStr = QVariant(setType.sPara); + QMetaObject::invokeMethod(buttonItem, "setDisplayText", + Q_ARG(QVariant, displayStr)); + } + }); +} + +void PropertyTypeCustomization_DataSourceType::customizeChildren(QPropertyHandle* inPropertyHandle, QQuickDetailsViewLayoutBuilder* inBuilder) +{ + +} + diff --git a/diagramCavas/ui/dataSourceDlg.ui b/diagramCavas/ui/dataSourceDlg.ui index bfe5ee4..0596afb 100644 --- a/diagramCavas/ui/dataSourceDlg.ui +++ b/diagramCavas/ui/dataSourceDlg.ui @@ -6,8 +6,8 @@ 0 0 - 698 - 436 + 773 + 537 @@ -38,7 +38,17 @@ - background-color: rgb(199, 199, 199); + QWidget { + background: #2c5282; + color: white; + border: none; +} + +QWidget QLabel { + color: white; + font-size: 12px; + background: transparent; +} @@ -167,7 +177,7 @@ - + @@ -189,6 +199,36 @@ + + + 75 + 0 + + + + QPushButton { + background-color: #5a79a1; /* 中性灰蓝,不刺眼 */ + color: white; + border: none; /* 无边框,扁平化 */ + border-radius: 4px; /* 小圆角,扁平感 */ + font-size: 13px; /* 适中字号 */ + font-weight: 500; /* 中等字重 */ +} + +QPushButton:hover { + background-color: #4a5d7e; /* 稍深的灰蓝 */ +} + +QPushButton:pressed { + background-color: #3d4e6b; /* 更深的灰蓝 */ +} + +QPushButton:disabled { + background-color: #a0b3d1; /* 灰调的浅蓝 */ + color: #d1dce9; /* 浅灰色文字 */ +} + + 确定 @@ -196,6 +236,36 @@ + + + 75 + 0 + + + + QPushButton { + background-color: #5a79a1; /* 中性灰蓝,不刺眼 */ + color: white; + border: none; /* 无边框,扁平化 */ + border-radius: 4px; /* 小圆角,扁平感 */ + font-size: 13px; /* 适中字号 */ + font-weight: 500; /* 中等字重 */ +} + +QPushButton:hover { + background-color: #4a5d7e; /* 稍深的灰蓝 */ +} + +QPushButton:pressed { + background-color: #3d4e6b; /* 更深的灰蓝 */ +} + +QPushButton:disabled { + background-color: #a0b3d1; /* 灰调的浅蓝 */ + color: #d1dce9; /* 浅灰色文字 */ +} + + 取消 diff --git a/source/mainwindow.cpp b/source/mainwindow.cpp index 67005b1..3870f87 100644 --- a/source/mainwindow.cpp +++ b/source/mainwindow.cpp @@ -30,6 +30,8 @@ #include "QDetailsView.h" #include "baseDockWidget.h" +#include "QDetailsView.h" + CMainWindow::CMainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::CMainWindow)