#include "objectcontroller.h" #include "qtvariantproperty.h" #include "qtgroupboxpropertybrowser.h" #include "qttreepropertybrowser.h" #include "qtpropertybrowser.h" #include "variantfactory.h" #include "variantmanager.h" QMap propertyNamesMap; BasicObjectController::BasicObjectController() { propertyNamesMap.insert("tip", "文本"); propertyNamesMap.insert("title", "标题"); propertyNamesMap.insert("dataLink", "链接"); propertyNamesMap.insert("textColor", "文本色"); propertyNamesMap.insert("bgColor", "背景色"); propertyNamesMap.insert("Red", "红"); propertyNamesMap.insert("Green", "绿"); propertyNamesMap.insert("Blue", "蓝"); propertyNamesMap.insert("Alpha", "明度"); propertyNamesMap.insert("font", "字体"); propertyNamesMap.insert("enable", "启用"); propertyNamesMap.insert("rowCount", "行数"); propertyNamesMap.insert("colCount", "列数"); } int BasicObjectController::enumToInt(const QMetaEnum &metaEnum, int enumValue) const { QMap valueMap; // dont show multiple enum values which have the same values int pos = 0; for (int i = 0; i < metaEnum.keyCount(); i++) { int value = metaEnum.value(i); if (!valueMap.contains(value)) { if (value == enumValue) { return pos; } valueMap[value] = pos++; } } return -1; } int BasicObjectController::intToEnum(const QMetaEnum &metaEnum, int intValue) const { QMap valueMap; // dont show multiple enum values which have the same values QList values; for (int i = 0; i < metaEnum.keyCount(); i++) { int value = metaEnum.value(i); if (!valueMap.contains(value)) { valueMap[value] = true; values.append(value); } } if (intValue >= values.count()) { return -1; } return values.at(intValue); } bool BasicObjectController::isSubValue(int value, int subValue) const { if (value == subValue) { return true; } int i = 0; while (subValue) { if (!(value & (1 << i))) { if (subValue & 1) { return false; } } i++; subValue = subValue >> 1; } return true; } bool BasicObjectController::isPowerOf2(int value) const { while (value) { if (value & 1) { return value == 1; } value = value >> 1; } return false; } int BasicObjectController::flagToInt(const QMetaEnum &metaEnum, int flagValue) const { if (!flagValue) { return 0; } int intValue = 0; QMap valueMap; // dont show multiple enum values which have the same values int pos = 0; for (int i = 0; i < metaEnum.keyCount(); i++) { int value = metaEnum.value(i); if (!valueMap.contains(value) && isPowerOf2(value)) { if (isSubValue(flagValue, value)) { intValue |= (1 << pos); } valueMap[value] = pos++; } } return intValue; } int BasicObjectController::intToFlag(const QMetaEnum &metaEnum, int intValue) const { QMap valueMap; // dont show multiple enum values which have the same values QList values; for (int i = 0; i < metaEnum.keyCount(); i++) { int value = metaEnum.value(i); if (!valueMap.contains(value) && isPowerOf2(value)) { valueMap[value] = true; values.append(value); } } int flagValue = 0; int temp = intValue; int i = 0; while (temp) { if (i >= values.count()) { return -1; } if (temp & 1) { flagValue |= values.at(i); } i++; temp = temp >> 1; } return flagValue; } void BasicObjectController::expandAll() { //打开所有节点 QtTreePropertyBrowser *browser = (QtTreePropertyBrowser *)m_browser; browser->expandAll(); } void BasicObjectController::collapseAll() { //折叠所有节点 QtTreePropertyBrowser *browser = (QtTreePropertyBrowser *)m_browser; browser->collapseAll(); //展开父节点 QList items = browser->topLevelItems(); for (QtBrowserItem *item : items) { browser->setExpanded(item, true); } } /// /// 设置控件属性 /// /// void BasicObjectController::setBasicControlProperties(const QMetaObject* metaObject) { if (!metaObject) { return; } // 取出属于本控件的控件属性组 QtProperty* classProperty = m_classToProperty.value(metaObject); // 重新创建新的属性表 if (!classProperty) { // 首先添加基础属性 addBasicProperties(metaObject, classProperty); // // 如果是复杂类型,还需要添加扩展属性 // QString strClassName = metaObject->className(); // if (strClassName == CLASS_NAME_TABLECONTROL) // { //// 添加扩展属性 //addExtendProperties(classProperty); // } } // 如果之前已经创建过本类型控件的属性表,那么直接从数据结构中更新即可 else { // 首先更新基础属性 updateBasicProperties(metaObject); // // 如果是复杂类型,还需要更新扩展属性 //QString strClassName = metaObject->className(); //if (strClassName == CLASS_NAME_TABLECONTROL) //{ // // 添加扩展属性 // updateExtendProperties(metaObject); //} } // 保存根节点 m_topLevelProperties.append(classProperty); // 界面中添加此根节点 m_browser->addProperty(classProperty); // 展开属性表 this->expandAll(); } /// /// 建立控件的基础属性表 /// /// /// void BasicObjectController::addBasicProperties(const QMetaObject *metaObject, QtProperty*& classProperty) { // 获取类名,根据类型名建立属性表根节点 QString className = QLatin1String(metaObject->className()); // 创建根节点 classProperty = m_manager->addProperty(QtVariantPropertyManager::groupTypeId(), className); // 保存根节点和控件对象的对应关系 m_classToProperty[metaObject] = classProperty; //m_propertyToClass[classProperty] = metaObject; int nPropertyCount = metaObject->propertyCount(); int nPropertyOffset = metaObject->propertyOffset(); // 遍历所有的固定属性执行添加 for (int idx = nPropertyOffset; idx < nPropertyCount; idx++) { // 取出对应的固定属性 QMetaProperty metaProperty = metaObject->property(idx); // 取出属性的Type值 int type = metaProperty.userType(); // 准备添加子属性节点(注意要保存带值的子属性,需要用QtVariantProperty类型) QtVariantProperty* subProperty = 0; // 英文属性名称 QString propertyName = metaProperty.name(); // 中文属性名称 propertyName = propertyNamesMap.value(propertyName); // 确保是所支持的类型 if (m_manager->isPropertyTypeSupported(type)) { // 添加属性 subProperty = m_manager->addProperty(type, propertyName); // 设置值 subProperty->setValue(metaProperty.read(m_object)); } // 设置无效属性 else { subProperty = m_readOnlyManager->addProperty(QVariant::String, propertyName); subProperty->setValue(QLatin1String("< Unknown Type >")); subProperty->setEnabled(false); } // 根节点下添加此子节点 classProperty->addSubProperty(subProperty); // 保存此子属性和索引值的对应关系 m_propertyToIndex[subProperty] = idx; // 保存根节点下所有子节点和子属性的对应关系 m_classToIndexToProperty[metaObject][idx] = subProperty; } } /// /// 设置复杂控件属性 /// void BasicObjectController::setComplexControlProperties() { if (!m_object) { return; } // 取出属于本控件的控件属性组 QtProperty* objectProperty = m_objectToProperty.value(m_object); // 重新创建新的属性表 if (!objectProperty) { // 首先添加基础属性 //addBasicProperties(metaObject, classProperty); // // 如果是复杂类型,还需要添加扩展属性 // QString strClassName = metaObject->className(); // if (strClassName == CLASS_NAME_TABLECONTROL) // { //// 添加扩展属性 //addExtendProperties(classProperty); // } } // 如果之前已经创建过本类型控件的属性表,那么直接从数据结构中更新即可 else { // 首先更新基础属性 //updateBasicProperties(metaObject); // // 如果是复杂类型,还需要更新扩展属性 //QString strClassName = metaObject->className(); //if (strClassName == CLASS_NAME_TABLECONTROL) //{ // // 添加扩展属性 // updateExtendProperties(metaObject); //} } // 保存根节点 m_topLevelProperties.append(objectProperty); // 界面中添加此根节点 m_browser->addProperty(objectProperty); // 展开属性表 this->expandAll(); } /// /// 增加新的扩展属性表(仅复杂控件才有) /// /// /// void BasicObjectController::addExtendProperties(QtProperty*& classProperty) { // 获取Table控件指针 VTableControl* pTable = qobject_cast(m_object); // 取出对应的扩展属性 const CONTROL_PROPERTY_EX& props = pTable->getPropertyEx(); // 取出每一项Item const QVector& propsItems = props.m_subGroups; // 扩展属性的数量 int nExCount = propsItems.size(); if (nExCount <= 0) { return; } qDebug() << "ObjectControllerPrivate::addExtendProperties - Count:" << nExCount; // 建立扩展属性根节点 m_exPropertiesRoot = m_manager->addProperty(QtVariantPropertyManager::groupTypeId(), props.m_strTitle); // 添加列索引属性 QtVariantProperty* item = m_manager->addProperty(VariantManager::tagDataLinkTypeId(), props.m_linkIndexName); // 数据链接值 item->setValue(""); // 保存子项和名字的对应关系 m_propertyToName.insert(item, props.m_linkIndexName); // 添加此子分组 m_exPropertiesRoot->addSubProperty(item); // 2021-12-24 保存本属性对应关系,用于后续查找和更新 m_objectToNameToProperty[m_object][props.m_linkIndexName] = item; // 循环将所有子项添加到属性表中 for (int i = 0; i < nExCount; i++) { this->addPropertiesSubGroup(propsItems[i]); } // 在本属性组中添加本属性根节点 classProperty->addSubProperty(m_exPropertiesRoot); } /// /// 更新基础属性表 /// /// /// void BasicObjectController::updateBasicProperties(const QMetaObject* metaObject) { if (!metaObject) { return; } // // 是否递归(未使用) //if (recursive) //{ // updateBasicProperties(metaObject->superClass(), recursive); //} // // 从数据结构中取出本组属性表节点 //QtProperty* classProperty = m_classToProperty.value(metaObject); //if (!classProperty) //{ // return; //} // 遍历所有的属性更新数值 for (int idx = metaObject->propertyOffset(); idx < metaObject->propertyCount(); idx++) { QMetaProperty metaProperty = metaObject->property(idx); if (metaProperty.isReadable()) { // 从数据结构中找到对应的子属性 if (m_classToIndexToProperty.contains(metaObject) && m_classToIndexToProperty[metaObject].contains(idx)) { QtVariantProperty* subProperty = m_classToIndexToProperty[metaObject][idx]; // 设置属性值 QVariant propertyValue = metaProperty.read(m_object); //QString valueString = propertyValue.toString(); //QString propertyName = subProperty->propertyName(); //if (valueString.isEmpty()) //{ // subProperty->setValue(""); //} //else //{ subProperty->setValue(propertyValue); //} } } } } /// /// 更新扩展属性表 /// void BasicObjectController::updateExtendProperties(const QMetaObject* metaObject) { // 获取Table控件指针 VTableControl* pTable = qobject_cast(m_object); // 取出对应的扩展属性 const CONTROL_PROPERTY_EX& props = pTable->getPropertyEx(); // 取出每一项Item const QVector& propsItems = props.m_subGroups; // 扩展属性的数量 int nExCount = propsItems.size(); if (nExCount <= 0) { return; } qDebug() << "ObjectControllerPrivate::updateExtendProperties - Count:" << nExCount; // Memo:由于前面setControlProperties()的判断是根据metaObject按照控件种类判断的 // 所以此处虽然执行了update,但是只能说明本大类的控件要做更新,但是有可能本类的这个object // 属性表都没有建立,所以需要重新建立一下属性表 if (!m_objectToNameToProperty[m_object].contains(props.m_linkIndexName)) { QtProperty* classProperty = m_classToProperty.value(metaObject); // this->addExtendProperties(classProperty); } else { // 遍历所有的扩展属性,全部更新一遍 // 更新列索引 QtVariantProperty* subProperty = m_objectToNameToProperty[m_object][props.m_linkIndexName]; subProperty->setValue(props.m_linkIndex.toString()); // 更新每一个子属性值 } } /// /// 向界面属性表中增加属性内容 /// /// void BasicObjectController::addPropertiesSubGroup(const PROPERTY_EX_SUBGROUP& prop) { // 创建子分组 QtProperty* subGroup = m_manager->addProperty( QtVariantPropertyManager::groupTypeId(), prop.m_strName ); // 添加子项 // 子项名 QtVariantProperty* item = m_manager->addProperty(QVariant::String, prop.m_strValueName); // 子项值 item->setValue(prop.m_strValue); // 添加子项 subGroup->addSubProperty(item); // 保存子项和名字的对应关系 m_propertyToName.insert(item, prop.m_strValueName); // 2021-12-24 保存本属性对应关系,用于后续查找和更新 m_objectToNameToProperty[m_object][prop.m_strValueName] = item; // 数据链接项名 item = m_manager->addProperty(VariantManager::tagDataLinkTypeId(), prop.m_dataLinkName); // 数据链接值 item->setValue(""); // 添加数据链接 subGroup->addSubProperty(item); // 保存子项和名字的对应关系 m_propertyToName.insert(item, prop.m_dataLinkName); // 2021-12-24 保存本属性对应关系,用于后续查找和更新 m_objectToNameToProperty[m_object][prop.m_dataLinkName] = item; // 添加此子分组 m_exPropertiesRoot->addSubProperty(subGroup); // 保存这个SubGroup的信息(用于删除使用) m_subGroups.push_back(subGroup); } void BasicObjectController::saveExpandedState() { } void BasicObjectController::restoreExpandedState() { } /// /// 属性表数据变动槽函数 /// void BasicObjectController::slotValueChanged(QtProperty *property, const QVariant &value) { qDebug() << "ObjectControllerPrivate::slotValueChanged - Property: " << property->propertyName() << " - Value: " << value.toString(); // 基础属性 if (m_propertyToIndex.contains(property)) { this->changeBasicProperties(property, value); } // 动态属性 else { QString className = m_object->metaObject()->className(); // 如果是Table控件相关属性变更 if (className == CLASS_NAME_TABLECONTROL) { // 动态属性 this->changeExtendProperties(property, value); } } //if (!m_propertyToIndex.contains(property)) { // return; //} //int idx = m_propertyToIndex.value(property); //const QMetaObject *metaObject = m_object->metaObject(); //QMetaProperty metaProperty = metaObject->property(idx); //if (metaProperty.isEnumType()) { // if (metaProperty.isFlagType()) { // metaProperty.write(m_object, intToFlag(metaProperty.enumerator(), value.toInt())); // } else { // metaProperty.write(m_object, intToEnum(metaProperty.enumerator(), value.toInt())); // } //} else { // metaProperty.write(m_object, value); //} //updateClassProperties(metaObject, true); } /// /// 更新基础属性 /// /// /// void BasicObjectController::changeBasicProperties(QtProperty* property, const QVariant& value) { int idx = m_propertyToIndex.value(property); const QMetaObject *metaObject = m_object->metaObject(); QMetaProperty metaProperty = metaObject->property(idx); metaProperty.write(m_object, value); updateBasicProperties(metaObject); // 额外处理:如果刷新的是colCount,还需要动态调整一下Table的表格 QString propertyName = metaProperty.name(); QString className = metaObject->className(); if (className == CLASS_NAME_TABLECONTROL && propertyName == COL_COUNT_NAME) { // updateTablePropertyCount(value.toInt()); // 获取Table控件指针 VTableControl* pTable = qobject_cast(m_object); // 计算新的列数 int newCount = value.toInt(); int nFixCount = newCount - pTable->getPropertyExSubGroupCount(); if (nFixCount > 0) { this->appendTableProperty(pTable, nFixCount); } else if( nFixCount < 0) { this->removeTableProperty(pTable, nFixCount); } } } /// /// 更新扩展属性 /// /// /// void BasicObjectController::changeExtendProperties(QtProperty* property, const QVariant& value) { // 找到属性对应的属性名字 if (m_propertyToName.contains(property)) { // 获取Table指针 VTableControl* pTable = qobject_cast(m_object); // 获取改变的属性Name QString strValueTitle = m_propertyToName[property]; // 如果改变了列标题 if (strValueTitle.indexOf(PROPERTY_EX_VALUE_NAME) != -1) { // 获取修改属性的列索引 int nColIndex = strValueTitle.remove(PROPERTY_EX_VALUE_NAME).toInt() - 1; // 修改对应Table的数据结构内容 pTable->updateColTitle(value.toString(), nColIndex); } // 如果改变了数据链接 else if (strValueTitle.indexOf(PROPERTY_EX_LINK_NAME) != -1) { } } } /// /// 增加新的属性项 /// /// /// void BasicObjectController::appendTableProperty(VTableControl* pTable, const int fixCount) { // 首先控件中增加新的数据结构信息 pTable->updateExPropertyCount(fixCount); // 获取最新的属性数据 const QVector& propsItems = pTable->getPropertyEx().m_subGroups; // 同步进行界面信息变更 int nStart = pTable->getPropertyExSubGroupCount() - fixCount; int nEnd = nStart + fixCount; for (int i = nStart; i < nEnd; i++) { this->addPropertiesSubGroup(propsItems[i]); } } /// /// 减少新的属性项 /// /// /// void BasicObjectController::removeTableProperty(VTableControl* pTable, const int fixCount) { // 首先控件中减少数据结构信息 pTable->updateExPropertyCount(fixCount); // 同步进行界面信息变更 int nDelCount = -fixCount; // 从后往前依次删除掉属性 for (int i = 0; i < nDelCount; i++) { QtProperty* pDelSubGroup = m_subGroups.back(); // m_browser->removeProperty(pDelProperty); // 删除子属性 m_exPropertiesRoot->removeSubProperty(pDelSubGroup); m_subGroups.pop_back(); } }