From 5dfa31238b20c92fdaa5688c1ddd7e652ad6d24c Mon Sep 17 00:00:00 2001
From: Alex Diev <alex.diev@vikingsoftware.com>
Date: Fri, 3 Feb 2023 03:19:19 +0200
Subject: [PATCH 1/9] macOS/clang fixes, instance attrs are enabled for
 editing, fixes for attribute scopes

---
 src/applications/sedsconverter/CMakeLists.txt            | 5 ++++-
 .../sdl/MscToSdlTranslator/mscparametervalueparser.h     | 1 +
 src/libs/libiveditor/CMakeLists.txt                      | 4 +++-
 .../libiveditor/properties/ivpropertieslistmodel.cpp     | 2 --
 src/libs/seds/SedsXmlImporter/CMakeLists.txt             | 2 ++
 src/libs/seds/XmlValidator/CMakeLists.txt                | 5 ++++-
 src/libs/shared/propertytemplate.cpp                     | 9 +++++----
 .../testgenerator/datareconstructor/datareconstructor.h  | 2 ++
 src/qtcreator/functiontesterplugin/CMakeLists.txt        | 2 ++
 9 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/src/applications/sedsconverter/CMakeLists.txt b/src/applications/sedsconverter/CMakeLists.txt
index 2bfdc0852b..ddd7075835 100644
--- a/src/applications/sedsconverter/CMakeLists.txt
+++ b/src/applications/sedsconverter/CMakeLists.txt
@@ -22,7 +22,10 @@ target_link_libraries(SedsConverter
                 Conversion::SedsRegistrar
                 Conversion::SdlRegistrar
                 Conversion::Asn1ToSedsTranslator
-                "stdc++fs")
+if(NOT APPLE)
+                "stdc++fs"
+endif()
+                )
 
 set_target_properties(SedsConverter PROPERTIES
     RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
diff --git a/src/libs/conversion/sdl/MscToSdlTranslator/mscparametervalueparser.h b/src/libs/conversion/sdl/MscToSdlTranslator/mscparametervalueparser.h
index 60ef597f32..c51d961c9b 100644
--- a/src/libs/conversion/sdl/MscToSdlTranslator/mscparametervalueparser.h
+++ b/src/libs/conversion/sdl/MscToSdlTranslator/mscparametervalueparser.h
@@ -27,6 +27,7 @@
 #include <asn1library/asn1valueparser.h>
 #include <ivcore/ivinterface.h>
 #include <map>
+#include <unordered_map>
 #include <optional>
 #include <shared/parameter.h>
 #include <shared/qstringhash.h>
diff --git a/src/libs/libiveditor/CMakeLists.txt b/src/libs/libiveditor/CMakeLists.txt
index 12d8a97f75..bac64288dd 100644
--- a/src/libs/libiveditor/CMakeLists.txt
+++ b/src/libs/libiveditor/CMakeLists.txt
@@ -234,7 +234,7 @@ target_sources(${LIB_NAME} PRIVATE
     )
 
 target_link_libraries(${LIB_NAME}
-	Tmc::Verifier
+    Tmc::Verifier
     ivcore
     asn1library
     shared
@@ -246,7 +246,9 @@ target_link_libraries(${LIB_NAME}
     ${QT_SVGWIDGETS}
     ${QT_WIDGETS}
     ${QT_XML}
+if(NOT APPLE)
     "stdc++fs"
+endif()
     )
 
 target_include_directories(${LIB_NAME} PUBLIC .)
diff --git a/src/libs/libiveditor/properties/ivpropertieslistmodel.cpp b/src/libs/libiveditor/properties/ivpropertieslistmodel.cpp
index 4313fb264b..ce7d390aee 100644
--- a/src/libs/libiveditor/properties/ivpropertieslistmodel.cpp
+++ b/src/libs/libiveditor/properties/ivpropertieslistmodel.cpp
@@ -205,8 +205,6 @@ bool FunctionPropertiesListModel::isEditable(const QModelIndex &index) const
         break;
     }
     default:
-        if (auto fn = entity()->as<const ivm::IVFunction *>())
-            editable = !fn->inheritsFunctionType();
         break;
     }
 
diff --git a/src/libs/seds/SedsXmlImporter/CMakeLists.txt b/src/libs/seds/SedsXmlImporter/CMakeLists.txt
index 17fe87b14d..70fbd47823 100644
--- a/src/libs/seds/SedsXmlImporter/CMakeLists.txt
+++ b/src/libs/seds/SedsXmlImporter/CMakeLists.txt
@@ -14,7 +14,9 @@ target_include_directories(SedsXmlImporter
 target_link_libraries(SedsXmlImporter
     PUBLIC      Conversion::Common
                 SEDS::SymbolDefinitionReader
+if(NOT APPLE)
                 "stdc++fs"
+endif()
     PRIVATE     SEDS::XmlParser
                 SEDS::XmlPreprocessor
                 SEDS::XmlValidator
diff --git a/src/libs/seds/XmlValidator/CMakeLists.txt b/src/libs/seds/XmlValidator/CMakeLists.txt
index f58d647d37..f0d8a07139 100644
--- a/src/libs/seds/XmlValidator/CMakeLists.txt
+++ b/src/libs/seds/XmlValidator/CMakeLists.txt
@@ -17,7 +17,10 @@ target_link_libraries(SedsXmlValidator
                 Qt${QT_VERSION_MAJOR}::Core
     PRIVATE     LibXml2::LibXml2
                 CommonProjectWarnings
-                stdc++fs)
+if(NOT APPLE)
+                "stdc++fs"
+endif()
+                )
 
 add_format_target(SedsXmlValidator)
 add_tidy_target(SedsXmlValidator)
diff --git a/src/libs/shared/propertytemplate.cpp b/src/libs/shared/propertytemplate.cpp
index 4540a741d8..364e891aeb 100644
--- a/src/libs/shared/propertytemplate.cpp
+++ b/src/libs/shared/propertytemplate.cpp
@@ -428,7 +428,7 @@ bool PropertyTemplate::validate(const VEObject *object) const
     auto it = d->m_rxAttrValidatorPattern.lowerBound(objScope);
     const auto upperBound = d->m_rxAttrValidatorPattern.upperBound(objScope);
     while (it != upperBound) {
-        auto checkPattern = [](const EntityAttributes &data, const QString &name, const QString &pattern) {
+        auto checkPattern = [](const EntityAttributes &data, const QString &name, const QString &pattern) -> std::optional<bool> {
             auto objAttrIter = data.constFind(name);
             if (objAttrIter != data.constEnd()) {
                 const QRegularExpression rx(pattern);
@@ -436,10 +436,11 @@ bool PropertyTemplate::validate(const VEObject *object) const
                 const QRegularExpressionMatch match = rx.match(value);
                 return match.capturedLength() == value.length();
             }
-            return true;
+            return std::nullopt;
         };
-        if (checkPattern(object->entityAttributes(), it->first, it->second))
-            return true;
+        auto res = checkPattern(object->entityAttributes(), it->first, it->second);
+        if (res.has_value())
+            return res.value();
         ++it;
     }
     return false;
diff --git a/src/libs/testgenerator/datareconstructor/datareconstructor.h b/src/libs/testgenerator/datareconstructor/datareconstructor.h
index 851f9203bb..fe1413e2ca 100644
--- a/src/libs/testgenerator/datareconstructor/datareconstructor.h
+++ b/src/libs/testgenerator/datareconstructor/datareconstructor.h
@@ -26,7 +26,9 @@
 #include <QPair>
 #include <QString>
 #include <QVariant>
+#ifndef Q_OS_MACOS
 #include <endian.h>
+#endif
 #include <ivcore/ivinterface.h>
 #include <ivcore/ivmodel.h>
 #include <qglobal.h>
diff --git a/src/qtcreator/functiontesterplugin/CMakeLists.txt b/src/qtcreator/functiontesterplugin/CMakeLists.txt
index ff5d3a5cb3..0ce834f0de 100644
--- a/src/qtcreator/functiontesterplugin/CMakeLists.txt
+++ b/src/qtcreator/functiontesterplugin/CMakeLists.txt
@@ -9,6 +9,8 @@ set(FT_PLUGIN_SOURCES
 set(FT_QTC_LIBRARIES
     -L"${QTC_LIB_DIR}"
     -L"${QTC_PLUGINS_DIR}"
+    ExtensionSystem
+    Utils
 )
 
 set(FT_QTC_PLUGINS
-- 
GitLab


From 6659aed734d53805693ab70558f07430d8df03cc Mon Sep 17 00:00:00 2001
From: Alex Diev <alex.diev@vikingsoftware.com>
Date: Fri, 3 Feb 2023 10:28:06 +0200
Subject: [PATCH 2/9] cmake fix

---
 src/applications/sedsconverter/CMakeLists.txt | 25 +++++++++++--------
 src/libs/libiveditor/CMakeLists.txt           | 10 +++++---
 src/libs/seds/SedsXmlImporter/CMakeLists.txt  | 22 ++++++++++------
 src/libs/seds/XmlValidator/CMakeLists.txt     | 17 ++++++++-----
 4 files changed, 45 insertions(+), 29 deletions(-)

diff --git a/src/applications/sedsconverter/CMakeLists.txt b/src/applications/sedsconverter/CMakeLists.txt
index ddd7075835..5b69241558 100644
--- a/src/applications/sedsconverter/CMakeLists.txt
+++ b/src/applications/sedsconverter/CMakeLists.txt
@@ -13,19 +13,22 @@ target_sources(SedsConverter
 target_include_directories(SedsConverter
     PRIVATE     .
                 ${CMAKE_SOURCE_DIR}/src/libs)
-target_link_libraries(SedsConverter
-    PRIVATE     CommonProjectWarnings
-                Conversion::Converter
-                Conversion::Registry
-                Conversion::Asn1Registrar
-                Conversion::IvRegistrar
-                Conversion::SedsRegistrar
-                Conversion::SdlRegistrar
-                Conversion::Asn1ToSedsTranslator
+
+set (LIBS CommonProjectWarnings
+    Conversion::Converter
+    Conversion::Registry
+    Conversion::Asn1Registrar
+    Conversion::IvRegistrar
+    Conversion::SedsRegistrar
+    Conversion::SdlRegistrar
+    Conversion::Asn1ToSedsTranslator
+)
+
 if(NOT APPLE)
-                "stdc++fs"
+    set (LIBS ${LIBS} "stdc++fs")
 endif()
-                )
+
+target_link_libraries(SedsConverter PRIVATE ${LIBS})
 
 set_target_properties(SedsConverter PROPERTIES
     RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
diff --git a/src/libs/libiveditor/CMakeLists.txt b/src/libs/libiveditor/CMakeLists.txt
index bac64288dd..66d5e1cbe6 100644
--- a/src/libs/libiveditor/CMakeLists.txt
+++ b/src/libs/libiveditor/CMakeLists.txt
@@ -233,8 +233,7 @@ target_sources(${LIB_NAME} PRIVATE
     config/ivlibrarydialog.h
     )
 
-target_link_libraries(${LIB_NAME}
-    Tmc::Verifier
+set (LIBS Tmc::Verifier
     ivcore
     asn1library
     shared
@@ -246,10 +245,13 @@ target_link_libraries(${LIB_NAME}
     ${QT_SVGWIDGETS}
     ${QT_WIDGETS}
     ${QT_XML}
+)
+
 if(NOT APPLE)
-    "stdc++fs"
+    set (LIBS ${LIBS} "stdc++fs")
 endif()
-    )
+
+target_link_libraries(${LIB_NAME} ${LIBS})
 
 target_include_directories(${LIB_NAME} PUBLIC .)
 
diff --git a/src/libs/seds/SedsXmlImporter/CMakeLists.txt b/src/libs/seds/SedsXmlImporter/CMakeLists.txt
index 70fbd47823..c78ca90c97 100644
--- a/src/libs/seds/SedsXmlImporter/CMakeLists.txt
+++ b/src/libs/seds/SedsXmlImporter/CMakeLists.txt
@@ -11,17 +11,23 @@ target_sources(SedsXmlImporter
 target_include_directories(SedsXmlImporter
     PUBLIC      .
     PRIVATE     ${CMAKE_SOURCE_DIR}/src/libs)
+
+set (PRIVATE_LIBS SEDS::XmlParser
+    SEDS::XmlPreprocessor
+    SEDS::XmlValidator
+    Qt${QT_VERSION_MAJOR}::Xml
+    CommonProjectWarnings
+)
+
+if(NOT APPLE)
+    set (PRIVATE_LIBS ${PRIVATE_LIBS} "stdc++fs")
+endif()
+
 target_link_libraries(SedsXmlImporter
     PUBLIC      Conversion::Common
                 SEDS::SymbolDefinitionReader
-if(NOT APPLE)
-                "stdc++fs"
-endif()
-    PRIVATE     SEDS::XmlParser
-                SEDS::XmlPreprocessor
-                SEDS::XmlValidator
-                Qt${QT_VERSION_MAJOR}::Xml
-                CommonProjectWarnings)
+    PRIVATE     ${PRIVATE_LIBS}
+)
 
 add_format_target(SedsXmlImporter)
 add_tidy_target(SedsXmlImporter)
diff --git a/src/libs/seds/XmlValidator/CMakeLists.txt b/src/libs/seds/XmlValidator/CMakeLists.txt
index f0d8a07139..a933bfb4b8 100644
--- a/src/libs/seds/XmlValidator/CMakeLists.txt
+++ b/src/libs/seds/XmlValidator/CMakeLists.txt
@@ -12,15 +12,20 @@ target_sources(SedsXmlValidator
 target_include_directories(SedsXmlValidator
     PUBLIC      .
     PRIVATE     ${CMAKE_SOURCE_DIR}/src/libs)
+
+set (PRIVATE_LIBS LibXml2::LibXml2
+    CommonProjectWarnings
+)
+
+if(NOT APPLE)
+    set (PRIVATE_LIBS ${PRIVATE_LIBS} "stdc++fs")
+endif()
+
 target_link_libraries(SedsXmlValidator
     PUBLIC      Conversion::Converter
                 Qt${QT_VERSION_MAJOR}::Core
-    PRIVATE     LibXml2::LibXml2
-                CommonProjectWarnings
-if(NOT APPLE)
-                "stdc++fs"
-endif()
-                )
+    PRIVATE     ${PRIVATE_LIBS}
+)
 
 add_format_target(SedsXmlValidator)
 add_tidy_target(SedsXmlValidator)
-- 
GitLab


From 0cc94a02ae6f7861550775b3a1a5c66be810ad58 Mon Sep 17 00:00:00 2001
From: Alex Diev <alex.diev@vikingsoftware.com>
Date: Fri, 3 Feb 2023 13:32:30 +0200
Subject: [PATCH 3/9] Set Interface kind fix. Test fix

---
 src/libs/ivcore/ivinterface.cpp                         | 2 +-
 tests/unittests/libiveditor/tst_attributesconfigure.cpp | 5 ++++-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/libs/ivcore/ivinterface.cpp b/src/libs/ivcore/ivinterface.cpp
index ee54518f5d..e1ac42d92a 100644
--- a/src/libs/ivcore/ivinterface.cpp
+++ b/src/libs/ivcore/ivinterface.cpp
@@ -307,7 +307,7 @@ IVInterface::OperationKind IVInterface::kind() const
 
 bool IVInterface::setKind(IVInterface::OperationKind k)
 {
-    if (this->kind() != k) {
+    if (this->kind() != k || !hasEntityAttribute(meta::Props::token(meta::Props::Token::kind))) {
         setEntityAttribute(meta::Props::token(meta::Props::Token::kind), kindToString(k));
         return true;
     }
diff --git a/tests/unittests/libiveditor/tst_attributesconfigure.cpp b/tests/unittests/libiveditor/tst_attributesconfigure.cpp
index 4936e40582..5eab9a6022 100644
--- a/tests/unittests/libiveditor/tst_attributesconfigure.cpp
+++ b/tests/unittests/libiveditor/tst_attributesconfigure.cpp
@@ -322,6 +322,7 @@ void tst_AttributesConfigure::tst_attrValidators()
 
     ivm::IVFunctionType fnType;
     ivm::IVFunction fn;
+    fn.postInit();
 
     ivm::IVInterface::CreationInfo ci;
     ci.function = &fn;
@@ -330,14 +331,16 @@ void tst_AttributesConfigure::tst_attrValidators()
     ci.name = QLatin1String("reqIface");
     ci.kind = ivm::IVInterface::OperationKind::Any;
     ivm::IVInterfaceRequired reqIface(ci);
+    reqIface.postInit();
 
     ci.type = ivm::IVInterface::InterfaceType::Provided;
     ci.name = QLatin1String("provIface");
     ci.kind = ivm::IVInterface::OperationKind::Cyclic;
     ivm::IVInterfaceProvided provIface(ci);
+    provIface.postInit();
 
     ivm::IVConnection connection(&reqIface, &provIface);
-    comment.setEntityAttribute(QLatin1String("Custom_Connection_Attribute"), QStringLiteral("0123456789"));
+    connection.setEntityAttribute(QLatin1String("Custom_Connection_Attribute"), QStringLiteral("0123456789"));
 
     const QMultiMap<int, QPair<QString, QString>> validators {
         { int(ivm::IVPropertyTemplate::Scope::Function), { "name", "[a-zA-Z_]+[\\d\\w]*" } },
-- 
GitLab


From 467cd760bb51a7c60cb99896c398adbd7d8d10b0 Mon Sep 17 00:00:00 2001
From: Alex Diev <alex.diev@vikingsoftware.com>
Date: Sun, 5 Feb 2023 18:09:54 +0200
Subject: [PATCH 4/9] Default value for attribute is added without inserting if
 it's optional

---
 src/libs/ivcore/ivinterface.cpp | 36 ++++++++++++++-------------------
 src/libs/ivcore/ivmodel.cpp     | 35 +++++++++++++++-----------------
 src/libs/ivcore/ivobject.cpp    | 11 ++++++++++
 src/libs/ivcore/ivobject.h      |  2 ++
 src/libs/shared/veobject.cpp    | 13 +++++++++++-
 src/libs/shared/veobject.h      |  1 +
 6 files changed, 57 insertions(+), 41 deletions(-)

diff --git a/src/libs/ivcore/ivinterface.cpp b/src/libs/ivcore/ivinterface.cpp
index e1ac42d92a..1069654b28 100644
--- a/src/libs/ivcore/ivinterface.cpp
+++ b/src/libs/ivcore/ivinterface.cpp
@@ -120,10 +120,9 @@ struct IVInterfacePrivate {
 
 IVInterface::IVInterface(IVObject::Type ifaceType, const CreationInfo &ci)
     : IVObject(ifaceType, ci.function, ci.toBeCloned ? shared::createId() : ci.id)
-    , d(new IVInterfacePrivate(Type::InterfaceGroup == ifaceType
-                      ? ci.type
-                      : Type::RequiredInterface == ifaceType ? IVInterface::InterfaceType::Required
-                                                             : IVInterface::InterfaceType::Provided))
+    , d(new IVInterfacePrivate(Type::InterfaceGroup == ifaceType ? ci.type
+                      : Type::RequiredInterface == ifaceType     ? IVInterface::InterfaceType::Required
+                                                                 : IVInterface::InterfaceType::Provided))
 {
     setKind(ci.kind);
     setLayerName(ci.layer != nullptr ? ci.layer->title() : IVConnectionLayerType::DefaultLayerName);
@@ -166,35 +165,30 @@ bool IVInterface::postInit()
         return IVObject::postInit();
     }
 
-    if(fn->entityAttributeValue(meta::Props::token(meta::Props::Token::language)).toString() == 
-        meta::Props::token(meta::Props::Token::QGenC))
-    {
+    if (fn->entityAttributeValue(meta::Props::token(meta::Props::Token::language)).toString()
+            == meta::Props::token(meta::Props::Token::QGenC)) {
         setEntityAttribute(meta::Props::token(meta::Props::Token::is_simulink_interface), true);
     }
 
     bool isSimulinkInterfaceTypeAttrPresent = false;
-    for(QString key : entityAttributes().keys())
-    {
-        if(key == meta::Props::token(meta::Props::Token::simulink_interface_type))
-        {
+    for (QString key : entityAttributes().keys()) {
+        if (key == meta::Props::token(meta::Props::Token::simulink_interface_type)) {
             isSimulinkInterfaceTypeAttrPresent = true;
             break;
         }
     }
 
-    if (entityAttributeValue<bool>(meta::Props::token(meta::Props::Token::is_simulink_interface)) == false ||
-        !isSimulinkInterfaceTypeAttrPresent ||
-        entityAttributeValue<QString>(meta::Props::token(meta::Props::Token::simulink_interface_type)) ==
-            meta::Props::token(meta::Props::Token::Full))
-    {
+    if (entityAttributeValue<bool>(meta::Props::token(meta::Props::Token::is_simulink_interface)) == false
+            || !isSimulinkInterfaceTypeAttrPresent
+            || entityAttributeValue<QString>(meta::Props::token(meta::Props::Token::simulink_interface_type))
+                    == meta::Props::token(meta::Props::Token::Full)) {
         removeEntityAttribute(meta::Props::token(meta::Props::Token::simulink_full_interface_ref));
     }
 
-    if(entityAttributeValue<bool>(meta::Props::token(meta::Props::Token::is_simulink_interface)) == true &&
-       !isSimulinkInterfaceTypeAttrPresent)
-    {
+    if (entityAttributeValue<bool>(meta::Props::token(meta::Props::Token::is_simulink_interface)) == true
+            && !isSimulinkInterfaceTypeAttrPresent) {
         setEntityAttribute(meta::Props::token(meta::Props::Token::simulink_interface_type),
-                           QVariant(meta::Props::token(meta::Props::Token::Full)));
+                QVariant(meta::Props::token(meta::Props::Token::Full)));
     }
 
     const QString prototypeName =
@@ -307,7 +301,7 @@ IVInterface::OperationKind IVInterface::kind() const
 
 bool IVInterface::setKind(IVInterface::OperationKind k)
 {
-    if (this->kind() != k || !hasEntityAttribute(meta::Props::token(meta::Props::Token::kind))) {
+    if (this->kind() != k) {
         setEntityAttribute(meta::Props::token(meta::Props::Token::kind), kindToString(k));
         return true;
     }
diff --git a/src/libs/ivcore/ivmodel.cpp b/src/libs/ivcore/ivmodel.cpp
index b8aa93777a..7f9ad549ed 100644
--- a/src/libs/ivcore/ivmodel.cpp
+++ b/src/libs/ivcore/ivmodel.cpp
@@ -19,11 +19,11 @@
 
 #include "common.h"
 #include "errorhub.h"
+#include "ivarchetypelibraryreference.h"
 #include "ivcomment.h"
 #include "ivconnection.h"
 #include "ivfunction.h"
 #include "ivfunctiontype.h"
-#include "ivarchetypelibraryreference.h"
 #include "ivpropertytemplate.h"
 #include "propertytemplateconfig.h"
 
@@ -49,7 +49,7 @@ IVModel::IVModel(shared::PropertyTemplateConfig *dynPropConfig, IVModel *sharedM
     d->m_layersModel = nullptr;
 }
 
-IVModel::~IVModel() {}
+IVModel::~IVModel() { }
 
 bool IVModel::addObjectImpl(shared::VEObject *obj)
 {
@@ -58,21 +58,18 @@ bool IVModel::addObjectImpl(shared::VEObject *obj)
             d->m_visibleObjects.append(ivObj);
 
             for (const auto attr : d->m_dynPropConfig->propertyTemplatesForObject(ivObj)) {
-                if (attr->validate(ivObj) && !attr->isOptional()) {
-                    const QVariant &currentValue = obj->entityAttributeValue(attr->name());
-                    if (currentValue.isNull()) {
-                        const QVariant &defaultValue = attr->defaultValue();
-                        if (!defaultValue.isNull()) {
-                            if (attr->info() == ivm::IVPropertyTemplate::Info::Attribute) {
-                                obj->setEntityAttribute(attr->name(), defaultValue);
-                            } else if (attr->info() == ivm::IVPropertyTemplate::Info::Property) {
-                                obj->setEntityProperty(attr->name(), defaultValue);
-                            } else {
-                                QMetaEnum metaEnum = QMetaEnum::fromType<shared::PropertyTemplate::Info>();
-                                shared::ErrorHub::addError(shared::ErrorItem::Warning,
-                                        tr("Unknown dynamic property info: %1")
-                                                .arg(metaEnum.valueToKey(int(attr->info()))));
-                            }
+                if (attr->validate(ivObj) && !attr->isOptional() && !obj->hasEntityAttribute(attr->name())) {
+                    const QVariant &defaultValue = attr->defaultValue();
+                    if (!defaultValue.isNull()) {
+                        if (attr->info() == ivm::IVPropertyTemplate::Info::Attribute) {
+                            obj->setEntityAttribute(attr->name(), defaultValue);
+                        } else if (attr->info() == ivm::IVPropertyTemplate::Info::Property) {
+                            obj->setEntityProperty(attr->name(), defaultValue);
+                        } else {
+                            QMetaEnum metaEnum = QMetaEnum::fromType<shared::PropertyTemplate::Info>();
+                            shared::ErrorHub::addError(shared::ErrorItem::Warning,
+                                    tr("Unknown dynamic property info: %1")
+                                            .arg(metaEnum.valueToKey(int(attr->info()))));
                         }
                     }
                 }
@@ -228,8 +225,8 @@ IVFunctionType *IVModel::getFunctionType(const shared::Id &id) const
 
 IVFunctionType *IVModel::getSharedFunctionType(const QString &name, Qt::CaseSensitivity caseSensitivity) const
 {
-    return d->m_sharedTypesModel ? qobject_cast<IVFunctionType *>(d->m_sharedTypesModel->getObjectByName(
-                                           name, IVObject::Type::FunctionType, caseSensitivity))
+    return d->m_sharedTypesModel ? qobject_cast<IVFunctionType *>(
+                   d->m_sharedTypesModel->getObjectByName(name, IVObject::Type::FunctionType, caseSensitivity))
                                  : nullptr;
 }
 
diff --git a/src/libs/ivcore/ivobject.cpp b/src/libs/ivcore/ivobject.cpp
index 693ebf0503..ba7c47b7f6 100644
--- a/src/libs/ivcore/ivobject.cpp
+++ b/src/libs/ivcore/ivobject.cpp
@@ -21,6 +21,8 @@
 #include "ivcoreutils.h"
 #include "ivmodel.h"
 #include "ivnamevalidator.h"
+#include "ivpropertytemplate.h"
+#include "ivpropertytemplateconfig.h"
 
 #include <QPointer>
 #include <QVector>
@@ -168,6 +170,15 @@ QVariantList IVObject::generateProperties(bool isProperty) const
     return result;
 }
 
+QVariant IVObject::defaultEntityAttributeValue(const QString &name) const
+{
+    if (const shared::PropertyTemplate *propTemplate =
+                    IVPropertyTemplateConfig::instance()->propertyTemplateForObject(this, name)) {
+        return propTemplate->defaultValue();
+    }
+    return {};
+}
+
 IVObject::Type IVObject::type() const
 {
     return d->m_type;
diff --git a/src/libs/ivcore/ivobject.h b/src/libs/ivcore/ivobject.h
index 2459b16560..5cc33d6e6e 100644
--- a/src/libs/ivcore/ivobject.h
+++ b/src/libs/ivcore/ivobject.h
@@ -113,6 +113,8 @@ public:
 
     QVariantList generateProperties(bool isProperty) const override;
 
+    QVariant defaultEntityAttributeValue(const QString &name) const override;
+
 Q_SIGNALS:
     void urlChanged(const QString &url);
     void titleChanged(const QString &title);
diff --git a/src/libs/shared/veobject.cpp b/src/libs/shared/veobject.cpp
index b52683f75d..59e676abdd 100644
--- a/src/libs/shared/veobject.cpp
+++ b/src/libs/shared/veobject.cpp
@@ -95,7 +95,18 @@ EntityAttribute VEObject::entityAttribute(const QString &name) const
 QVariant VEObject::entityAttributeValue(const QString &name, const QVariant &defaultValue) const
 {
     const EntityAttribute attr = entityAttribute(name);
-    return attr.isNull() ? defaultValue : attr.value();
+    if (!attr.isNull())
+        return attr.value();
+
+    if (!defaultValue.isNull())
+        return defaultValue;
+
+    return defaultEntityAttributeValue(name);
+}
+
+QVariant VEObject::defaultEntityAttributeValue(const QString &name) const
+{
+    return {};
 }
 
 void VEObject::removeEntityAttribute(const QString &attributeName)
diff --git a/src/libs/shared/veobject.h b/src/libs/shared/veobject.h
index 1268dfaa89..d1fba24cff 100644
--- a/src/libs/shared/veobject.h
+++ b/src/libs/shared/veobject.h
@@ -65,6 +65,7 @@ public:
     }
 
     QVariant entityAttributeValue(const QString &name, const QVariant &defaultValue = QVariant()) const;
+    virtual QVariant defaultEntityAttributeValue(const QString &name) const;
 
     void removeEntityAttribute(const QString &attributeName);
     bool hasEntityAttribute(const QString &attributeName, const QVariant &value = QVariant()) const;
-- 
GitLab


From c0662e65982e20f120674bbd67cc539f5e4fa932 Mon Sep 17 00:00:00 2001
From: Alex Diev <alex.diev@vikingsoftware.com>
Date: Sun, 5 Feb 2023 22:23:42 +0200
Subject: [PATCH 5/9] Setup default attribute values in postInit method

---
 src/libs/dvcore/dvconnection.cpp              |  4 +++
 src/libs/dvcore/dvmessage.cpp                 |  4 +++
 src/libs/dvcore/dvnode.cpp                    |  5 +++-
 src/libs/dvcore/dvobject.cpp                  | 10 +++++--
 src/libs/dvcore/dvobject.h                    |  1 +
 .../ivcore/archetypes/archetypeobject.cpp     | 14 +++++++---
 src/libs/ivcore/ivconnection.cpp              |  9 +++++--
 src/libs/ivcore/ivconnectiongroup.cpp         |  3 +++
 src/libs/ivcore/ivfunction.cpp                | 18 ++++++++-----
 src/libs/ivcore/ivinterface.cpp               | 10 ++++---
 src/libs/ivcore/ivmodel.cpp                   | 18 -------------
 src/libs/ivcore/ivobject.cpp                  | 10 +++++++
 src/libs/ivcore/ivobject.h                    |  4 +++
 src/libs/shared/veobject.cpp                  | 26 +++++++++++++++++++
 src/libs/shared/veobject.h                    |  5 +++-
 .../libiveditor/tst_attributesconfigure.cpp   |  2 +-
 tests/unittests/shared/tst_veobject.cpp       |  4 ++-
 17 files changed, 108 insertions(+), 39 deletions(-)

diff --git a/src/libs/dvcore/dvconnection.cpp b/src/libs/dvcore/dvconnection.cpp
index 4980124451..a6ac43530a 100644
--- a/src/libs/dvcore/dvconnection.cpp
+++ b/src/libs/dvcore/dvconnection.cpp
@@ -56,6 +56,10 @@ DVConnection::~DVConnection() { }
 
 bool DVConnection::postInit()
 {
+    if (!DVObject::postInit()) {
+        return false;
+    }
+
     if (!model()) {
         shared::ErrorHub::addError(shared::ErrorItem::Error, tr("Connection can't init without model set"));
         return false;
diff --git a/src/libs/dvcore/dvmessage.cpp b/src/libs/dvcore/dvmessage.cpp
index 398205f384..5812feb77d 100644
--- a/src/libs/dvcore/dvmessage.cpp
+++ b/src/libs/dvcore/dvmessage.cpp
@@ -36,6 +36,10 @@ DVMessage::DVMessage(QObject *parent)
 
 bool DVMessage::postInit()
 {
+    if (!DVObject::postInit()) {
+        return false;
+    }
+
     DVNode *node1 = fromNode();
     if (!node1) {
         shared::ErrorHub::addError(shared::ErrorItem::Error, tr("Message %1 has invalid node").arg(title()));
diff --git a/src/libs/dvcore/dvnode.cpp b/src/libs/dvcore/dvnode.cpp
index 1651df9da3..b025924364 100644
--- a/src/libs/dvcore/dvnode.cpp
+++ b/src/libs/dvcore/dvnode.cpp
@@ -48,8 +48,11 @@ DVNode::~DVNode() { }
 
 bool DVNode::postInit()
 {
-    QString label = nodeLabel();
+    if (!DVObject::postInit()) {
+        return false;
+    }
 
+    const QString label = nodeLabel();
     if (label.isEmpty() || nodeLabelCount(label) > 1) {
         setEntityAttribute(dvm::meta::Props::token(dvm::meta::Props::Token::node_label), uniqueLabelName());
     }
diff --git a/src/libs/dvcore/dvobject.cpp b/src/libs/dvcore/dvobject.cpp
index 86b17ba545..85c1a09f91 100644
--- a/src/libs/dvcore/dvobject.cpp
+++ b/src/libs/dvcore/dvobject.cpp
@@ -19,6 +19,7 @@
 
 #include "dvmodel.h"
 #include "dvnamevalidator.h"
+#include "dvpropertytemplateconfig.h"
 #include "exportableproperty.h"
 
 #include <QVector>
@@ -41,7 +42,7 @@ DVObject::DVObject(const DVObject::Type t, const QString &title, QObject *parent
     setEntityAttribute(meta::Props::token(meta::Props::Token::name), title);
 }
 
-DVObject::~DVObject() {}
+DVObject::~DVObject() { }
 
 QString DVObject::title() const
 {
@@ -141,7 +142,7 @@ DVModel *DVObject::model() const
 
 bool DVObject::postInit()
 {
-    return true;
+    return shared::VEObject::postInit();
 }
 
 bool DVObject::aboutToBeRemoved()
@@ -172,6 +173,11 @@ QVariantList DVObject::properties() const
     return generateProperties(true);
 }
 
+shared::PropertyTemplateConfig *DVObject::propertyTemplaceConfig() const
+{
+    return DVPropertyTemplateConfig::instance();
+}
+
 /**
  * @brief generateProperties generates a variant list sorted by meta::Props::Token.
  * @param props can be hash of attributes or properties of DVObject.
diff --git a/src/libs/dvcore/dvobject.h b/src/libs/dvcore/dvobject.h
index 0e91733eff..b4e323939a 100644
--- a/src/libs/dvcore/dvobject.h
+++ b/src/libs/dvcore/dvobject.h
@@ -82,6 +82,7 @@ public:
     QVariantList properties() const;
 
     QVariantList generateProperties(bool isProperty) const override;
+    shared::PropertyTemplateConfig *propertyTemplaceConfig() const override;
 
 Q_SIGNALS:
     void urlChanged(const QString &title);
diff --git a/src/libs/ivcore/archetypes/archetypeobject.cpp b/src/libs/ivcore/archetypes/archetypeobject.cpp
index 86c4fe0cfb..63e9686f41 100644
--- a/src/libs/ivcore/archetypes/archetypeobject.cpp
+++ b/src/libs/ivcore/archetypes/archetypeobject.cpp
@@ -53,15 +53,21 @@ QString ArchetypeObject::title() const
 
 QString ArchetypeObject::titleUI() const
 {
-    QString text;
-    std::transform(title().cbegin(), title().cend(), std::back_inserter(text),
-            [](const QChar &ch) { return ch.isLetterOrNumber() ? ch : QLatin1Char(' '); });
+    QString text { title() };
+    std::for_each(text.begin(), text.end(), [](QChar &ch) {
+        if (!ch.isLetterOrNumber())
+            ch = QLatin1Char(' ');
+    });
 
     return text;
 }
 
 bool ArchetypeObject::postInit()
 {
+    if (!shared::VEObject::postInit()) {
+        return false;
+    }
+
     if (title().isEmpty()) {
         resetTitle();
     }
@@ -103,7 +109,7 @@ QVector<qint32> ArchetypeObject::coordinates() const
     return QVector<qint32>();
 }
 
-void ArchetypeObject::setCoordinates(const QVector<qint32> &coordinates) {}
+void ArchetypeObject::setCoordinates(const QVector<qint32> &coordinates) { }
 
 ArchetypeObject *ArchetypeObject::parentObject() const
 {
diff --git a/src/libs/ivcore/ivconnection.cpp b/src/libs/ivcore/ivconnection.cpp
index 7e2227a727..a3f83dc921 100644
--- a/src/libs/ivcore/ivconnection.cpp
+++ b/src/libs/ivcore/ivconnection.cpp
@@ -38,7 +38,7 @@ struct ConnectionHolder {
 };
 
 struct IVConnectionPrivate {
-    IVConnectionPrivate() {}
+    IVConnectionPrivate() { }
     IVConnectionPrivate(IVInterface *ifaceSource, IVInterface *ifaceTarget) { setData(ifaceSource, ifaceTarget); }
 
     void setData(IVInterface *ifaceSource, IVInterface *ifaceTarget)
@@ -83,7 +83,8 @@ IVConnection::IVConnection(IVInterface *ifaceSource, IVInterface *ifaceTarget, Q
 {
 }
 
-IVConnection::IVConnection(const IVObject::Type t, IVInterface *ifaceSource, IVInterface *ifaceTarget, QObject *parent, const shared::Id &id)
+IVConnection::IVConnection(const IVObject::Type t, IVInterface *ifaceSource, IVInterface *ifaceTarget, QObject *parent,
+        const shared::Id &id)
     : IVObject(t, parent, id)
     , d(new IVConnectionPrivate { ifaceSource, ifaceTarget })
 {
@@ -354,6 +355,10 @@ void IVConnection::clearPostponedEndpoints()
 
 bool IVConnection::postInit()
 {
+    if (!shared::VEObject::postInit()) {
+        return false;
+    }
+
     if (needPostponedInit() && !lookupEndpointsPostponed()) {
         shared::ErrorHub::addError(shared::ErrorItem::Warning, tr("Postponed Connection initialization failed"), "");
         return false;
diff --git a/src/libs/ivcore/ivconnectiongroup.cpp b/src/libs/ivcore/ivconnectiongroup.cpp
index 8797d1b2f4..497279fd66 100644
--- a/src/libs/ivcore/ivconnectiongroup.cpp
+++ b/src/libs/ivcore/ivconnectiongroup.cpp
@@ -40,6 +40,9 @@ IVConnectionGroup::IVConnectionGroup(const QString &name, IVInterfaceGroup *ifac
 
 bool IVConnectionGroup::postInit()
 {
+    if (!shared::VEObject::postInit())
+        return false;
+
     if (m_initConnections.isEmpty()) {
         return true;
     }
diff --git a/src/libs/ivcore/ivfunction.cpp b/src/libs/ivcore/ivfunction.cpp
index eaed814659..682f36fd61 100644
--- a/src/libs/ivcore/ivfunction.cpp
+++ b/src/libs/ivcore/ivfunction.cpp
@@ -42,10 +42,14 @@ IVFunction::IVFunction(QObject *parent, const shared::Id &id)
 {
 }
 
-IVFunction::~IVFunction() {}
+IVFunction::~IVFunction() { }
 
 bool IVFunction::postInit()
 {
+    if (!IVObject::postInit()) {
+        return false;
+    }
+
     if (auto objModel = model()) {
         const QString typeName =
                 entityAttributeValue(meta::Props::token(meta::Props::Token::instance_of)).value<QString>();
@@ -61,7 +65,7 @@ bool IVFunction::postInit()
         checkDefaultFunctionImplementation();
     }
 
-    return IVObject::postInit();
+    return true;
 }
 
 void IVFunction::setInstanceOf(IVFunctionType *fnType)
@@ -105,7 +109,7 @@ void IVFunction::restoreInternals()
         d->m_fnType->forgetInstance(this);
 
     if (m_originalFields.collected()) {
-        for (const EntityAttribute &attr: qAsConst(d->m_implementations))
+        for (const EntityAttribute &attr : qAsConst(d->m_implementations))
             addImplementation(attr.name(), attr.value<QString>());
         setDefaultImplementation(m_originalFields.defaultImplementation);
         reflectAttrs(m_originalFields.attrs);
@@ -199,7 +203,7 @@ void IVFunction::reflectAttrs(const EntityAttributes &attributes)
     setEntityAttributes(prepared);
     if (attributes.contains(meta::Props::token(meta::Props::Token::type_language))) {
         setEntityAttribute(meta::Props::token(meta::Props::Token::language),
-                           attributes.value(meta::Props::token(meta::Props::Token::type_language)).value());
+                attributes.value(meta::Props::token(meta::Props::Token::type_language)).value());
     }
 }
 
@@ -297,9 +301,11 @@ QDebug operator<<(QDebug debug, const IVFunction &function)
     QDebugStateSaver saver(debug);
     const auto separator1 = debug.verbosity() > 2 ? '\t' : ' ';
     const auto separator2 = debug.verbosity() > 2 ? '\n' : ' ';
-    debug.nospace() << "IVFunction(id=" << function.id() << ", title=" << function.titleUI() << ", attributes={" << separator2;
+    debug.nospace() << "IVFunction(id=" << function.id() << ", title=" << function.titleUI() << ", attributes={"
+                    << separator2;
     for (auto attribute : function.entityAttributes()) {
-        debug << separator1 << attribute.name() << "=" << attribute.value() << " " << (int)attribute.type() << separator2;
+        debug << separator1 << attribute.name() << "=" << attribute.value() << " " << (int)attribute.type()
+              << separator2;
     }
     debug << "})";
 
diff --git a/src/libs/ivcore/ivinterface.cpp b/src/libs/ivcore/ivinterface.cpp
index 1069654b28..b4433d2f11 100644
--- a/src/libs/ivcore/ivinterface.cpp
+++ b/src/libs/ivcore/ivinterface.cpp
@@ -152,17 +152,21 @@ void IVInterface::setDirection(IVInterface::InterfaceType type) const
 
 bool IVInterface::postInit()
 {
+    if (!IVObject::postInit()) {
+        return false;
+    }
+
     if (!model() || !function()) {
         return false;
     }
 
     if (!function()->isFunction()) {
-        return IVObject::postInit();
+        return false;
     }
 
     IVFunction *fn = function()->as<IVFunction *>();
     if (!fn) {
-        return IVObject::postInit();
+        return false;
     }
 
     if (fn->entityAttributeValue(meta::Props::token(meta::Props::Token::language)).toString()
@@ -210,7 +214,7 @@ bool IVInterface::postInit()
         }
     }
 
-    return IVObject::postInit();
+    return true;
 }
 
 bool IVInterface::isProvided() const
diff --git a/src/libs/ivcore/ivmodel.cpp b/src/libs/ivcore/ivmodel.cpp
index 7f9ad549ed..0114a16b40 100644
--- a/src/libs/ivcore/ivmodel.cpp
+++ b/src/libs/ivcore/ivmodel.cpp
@@ -56,24 +56,6 @@ bool IVModel::addObjectImpl(shared::VEObject *obj)
     if (ivm::IVObject *ivObj = obj->as<ivm::IVObject *>()) {
         if (shared::VEModel::addObjectImpl(obj)) {
             d->m_visibleObjects.append(ivObj);
-
-            for (const auto attr : d->m_dynPropConfig->propertyTemplatesForObject(ivObj)) {
-                if (attr->validate(ivObj) && !attr->isOptional() && !obj->hasEntityAttribute(attr->name())) {
-                    const QVariant &defaultValue = attr->defaultValue();
-                    if (!defaultValue.isNull()) {
-                        if (attr->info() == ivm::IVPropertyTemplate::Info::Attribute) {
-                            obj->setEntityAttribute(attr->name(), defaultValue);
-                        } else if (attr->info() == ivm::IVPropertyTemplate::Info::Property) {
-                            obj->setEntityProperty(attr->name(), defaultValue);
-                        } else {
-                            QMetaEnum metaEnum = QMetaEnum::fromType<shared::PropertyTemplate::Info>();
-                            shared::ErrorHub::addError(shared::ErrorItem::Warning,
-                                    tr("Unknown dynamic property info: %1")
-                                            .arg(metaEnum.valueToKey(int(attr->info()))));
-                        }
-                    }
-                }
-            }
             return true;
         }
     }
diff --git a/src/libs/ivcore/ivobject.cpp b/src/libs/ivcore/ivobject.cpp
index ba7c47b7f6..518841bb85 100644
--- a/src/libs/ivcore/ivobject.cpp
+++ b/src/libs/ivcore/ivobject.cpp
@@ -75,9 +75,14 @@ QString IVObject::titleUI() const
 
 bool IVObject::postInit()
 {
+    if (!shared::VEObject::postInit()) {
+        return false;
+    }
+
     if (title().isEmpty()) {
         resetTitle();
     }
+
     return true;
 }
 
@@ -414,6 +419,11 @@ bool IVObject::isVisible() const
     return entityAttributeValue(meta::Props::token(meta::Props::Token::is_visible), true);
 }
 
+shared::PropertyTemplateConfig *IVObject::propertyTemplaceConfig() const
+{
+    return IVPropertyTemplateConfig::instance();
+}
+
 bool IVObject::isFixedSystemElement() const
 {
     auto obj = this;
diff --git a/src/libs/ivcore/ivobject.h b/src/libs/ivcore/ivobject.h
index 5cc33d6e6e..e272bdeeae 100644
--- a/src/libs/ivcore/ivobject.h
+++ b/src/libs/ivcore/ivobject.h
@@ -28,8 +28,11 @@
 #include <memory>
 
 namespace ivm {
+class IVPropertyTemplateConfig;
 class IVModel;
+
 struct IVObjectPrivate;
+
 class IVObject : public shared::VEObject
 {
     Q_OBJECT
@@ -99,6 +102,7 @@ public:
     void setVisible(bool isVisible);
     bool isVisible() const;
 
+    shared::PropertyTemplateConfig *propertyTemplaceConfig() const override;
     bool postInit() override;
     bool aboutToBeRemoved() override;
 
diff --git a/src/libs/shared/veobject.cpp b/src/libs/shared/veobject.cpp
index 59e676abdd..f16fec1235 100644
--- a/src/libs/shared/veobject.cpp
+++ b/src/libs/shared/veobject.cpp
@@ -17,6 +17,9 @@
 
 #include "veobject.h"
 
+#include "errorhub.h"
+#include "propertytemplate.h"
+#include "propertytemplateconfig.h"
 #include "vemodel.h"
 
 #include <QScopedValueRollback>
@@ -267,6 +270,29 @@ VEModel *VEObject::model() const
     return d->m_model;
 }
 
+bool VEObject::postInit()
+{
+    if (auto dynPropConfig = propertyTemplaceConfig()) {
+        for (const auto attr : dynPropConfig->propertyTemplatesForObject(this)) {
+            if (attr->validate(this) && !attr->isOptional() && !hasEntityAttribute(attr->name())) {
+                const QVariant &defaultValue = attr->defaultValue();
+                if (!defaultValue.isNull()) {
+                    if (attr->info() == PropertyTemplate::Info::Attribute) {
+                        setEntityAttribute(attr->name(), defaultValue);
+                    } else if (attr->info() == PropertyTemplate::Info::Property) {
+                        setEntityProperty(attr->name(), defaultValue);
+                    } else {
+                        QMetaEnum metaEnum = QMetaEnum::fromType<shared::PropertyTemplate::Info>();
+                        ErrorHub::addError(ErrorItem::Warning,
+                                tr("Unknown dynamic property info: %1").arg(metaEnum.valueToKey(int(attr->info()))));
+                    }
+                }
+            }
+        }
+    }
+    return true;
+}
+
 QString toString(VEObject *object)
 {
     return object->titleUI();
diff --git a/src/libs/shared/veobject.h b/src/libs/shared/veobject.h
index d1fba24cff..ef56750440 100644
--- a/src/libs/shared/veobject.h
+++ b/src/libs/shared/veobject.h
@@ -25,6 +25,7 @@
 
 namespace shared {
 class VEModel;
+class PropertyTemplateConfig;
 
 struct VEObjectPrivate;
 class VEObject : public QObject
@@ -89,7 +90,9 @@ public:
     }
 
     VEModel *model() const;
-    virtual bool postInit() = 0;
+
+    virtual PropertyTemplateConfig *propertyTemplaceConfig() const { return nullptr; };
+    virtual bool postInit();
     virtual bool aboutToBeRemoved() = 0;
 
     template<class T>
diff --git a/tests/unittests/libiveditor/tst_attributesconfigure.cpp b/tests/unittests/libiveditor/tst_attributesconfigure.cpp
index 5eab9a6022..1b296f0c23 100644
--- a/tests/unittests/libiveditor/tst_attributesconfigure.cpp
+++ b/tests/unittests/libiveditor/tst_attributesconfigure.cpp
@@ -370,7 +370,7 @@ void tst_AttributesConfigure::tst_attrValidators()
     QVERIFY(attrTemplate.validate(&provIface));
 
     attrTemplate.setScopes(int(ivm::IVPropertyTemplate::Scope::Required_Interface));
-    QVERIFY(attrTemplate.validate(&reqIface));
+    QVERIFY(!attrTemplate.validate(&reqIface));
     reqIface.setKind(ivm::IVInterface::OperationKind::Cyclic);
     QVERIFY(!attrTemplate.validate(&reqIface));
     reqIface.setKind(ivm::IVInterface::OperationKind::Any);
diff --git a/tests/unittests/shared/tst_veobject.cpp b/tests/unittests/shared/tst_veobject.cpp
index 3bbaf72dea..0385d156d4 100644
--- a/tests/unittests/shared/tst_veobject.cpp
+++ b/tests/unittests/shared/tst_veobject.cpp
@@ -28,7 +28,7 @@ public:
     QString titleUI() const override { return {}; }
     QVector<qint32> coordinates() const override { return {}; }
     void setCoordinates(const QVector<qint32> &coordinates) override { Q_UNUSED(coordinates) }
-    bool postInit() override { return false; }
+    bool postInit() override { return shared::VEObject::postInit(); }
     bool aboutToBeRemoved() override { return false; }
     QVariantList generateProperties(bool isProperty) const override
     {
@@ -48,6 +48,8 @@ private Q_SLOTS:
 void tst_VEObject::testSetAttributeImpl()
 {
     XEObject obj;
+    obj.postInit();
+
     const QString attrName = "foo";
     obj.setEntityAttribute(attrName, QVariant(42));
     QCOMPARE(obj.entityAttribute(attrName).isExportable(), true);
-- 
GitLab


From 6428d32ee3e0a5c8cf25ea38fbf55eada7f216d2 Mon Sep 17 00:00:00 2001
From: Alex Diev <alex.diev@vikingsoftware.com>
Date: Mon, 6 Feb 2023 00:29:19 +0200
Subject: [PATCH 6/9] Interface fix

---
 src/libs/ivcore/ivinterface.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libs/ivcore/ivinterface.cpp b/src/libs/ivcore/ivinterface.cpp
index b4433d2f11..f1f61e2659 100644
--- a/src/libs/ivcore/ivinterface.cpp
+++ b/src/libs/ivcore/ivinterface.cpp
@@ -161,12 +161,12 @@ bool IVInterface::postInit()
     }
 
     if (!function()->isFunction()) {
-        return false;
+        return true;
     }
 
     IVFunction *fn = function()->as<IVFunction *>();
     if (!fn) {
-        return false;
+        return true;
     }
 
     if (fn->entityAttributeValue(meta::Props::token(meta::Props::Token::language)).toString()
-- 
GitLab


From a60050fd9eba36c343ff5d2ee68460b7c28cd1a2 Mon Sep 17 00:00:00 2001
From: Alex Diev <alex.diev@vikingsoftware.com>
Date: Tue, 7 Feb 2023 14:18:27 +0200
Subject: [PATCH 7/9] Check

---
 src/libs/shared/propertytemplate.cpp | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/src/libs/shared/propertytemplate.cpp b/src/libs/shared/propertytemplate.cpp
index 364e891aeb..78ce12751e 100644
--- a/src/libs/shared/propertytemplate.cpp
+++ b/src/libs/shared/propertytemplate.cpp
@@ -345,11 +345,11 @@ void PropertyTemplate::initFromXml(const QDomElement &element)
 
 void PropertyTemplate::addEnumData(const QDomElement &typeEntryElement)
 {
-    const QString valueKey {"value"};
+    const QString valueKey { "value" };
     const QString enumValue = typeEntryElement.attribute(valueKey);
     QMap<QString, QString> data;
     QDomNamedNodeMap attributes = typeEntryElement.attributes();
-    for (int i = 0; i< attributes.count(); ++i) {
+    for (int i = 0; i < attributes.count(); ++i) {
         QDomAttr attr = attributes.item(i).toAttr();
         if (attr.name() != valueKey) {
             data[attr.name()] = attr.value();
@@ -428,7 +428,8 @@ bool PropertyTemplate::validate(const VEObject *object) const
     auto it = d->m_rxAttrValidatorPattern.lowerBound(objScope);
     const auto upperBound = d->m_rxAttrValidatorPattern.upperBound(objScope);
     while (it != upperBound) {
-        auto checkPattern = [](const EntityAttributes &data, const QString &name, const QString &pattern) -> std::optional<bool> {
+        auto checkPattern = [](const EntityAttributes &data, const QString &name,
+                                    const QString &pattern) /*-> std::optional<bool>*/ {
             auto objAttrIter = data.constFind(name);
             if (objAttrIter != data.constEnd()) {
                 const QRegularExpression rx(pattern);
@@ -436,11 +437,14 @@ bool PropertyTemplate::validate(const VEObject *object) const
                 const QRegularExpressionMatch match = rx.match(value);
                 return match.capturedLength() == value.length();
             }
-            return std::nullopt;
+            return true;
+            //            return std::nullopt;
         };
-        auto res = checkPattern(object->entityAttributes(), it->first, it->second);
-        if (res.has_value())
-            return res.value();
+        const auto res = checkPattern(object->entityAttributes(), it->first, it->second);
+        if (res)
+            return true;
+        //        if (res.has_value())
+        //            return res.value();
         ++it;
     }
     return false;
-- 
GitLab


From d81014950eba3a5f72b4537a2e66b1c9b0e536f3 Mon Sep 17 00:00:00 2001
From: Alex Diev <alex.diev@vikingsoftware.com>
Date: Tue, 7 Feb 2023 15:31:22 +0200
Subject: [PATCH 8/9] Revert "Check"

This reverts commit a60050fd9eba36c343ff5d2ee68460b7c28cd1a2.
---
 src/libs/shared/propertytemplate.cpp | 18 +++++++-----------
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/src/libs/shared/propertytemplate.cpp b/src/libs/shared/propertytemplate.cpp
index 78ce12751e..364e891aeb 100644
--- a/src/libs/shared/propertytemplate.cpp
+++ b/src/libs/shared/propertytemplate.cpp
@@ -345,11 +345,11 @@ void PropertyTemplate::initFromXml(const QDomElement &element)
 
 void PropertyTemplate::addEnumData(const QDomElement &typeEntryElement)
 {
-    const QString valueKey { "value" };
+    const QString valueKey {"value"};
     const QString enumValue = typeEntryElement.attribute(valueKey);
     QMap<QString, QString> data;
     QDomNamedNodeMap attributes = typeEntryElement.attributes();
-    for (int i = 0; i < attributes.count(); ++i) {
+    for (int i = 0; i< attributes.count(); ++i) {
         QDomAttr attr = attributes.item(i).toAttr();
         if (attr.name() != valueKey) {
             data[attr.name()] = attr.value();
@@ -428,8 +428,7 @@ bool PropertyTemplate::validate(const VEObject *object) const
     auto it = d->m_rxAttrValidatorPattern.lowerBound(objScope);
     const auto upperBound = d->m_rxAttrValidatorPattern.upperBound(objScope);
     while (it != upperBound) {
-        auto checkPattern = [](const EntityAttributes &data, const QString &name,
-                                    const QString &pattern) /*-> std::optional<bool>*/ {
+        auto checkPattern = [](const EntityAttributes &data, const QString &name, const QString &pattern) -> std::optional<bool> {
             auto objAttrIter = data.constFind(name);
             if (objAttrIter != data.constEnd()) {
                 const QRegularExpression rx(pattern);
@@ -437,14 +436,11 @@ bool PropertyTemplate::validate(const VEObject *object) const
                 const QRegularExpressionMatch match = rx.match(value);
                 return match.capturedLength() == value.length();
             }
-            return true;
-            //            return std::nullopt;
+            return std::nullopt;
         };
-        const auto res = checkPattern(object->entityAttributes(), it->first, it->second);
-        if (res)
-            return true;
-        //        if (res.has_value())
-        //            return res.value();
+        auto res = checkPattern(object->entityAttributes(), it->first, it->second);
+        if (res.has_value())
+            return res.value();
         ++it;
     }
     return false;
-- 
GitLab


From 2364104066e5c2b4329ad42f84d63717995f041d Mon Sep 17 00:00:00 2001
From: Alex Diev <alex.diev@vikingsoftware.com>
Date: Tue, 7 Feb 2023 15:32:58 +0200
Subject: [PATCH 9/9] Check

---
 src/libs/ivcore/ivmodel.cpp  | 21 ++++++++++++++++++++
 src/libs/shared/veobject.cpp | 37 ++++++++++++++++++------------------
 2 files changed, 40 insertions(+), 18 deletions(-)

diff --git a/src/libs/ivcore/ivmodel.cpp b/src/libs/ivcore/ivmodel.cpp
index 0114a16b40..6fefb2511a 100644
--- a/src/libs/ivcore/ivmodel.cpp
+++ b/src/libs/ivcore/ivmodel.cpp
@@ -56,6 +56,27 @@ bool IVModel::addObjectImpl(shared::VEObject *obj)
     if (ivm::IVObject *ivObj = obj->as<ivm::IVObject *>()) {
         if (shared::VEModel::addObjectImpl(obj)) {
             d->m_visibleObjects.append(ivObj);
+            for (const auto attr : d->m_dynPropConfig->propertyTemplatesForObject(ivObj)) {
+                if (attr->validate(ivObj) && !attr->isOptional()) {
+                    const QVariant &currentValue = obj->entityAttributeValue(attr->name());
+                    if (currentValue.isNull()) {
+                        const QVariant &defaultValue = attr->defaultValue();
+                        if (!defaultValue.isNull()) {
+                            if (attr->info() == ivm::IVPropertyTemplate::Info::Attribute) {
+                                obj->setEntityAttribute(attr->name(), defaultValue);
+                            } else if (attr->info() == ivm::IVPropertyTemplate::Info::Property) {
+                                obj->setEntityProperty(attr->name(), defaultValue);
+                            } else {
+                                QMetaEnum metaEnum = QMetaEnum::fromType<shared::PropertyTemplate::Info>();
+                                shared::ErrorHub::addError(shared::ErrorItem::Warning,
+                                        tr("Unknown dynamic property info: %1")
+                                                .arg(metaEnum.valueToKey(int(attr->info()))));
+                            }
+                        }
+                    }
+                }
+            }
+
             return true;
         }
     }
diff --git a/src/libs/shared/veobject.cpp b/src/libs/shared/veobject.cpp
index f16fec1235..26bbd947d4 100644
--- a/src/libs/shared/veobject.cpp
+++ b/src/libs/shared/veobject.cpp
@@ -272,24 +272,25 @@ VEModel *VEObject::model() const
 
 bool VEObject::postInit()
 {
-    if (auto dynPropConfig = propertyTemplaceConfig()) {
-        for (const auto attr : dynPropConfig->propertyTemplatesForObject(this)) {
-            if (attr->validate(this) && !attr->isOptional() && !hasEntityAttribute(attr->name())) {
-                const QVariant &defaultValue = attr->defaultValue();
-                if (!defaultValue.isNull()) {
-                    if (attr->info() == PropertyTemplate::Info::Attribute) {
-                        setEntityAttribute(attr->name(), defaultValue);
-                    } else if (attr->info() == PropertyTemplate::Info::Property) {
-                        setEntityProperty(attr->name(), defaultValue);
-                    } else {
-                        QMetaEnum metaEnum = QMetaEnum::fromType<shared::PropertyTemplate::Info>();
-                        ErrorHub::addError(ErrorItem::Warning,
-                                tr("Unknown dynamic property info: %1").arg(metaEnum.valueToKey(int(attr->info()))));
-                    }
-                }
-            }
-        }
-    }
+    //    if (auto dynPropConfig = propertyTemplaceConfig()) {
+    //        for (const auto attr : dynPropConfig->propertyTemplatesForObject(this)) {
+    //            if (attr->validate(this) && !attr->isOptional() && !hasEntityAttribute(attr->name())) {
+    //                const QVariant &defaultValue = attr->defaultValue();
+    //                if (!defaultValue.isNull()) {
+    //                    if (attr->info() == PropertyTemplate::Info::Attribute) {
+    //                        setEntityAttribute(attr->name(), defaultValue);
+    //                    } else if (attr->info() == PropertyTemplate::Info::Property) {
+    //                        setEntityProperty(attr->name(), defaultValue);
+    //                    } else {
+    //                        QMetaEnum metaEnum = QMetaEnum::fromType<shared::PropertyTemplate::Info>();
+    //                        ErrorHub::addError(ErrorItem::Warning,
+    //                                tr("Unknown dynamic property info:
+    //                                %1").arg(metaEnum.valueToKey(int(attr->info()))));
+    //                    }
+    //                }
+    //            }
+    //        }
+    //    }
     return true;
 }
 
-- 
GitLab