QTPropertyBrowser属性表控件:新增自定义属性类型

#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
最新发布
12-04
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值