|
|
#include "nmAttrRegistry.h"
|
|
|
#include "nmDataAttribute.h"
|
|
|
|
|
|
nmAttrRegistry::nmAttrRegistry(QObject* parent)
|
|
|
: QObject(parent)
|
|
|
, m_bSyncing(false)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
nmAttrRegistry::~nmAttrRegistry()
|
|
|
{
|
|
|
// 映射中的指针不拥有所有权,不需 delete
|
|
|
// nmDataAttribute 的 destroyed 信号已自动清理映射
|
|
|
m_nameToPtr.clear();
|
|
|
m_ptrToName.clear();
|
|
|
}
|
|
|
|
|
|
void nmAttrRegistry::regAttr(QString name, nmDataAttribute* pAttr)
|
|
|
{
|
|
|
if (name.isEmpty() || pAttr == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 如果同名已注册,先断开旧连接
|
|
|
if (m_nameToPtr.contains(name)) {
|
|
|
nmDataAttribute* pOld = m_nameToPtr[name];
|
|
|
if (pOld != nullptr && pOld != pAttr) {
|
|
|
disconnect(pOld, SIGNAL(sigValueChanged()), this, SLOT(onAttrValueChanged()));
|
|
|
disconnect(pOld, SIGNAL(destroyed(QObject*)), this, SLOT(onAttrDestroyed(QObject*)));
|
|
|
m_ptrToName.remove(pOld);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 如果同指针已注册(换名),先清理旧名
|
|
|
if (m_ptrToName.contains(pAttr)) {
|
|
|
QString oldName = m_ptrToName[pAttr];
|
|
|
if (oldName != name) {
|
|
|
m_nameToPtr.remove(oldName);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
m_nameToPtr[name] = pAttr;
|
|
|
m_ptrToName[pAttr] = name;
|
|
|
|
|
|
// 连接 nmDataAttribute 的信号
|
|
|
connect(pAttr, SIGNAL(sigValueChanged()),
|
|
|
this, SLOT(onAttrValueChanged()));
|
|
|
connect(pAttr, SIGNAL(destroyed(QObject*)),
|
|
|
this, SLOT(onAttrDestroyed(QObject*)));
|
|
|
}
|
|
|
|
|
|
void nmAttrRegistry::clear()
|
|
|
{
|
|
|
// 断开所有 nmDataAttribute 的信号连接
|
|
|
QMap<nmDataAttribute*, QString>::iterator iter = m_ptrToName.begin();
|
|
|
for (; iter != m_ptrToName.end(); iter++) {
|
|
|
nmDataAttribute* pAttr = iter.key();
|
|
|
if (pAttr != nullptr) {
|
|
|
disconnect(pAttr, SIGNAL(sigValueChanged()), this, SLOT(onAttrValueChanged()));
|
|
|
disconnect(pAttr, SIGNAL(destroyed(QObject*)), this, SLOT(onAttrDestroyed(QObject*)));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
m_nameToPtr.clear();
|
|
|
m_ptrToName.clear();
|
|
|
}
|
|
|
|
|
|
QMap<QString, QVariant> nmAttrRegistry::collect(const QStringList& names) const
|
|
|
{
|
|
|
QMap<QString, QVariant> mapResult;
|
|
|
for (int i = 0; i < names.size(); i++) {
|
|
|
QString name = names[i];
|
|
|
nmDataAttribute* pAttr = m_nameToPtr.value(name, nullptr);
|
|
|
if (pAttr != nullptr) {
|
|
|
mapResult[name] = pAttr->getValue();
|
|
|
}
|
|
|
}
|
|
|
return mapResult;
|
|
|
}
|
|
|
|
|
|
void nmAttrRegistry::setValue(QString name, QVariant value)
|
|
|
{
|
|
|
nmDataAttribute* pAttr = m_nameToPtr.value(name, nullptr);
|
|
|
if (pAttr == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
m_bSyncing = true;
|
|
|
pAttr->setValue(value); // → nmDataAttribute 发 sigValueChanged
|
|
|
// → onAttrValueChanged 检测 m_bSyncing=true → 跳过 sigAttrChanged
|
|
|
m_bSyncing = false;
|
|
|
}
|
|
|
|
|
|
void nmAttrRegistry::onAttrValueChanged()
|
|
|
{
|
|
|
nmDataAttribute* pAttr = qobject_cast<nmDataAttribute*>(sender());
|
|
|
if (pAttr == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 防循环:UI→Data 链路中跳过
|
|
|
if (m_bSyncing) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
QString name = m_ptrToName.value(pAttr, "");
|
|
|
if (name.isEmpty()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
emit sigAttrChanged(name, pAttr->getValue());
|
|
|
}
|
|
|
|
|
|
void nmAttrRegistry::onAttrDestroyed(QObject* pObj)
|
|
|
{
|
|
|
// nmDataAttribute 析构时发出 destroyed,此时对象已部分销毁
|
|
|
// 只用指针值做 key,不访问任何成员
|
|
|
nmDataAttribute* pAttr = static_cast<nmDataAttribute*>(pObj);
|
|
|
|
|
|
QString name = m_ptrToName.value(pAttr, "");
|
|
|
if (!name.isEmpty()) {
|
|
|
m_nameToPtr.remove(name);
|
|
|
}
|
|
|
m_ptrToName.remove(pAttr);
|
|
|
}
|