#ifndef CUSTOMDEVICESMANAGER_H
#define CUSTOMDEVICESMANAGER_H
#include "scada.h"
#include "qtpropertybrowser.h"
#include "qtpropertymanager.h"
#include <QScopedPointer>
#include <QVariantMap>
#include <QList>
class CustomDevicesManagerPrivate;
// DeviceManager
class CustomDevicesManager : public QtAbstractPropertyManager
{
Q_OBJECT
public:
explicit CustomDevicesManager(QObject* parent = nullptr);
~CustomDevicesManager() override;
// get the substring item manager
QtStringPropertyManager* subStringPropertyManager() const;
// get the ScadaHash struct.
Graphics::ScadaHash value(const QtProperty* property) const;
bool isManagedProperty(const QtProperty *property) const;
QString getValueText(const QtProperty* property) { return valueText(property); }
void initDeviceProperty(QtProperty* property) { initializeProperty(property); }
void uninitDeviceProperty(QtProperty* property) { uninitializeProperty(property); }
// get the property value corresponding to the attribute use QString.
QString valueText(const QtProperty* property) const override;
public slots:
// set the scada property with ScadaHash.
void setValue(QtProperty* property, const Graphics::ScadaHash& val);
signals:
void valueChanged(QtProperty* property, const Graphics::ScadaHash& val);
void buttonClicked(QtProperty* property);
protected:
void initializeProperty(QtProperty* property) override;
void uninitializeProperty(QtProperty* property) override;
private:
QScopedPointer<CustomDevicesManagerPrivate> d_ptr;
Q_DECLARE_PRIVATE(CustomDevicesManager)
Q_DISABLE_COPY(CustomDevicesManager)
// according to the Qt base manager settings.
Q_PRIVATE_SLOT(d_func(), void slotStringChanged(QtProperty*, const QString&))
Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty*))
};
// DevicesManagerPrivate(PIMPL)
class CustomDevicesManagerPrivate
{
CustomDevicesManager* q_ptr;
Q_DECLARE_PUBLIC(CustomDevicesManager)
public:
void slotStringChanged(QtProperty* property, const QString& value);
void slotPropertyDestroyed(QtProperty* property);
// map from QtProperty to the ScadaHash.
typedef QMap<const QtProperty*, Graphics::ScadaHash> PropertyValueMap;
PropertyValueMap m_values;
// the string manager to the editor lineEdior.
QtStringPropertyManager* m_stringPropertyManager = nullptr;
// let all these parameters be in one group.
QtGroupPropertyManager* m_groupPropertyManager = nullptr;
// map the master property to the childern parameters.
QMap<const QtProperty*, QList<QtProperty*>> m_propertyToScadas; // 主属性→参数复合属性列表(参数1、参数2...)
QMap<const QtProperty*, QList<QtProperty*>> m_scadaToFields; // 参数复合属性→字段子属性列表(LineEdit 对应的字段)
QMap<const QtProperty*, QtProperty*> m_fieldToScada; // 字段子属性→所属参数复合属性
QMap<const QtProperty*, QtProperty*> m_scadaToDevice; // 参数复合属性→所属主属性
QMap<const QtProperty*, QString> m_fieldToMember; // 字段子属性→对应数据的键名(QVariantMap 的 key)
QMap<const QtProperty*, Graphics::ScadaKey> m_scadaToKey; // Scada复合属性→对应的ScadaKey(用于显示)
};
#endif // CUSTOMDEVICESMANAGER_H
#include "customdevicesmanager.h"
#include <QCoreApplication>
#include <QDebug>
#include <QMetaProperty>
// ====================== private class(CustomDevicesManagerPrivate)======================
void CustomDevicesManagerPrivate::slotStringChanged(QtProperty* fieldProp, const QString& value)
{
// // 反向查找:字段→Scada复合属性→主属性
// QtProperty* scadaProp = m_fieldToScada.value(fieldProp, nullptr);
// QtProperty* deviceProp = m_scadaToDevice.value(scadaProp, nullptr);
// QString memberName = m_fieldToMember.value(fieldProp, "");
// if (!scadaProp || !deviceProp || memberName.isEmpty()) return;
// // 查找对应的 ScadaKey 和 ScadaPtr
// Graphics::ScadaHash& scadaHash = m_values[deviceProp];
// Graphics::ScadaKey scadaKey = m_scadaToKey.value(scadaProp);
// if (!scadaHash.contains(scadaKey)) return;
// // 更新 ScadaPtr 的元属性值
// Graphics::ScadaPtr scadaPtr = scadaHash[scadaKey];
// if (!scadaPtr) return;
// // 按元属性名赋值
// if (memberName == "code") scadaPtr->setCode(value);
// else if (memberName == "domain") scadaPtr->setDomain(value);
// else if (memberName == "type") scadaPtr->setType(value.toInt());
// else if (memberName == "substation") scadaPtr->setSubstation(value);
// else if (memberName == "tableName") scadaPtr->setTableName(value);
// else if (memberName == "realTableName") scadaPtr->setRealTableName(value);
// else if (memberName == "deviceId") scadaPtr->setDeviceId(value);
// else if (memberName == "deviceCode") scadaPtr->setDeviceCode(value);
// emit q_ptr->valueChanged(deviceProp, scadaHash);
QtProperty* scadaProp = m_fieldToScada.value(fieldProp, nullptr);
QtProperty* deviceProp = m_scadaToDevice.value(scadaProp, nullptr);
QString memberName = m_fieldToMember.value(fieldProp, "");
if (!scadaProp || !deviceProp || memberName.isEmpty()) return;
Graphics::ScadaHash& scadaHash = m_values[deviceProp];
Graphics::ScadaKey scadaKey = m_scadaToKey.value(scadaProp);
if (!scadaHash.contains(scadaKey)) return;
Graphics::ScadaPtr scadaPtr = scadaHash[scadaKey];
if (!scadaPtr) return;
//Get properties through QMetaObject reflection.
const QMetaObject* metaObj = scadaPtr->metaObject();
int propIndex = metaObj->indexOfProperty(memberName.toUtf8().constData());
if (propIndex == -1) {
qDebug() << "[slotStringChanged] Scada don't have " << memberName << " property,return";
return;
}
QMetaProperty metaProp = metaObj->property(propIndex);
if (metaProp.isWritable()) {
// QString/int
if (metaProp.type() == QMetaType::QString) {
metaProp.write(scadaPtr.get(), QVariant(value)); //
} else if (metaProp.type() == QMetaType::Int) {
metaProp.write(scadaPtr.get(), QVariant(value.toInt()));
} else if (metaProp.type() == QMetaType::Double) {
metaProp.write(scadaPtr.get(), QVariant(value.toDouble()));
} else {
qDebug() << "[slotStringChanged] " << metaProp.typeName() << "(" << memberName << ")";
}
} else {
qDebug() << "[slotStringChanged] Property" << memberName << "can't writable, jump";
}
emit q_ptr->valueChanged(deviceProp, scadaHash);
}
void CustomDevicesManagerPrivate::slotPropertyDestroyed(QtProperty* fieldProp)
{
// 清理映射关系
// -A|
// ----B1|
// -------C1|
// -------C2|
QtProperty* scadaProp = m_fieldToScada.take(fieldProp);//B
if (scadaProp) {//B
QtProperty* deviceProp = m_scadaToDevice.value(scadaProp, nullptr);//A
if (deviceProp) {//A
m_scadaToFields[scadaProp].removeAll(fieldProp);//C
if (m_scadaToFields[scadaProp].isEmpty()) {//C
m_propertyToScadas[deviceProp].removeAll(scadaProp);//B
m_scadaToDevice.remove(scadaProp);//A
m_scadaToFields.remove(scadaProp);//C
m_scadaToKey.remove(scadaProp);
}
}
m_fieldToMember.remove(fieldProp);
}
}
// ====================== 主管理器类(CustomDevicesManager)======================
CustomDevicesManager::CustomDevicesManager(QObject* parent)
: QtAbstractPropertyManager(parent)
, d_ptr(new CustomDevicesManagerPrivate)
{
Q_D(CustomDevicesManager);
d->q_ptr = this;
// sub String manager.
d->m_stringPropertyManager = new QtStringPropertyManager(this);
// sub manager signals.
connect(d->m_stringPropertyManager, &QtStringPropertyManager::valueChanged,
this, [d](QtProperty* prop, const QString& val) { d->slotStringChanged(prop, val); });
connect(d->m_stringPropertyManager, &QtStringPropertyManager::propertyDestroyed,
this, [d](QtProperty* prop) { d->slotPropertyDestroyed(prop); });
// group manager.
d_ptr->m_groupPropertyManager = new QtGroupPropertyManager(this);
// destroyed.
connect(d->m_groupPropertyManager, &QtGroupPropertyManager::propertyDestroyed,
this, [d](QtProperty* prop) { d->slotPropertyDestroyed(prop); });
}
CustomDevicesManager::~CustomDevicesManager()
{
clear();
}
QtStringPropertyManager* CustomDevicesManager::subStringPropertyManager() const
{
Q_D(const CustomDevicesManager);
return d->m_stringPropertyManager;
}
Graphics::ScadaHash CustomDevicesManager::value(const QtProperty* property) const
{
Q_D(const CustomDevicesManager);
return d->m_values.value(property, Graphics::ScadaHash());
}
bool CustomDevicesManager::isManagedProperty(const QtProperty *property) const
{
Q_D(const CustomDevicesManager);
return d->m_values.contains(property); // 直接检查核心映射是否包含该属性
}
void CustomDevicesManager::setValue(QtProperty* property, const Graphics::ScadaHash& val)
{
Q_D(CustomDevicesManager);
const auto it = d->m_values.find(property);
if (it == d->m_values.end()) return;
if (it.value() == val) return;
it.value() = val;
QList<QtProperty*>& scadaProps = d->m_propertyToScadas[property];
// 关键1:清理无效属性(仅保留val中存在的scadaProp)
QList<QtProperty*> validScadaProps;
for (QtProperty* prop : scadaProps) {
Graphics::ScadaKey key = d->m_scadaToKey.value(prop);
if (val.contains(key)) {
validScadaProps.append(prop);
} else {
QList<QtProperty*>& fieldProps = d->m_scadaToFields[prop];
for (QtProperty* fieldProp : fieldProps) {
d->m_fieldToScada.remove(fieldProp);
d->m_fieldToMember.remove(fieldProp);
delete fieldProp;
}
d->m_scadaToDevice.remove(prop);
d->m_scadaToFields.remove(prop);
d->m_scadaToKey.remove(prop);
delete prop;
}
}
scadaProps = validScadaProps;
// 关键2:用QHash替代QMap(无需ScadaKey重载<运算符)
QHash<Graphics::ScadaKey, QtProperty*> scadaKeyToProp;
for (QtProperty* prop : scadaProps) {
scadaKeyToProp.insert(d->m_scadaToKey.value(prop), prop);
}
// 遍历val,更新或创建属性
int scadaIdx = 0;
for (auto hashIt = val.begin(); hashIt != val.end(); ++hashIt) {
Graphics::ScadaKey scadaKey = hashIt.key();
Graphics::ScadaPtr scadaPtr = hashIt.value();
QtProperty* scadaProp = scadaKeyToProp.take(scadaKey); // 优先复用
if (!scadaProp) { // 无复用才创建
scadaProp = d->m_groupPropertyManager->addProperty();
scadaProps.append(scadaProp);
d->m_scadaToDevice[scadaProp] = property;
d->m_scadaToKey[scadaProp] = scadaKey;
property->addSubProperty(scadaProp);
}
// 更新属性名和tooltip
scadaProp->setPropertyName(QString("参数%1").arg(scadaIdx + 1));
scadaProp->setToolTip(QString("code: %1, tableName: %2").arg(scadaKey.code).arg(scadaKey.tableName));
// 提取元属性(不变)
QList<QPair<QString, QString>> metaProps;
if (scadaPtr) {
const QMetaObject* metaObj = scadaPtr->metaObject();
for (int i = metaObj->propertyOffset(); i < metaObj->propertyCount(); ++i) {
QMetaProperty metaProp = metaObj->property(i);
if (!metaProp.isReadable() || !metaProp.isWritable()) continue;
QString memberName = metaProp.name();
QString memberLabel = memberName;
for (int j = 1; j < memberLabel.size(); ++j) {
if (memberLabel[j].isUpper() && memberLabel[j-1].isLower()) {
memberLabel.insert(j, ' ');
j++;
}
}
memberLabel[0] = memberLabel[0].toUpper();
metaProps.append({memberName, memberLabel});
}
}
// 处理子属性字段(不变)
QList<QtProperty*>& fieldProps = d->m_scadaToFields[scadaProp];
while (fieldProps.size() > metaProps.size()) {
QtProperty* delFieldProp = fieldProps.takeLast();
d->m_fieldToScada.remove(delFieldProp);
d->m_fieldToMember.remove(delFieldProp);
delete delFieldProp;
}
// 动态创建/更新子字段(不变)
for (int fieldIdx = 0; fieldIdx < metaProps.size(); ++fieldIdx) {
QString memberName = metaProps[fieldIdx].first;
QString memberLabel = metaProps[fieldIdx].second;
QtProperty* fieldProp = nullptr;
if (fieldIdx < fieldProps.size()) {
fieldProp = fieldProps[fieldIdx];
fieldProp->setPropertyName(memberLabel);
} else {
fieldProp = d->m_stringPropertyManager->addProperty();
fieldProp->setPropertyName(memberLabel);
fieldProps.append(fieldProp);
d->m_fieldToScada[fieldProp] = scadaProp;
d->m_fieldToMember[fieldProp] = memberName;
scadaProp->addSubProperty(fieldProp);
}
// 设置字段值(不变)
QString fieldValue;
if (scadaPtr) {
const QMetaObject* metaObj = scadaPtr->metaObject();
int propIdx = metaObj->indexOfProperty(memberName.toUtf8().constData());
if (propIdx != -1) {
QMetaProperty metaProp = metaObj->property(propIdx);
QVariant propValue = metaProp.read(scadaPtr.get());
fieldValue = propValue.toString();
}
}
d->m_stringPropertyManager->setValue(fieldProp, fieldValue);
}
scadaIdx++;
}
emit propertyChanged(property);
emit valueChanged(property, val);
// Q_D(CustomDevicesManager);
// const auto it = d->m_values.find(property);
// if (it == d->m_values.end()) return;
// if (it.value() == val) return;
// it.value() = val;
// QList<QtProperty*>& scadaProps = d->m_propertyToScadas[property];
// // remove the redundant property.
// while (scadaProps.size() > val.size()) {
// QtProperty* delScadaProp = scadaProps.takeLast();
// QList<QtProperty*>& fieldProps = d->m_scadaToFields[delScadaProp];
// for (QtProperty* fieldProp : fieldProps) {
// d->m_fieldToScada.remove(fieldProp);
// d->m_fieldToMember.remove(fieldProp);
// delete fieldProp;
// }
// d->m_scadaToDevice.remove(delScadaProp);
// d->m_scadaToFields.remove(delScadaProp);
// d->m_scadaToKey.remove(delScadaProp);
// delete delScadaProp;
// }
// // iterate the val
// int scadaIdx = 0;
// for (auto hashIt = val.begin(); hashIt != val.end(); ++hashIt) {
// Graphics::ScadaKey scadaKey = hashIt.key();
// Graphics::ScadaPtr scadaPtr = hashIt.value();
// QtProperty* scadaProp = nullptr;
// // 复用或创建复合属性(参数X)
// if (scadaIdx < scadaProps.size()) {
// scadaProp = scadaProps[scadaIdx];
// scadaProp->setPropertyName(QString("参数%1").arg(scadaIdx + 1));
// scadaProp->setToolTip(QString("code: %1, tableName: %2").arg(scadaKey.code).arg(scadaKey.tableName));
// } else {
// scadaProp = d->m_groupPropertyManager->addProperty();
// scadaProp->setPropertyName(QString("参数%1").arg(scadaIdx + 1));
// scadaProp->setToolTip(QString("code: %1, tableName: %2").arg(scadaKey.code).arg(scadaKey.tableName));
// scadaProps.append(scadaProp);
// d->m_scadaToDevice[scadaProp] = property;
// d->m_scadaToKey[scadaProp] = scadaKey;
// property->addSubProperty(scadaProp);
// }
// // 3. 从 ScadaPtr 元对象中提取元属性(动态替代固定memberList)
// QList<QPair<QString, QString>> metaProps; // <属性名(memberName), 显示标签>
// if (scadaPtr) {
// const QMetaObject* metaObj = scadaPtr->metaObject();
// // 遍历所有可读写的属性(跳过父类继承的属性,仅保留自身属性)
// for (int i = metaObj->propertyOffset(); i < metaObj->propertyCount(); ++i) {
// QMetaProperty metaProp = metaObj->property(i);
// // 关键修正:删除!metaProp.isUser(),避免过滤所有属性
// if (!metaProp.isReadable() || !metaProp.isWritable()) continue;
// QString memberName = metaProp.name(); // 属性名(如"code")
// // 核心:属性名自动转人性化显示(兼容所有Qt版本)
// QString memberLabel = memberName;
// for (int j = 1; j < memberLabel.size(); ++j) {
// // 驼峰命名分隔(如"tableName"→"Table Name")
// if (memberLabel[j].isUpper() && memberLabel[j-1].isLower()) {
// memberLabel.insert(j, ' ');
// j++; // 跳过新增的空格,避免连续分隔
// }
// }
// // 首字母大写(如"table name"→"Table Name")
// memberLabel[0] = memberLabel[0].toUpper();
// metaProps.append({memberName, memberLabel});
// }
// }
// // 4. 处理元属性字段(LineEdit)
// QList<QtProperty*>& fieldProps = d->m_scadaToFields[scadaProp];
// while (fieldProps.size() > metaProps.size()) {
// QtProperty* delFieldProp = fieldProps.takeLast();
// d->m_fieldToScada.remove(delFieldProp);
// d->m_fieldToMember.remove(delFieldProp);
// delete delFieldProp;
// }
// // 5. 动态创建/更新字段(无固定字符串判断)
// for (int fieldIdx = 0; fieldIdx < metaProps.size(); ++fieldIdx) {
// QString memberName = metaProps[fieldIdx].first;
// QString memberLabel = metaProps[fieldIdx].second;
// QtProperty* fieldProp = nullptr;
// if (fieldIdx < fieldProps.size()) {
// fieldProp = fieldProps[fieldIdx];
// fieldProp->setPropertyName(memberLabel);
// } else {
// fieldProp = d->m_stringPropertyManager->addProperty();
// fieldProp->setPropertyName(memberLabel);
// fieldProps.append(fieldProp);
// d->m_fieldToScada[fieldProp] = scadaProp;
// d->m_fieldToMember[fieldProp] = memberName;
// scadaProp->addSubProperty(fieldProp); // 子项关联到复合属性
// }
// // 动态设置字段值(通过元属性读取,替代固定if判断)
// QString fieldValue;
// if (scadaPtr) {
// const QMetaObject* metaObj = scadaPtr->metaObject();
// int propIdx = metaObj->indexOfProperty(memberName.toUtf8().constData());
// if (propIdx != -1) {
// QMetaProperty metaProp = metaObj->property(propIdx);
// QVariant propValue = metaProp.read(scadaPtr.get());
// fieldValue = propValue.toString();
// }
// }
// d->m_stringPropertyManager->setValue(fieldProp, fieldValue);
// }
// scadaIdx++;
// }
// emit propertyChanged(property);
// emit valueChanged(property, val);
// Q_D(CustomDevicesManager);
// const auto it = d->m_values.find(property);
// if (it == d->m_values.end()) return;
// if (it.value() == val) return;
// // 更新核心数据(ScadaHash)
// it.value() = val;
// // 动态创建/更新 Scada 复合属性(参数1、参数2...)
// QList<QtProperty*>& scadaProps = d->m_propertyToScadas[property];
// // 1. 移除多余的复合属性
// while (scadaProps.size() > val.size()) {
// QtProperty* delScadaProp = scadaProps.takeLast();
// QList<QtProperty*>& fieldProps = d->m_scadaToFields[delScadaProp];
// for (QtProperty* fieldProp : fieldProps) {
// d->m_fieldToScada.remove(fieldProp);
// d->m_fieldToMember.remove(fieldProp);
// delete fieldProp;
// }
// d->m_scadaToDevice.remove(delScadaProp);
// d->m_scadaToFields.remove(delScadaProp);
// d->m_scadaToKey.remove(delScadaProp);
// delete delScadaProp;
// }
// // 2. 定义 Scada 元属性(名称+显示标签)
// QList<QPair<QString, QString>> memberList;
// memberList.append(QPair<QString, QString>("code", "代码"));
// memberList.append(QPair<QString, QString>("domain", "域名"));
// memberList.append(QPair<QString, QString>("type", "类型"));
// memberList.append(QPair<QString, QString>("substation", "厂站"));
// memberList.append(QPair<QString, QString>("tableName", "参数库表名"));
// memberList.append(QPair<QString, QString>("realTableName", "实时库表名"));
// memberList.append(QPair<QString, QString>("deviceId", "设备ID"));
// memberList.append(QPair<QString, QString>("deviceCode", "设备代码"));
// // 3. 遍历 ScadaHash,创建/更新复合属性和字段
// int scadaIdx = 0;
// for (auto hashIt = val.begin(); hashIt != val.end(); ++hashIt) {
// Graphics::ScadaKey scadaKey = hashIt.key();
// Graphics::ScadaPtr scadaPtr = hashIt.value();
// QtProperty* scadaProp = nullptr;
// // 复用或创建复合属性(参数X)
// if (scadaIdx < scadaProps.size()) {
// scadaProp = scadaProps[scadaIdx];
// // 核心:复合属性的“值列”显示 ScadaKey(code + tableName)
// scadaProp->setPropertyName(QString("参数%1").arg(scadaIdx + 1));
// scadaProp->setToolTip(QString("code: %1, tableName: %2").arg(scadaKey.code).arg(scadaKey.tableName));
// } else {
// scadaProp = d->m_groupPropertyManager->addProperty();
// scadaProp->setPropertyName(QString("参数%1").arg(scadaIdx + 1));
// scadaProp->setToolTip(QString("code: %1, tableName: %2").arg(scadaKey.code).arg(scadaKey.tableName));
// scadaProps.append(scadaProp);
// d->m_scadaToDevice[scadaProp] = property;
// d->m_scadaToKey[scadaProp] = scadaKey;
// property->addSubProperty(scadaProp);
// }
// // 4. 处理元属性字段(LineEdit)
// QList<QtProperty*>& fieldProps = d->m_scadaToFields[scadaProp];
// while (fieldProps.size() > memberList.size()) {
// QtProperty* delFieldProp = fieldProps.takeLast();
// d->m_fieldToScada.remove(delFieldProp);
// d->m_fieldToMember.remove(delFieldProp);
// delete delFieldProp;
// }
// // 创建/更新字段
// for (int fieldIdx = 0; fieldIdx < memberList.size(); ++fieldIdx) {
// QString memberName = memberList[fieldIdx].first;
// QString memberLabel = memberList[fieldIdx].second;
// QtProperty* fieldProp = nullptr;
// if (fieldIdx < fieldProps.size()) {
// fieldProp = fieldProps[fieldIdx];
// fieldProp->setPropertyName(memberLabel);
// } else {
// fieldProp = d->m_stringPropertyManager->addProperty();
// fieldProp->setPropertyName(memberLabel);
// fieldProps.append(fieldProp);
// d->m_fieldToScada[fieldProp] = scadaProp;
// d->m_fieldToMember[fieldProp] = memberName;
// scadaProp->addSubProperty(fieldProp);
// }
// // 设置字段值(从 ScadaPtr 读取)
// QString fieldValue;
// if (scadaPtr) {
// if (memberName == "code") fieldValue = scadaPtr->getCode();
// else if (memberName == "domain") fieldValue = scadaPtr->getDomain();
// else if (memberName == "type") fieldValue = QString::number(scadaPtr->getType());
// else if (memberName == "substation") fieldValue = scadaPtr->getSubstation();
// else if (memberName == "tableName") fieldValue = scadaPtr->getTableName();
// else if (memberName == "realTableName") fieldValue = scadaPtr->getRealTableName();
// else if (memberName == "deviceId") fieldValue = scadaPtr->getDeviceId();
// else if (memberName == "deviceCode") fieldValue = scadaPtr->getDeviceCode();
// }
// d->m_stringPropertyManager->setValue(fieldProp, fieldValue);
// }
// scadaIdx++;
// }
// emit propertyChanged(property);
// emit valueChanged(property, val);
}
QString CustomDevicesManager::valueText(const QtProperty* property) const
{
Q_D(const CustomDevicesManager);
const auto it = d->m_values.constFind(property);
if (it == d->m_values.constEnd()) return QString();
// 主属性显示:ScadaHash 数据量概览
const Graphics::ScadaHash& scadaHash = it.value();
int totalFieldCount = scadaHash.size() * 8; // 每个 Scada 8 个字段
return QString("数据点配置(%1个数据点,共%2个字段)").arg(scadaHash.size()).arg(totalFieldCount);
}
void CustomDevicesManager::initializeProperty(QtProperty* property)
{
Q_D(CustomDevicesManager);
if (!d->m_values.contains(property)) {
d->m_values[property] = Graphics::ScadaHash();
d->m_propertyToScadas[property] = QList<QtProperty*>();
}
}
void CustomDevicesManager::uninitializeProperty(QtProperty* property)
{
Q_D(CustomDevicesManager);
QList<QtProperty*>& scadaProps = d->m_propertyToScadas[property];
for (QtProperty* scadaProp : scadaProps) {
QList<QtProperty*>& fieldProps = d->m_scadaToFields[scadaProp];
for (QtProperty* fieldProp : fieldProps) {
d->m_fieldToScada.remove(fieldProp);
d->m_fieldToMember.remove(fieldProp);
delete fieldProp;
}
d->m_scadaToDevice.remove(scadaProp);
d->m_scadaToFields.remove(scadaProp);
d->m_scadaToKey.remove(scadaProp);
delete scadaProp;
}
d->m_propertyToScadas.remove(property);
d->m_values.remove(property);
}
我是用qtdesigner的源码相关的属性编辑器,加了自定义的属性,结果,我现在每次setValue都会导致私有类定义的数据结构里面的个数都增加1
最新发布