Salome HOME
Issue #1659 New widget for supporting optional inputs : correction for enclosed cases.
authornds <nds@opencascade.com>
Thu, 14 Jul 2016 07:22:58 +0000 (10:22 +0300)
committernds <nds@opencascade.com>
Thu, 14 Jul 2016 07:22:58 +0000 (10:22 +0300)
src/Config/Config_AttributeMessage.cpp
src/Config/Config_AttributeMessage.h
src/Config/Config_Common.cpp
src/Config/Config_Common.h
src/Config/Config_FeatureReader.cpp
src/Model/Model_Session.cpp
src/Model/Model_Validator.cpp
src/Model/Model_Validator.h
src/ModelAPI/ModelAPI_Validator.h
src/ModuleBase/ModuleBase_WidgetCheckGroupBox.cpp

index 973dd3930e2fb272d2157cad99cfc1882c0d7ce3..b154d9cbfbd2c4c9444d945d966c063696f86945 100644 (file)
@@ -9,7 +9,6 @@ Config_AttributeMessage::Config_AttributeMessage(const Events_ID theId, const vo
   myFeatureId = std::string(); // Feature unique id
   myIsObligatory = true;
   myIsConcealment = false;
-  myCaseId = std::string();
 }
 
 Config_AttributeMessage::~Config_AttributeMessage()
@@ -57,22 +56,12 @@ void Config_AttributeMessage::setObligatory(bool theObligatory)
   this->myIsObligatory = theObligatory;
 }
 
-const std::string& Config_AttributeMessage::caseId() const
+const std::list<std::pair<std::string, std::string> >& Config_AttributeMessage::getCases() const
 {
-  return myCaseId;
+  return myCases;
 }
 
-const std::string& Config_AttributeMessage::switchId() const
+void Config_AttributeMessage::setCases(const std::list<std::pair<std::string, std::string> >& theCases)
 {
-  return mySwitchId;
-}
-
-void Config_AttributeMessage::setCaseId(const std::string& theId)
-{
-  this->myCaseId = theId;
-}
-
-void Config_AttributeMessage::setSwitchId(const std::string& theId)
-{
-  this->mySwitchId = theId;
+  myCases = theCases;
 }
index e9ab250ea633cbeddab9e34fc07f74f3bac6da1a..d2a8cf705b44f625ffc292317cfd5c130d0625de 100644 (file)
@@ -8,6 +8,7 @@
 #include <Events_Message.h>
 
 #include <string>
+#include <list>
 
 /*!
  * \class Config_AttributeMessage
@@ -22,10 +23,10 @@ class Config_AttributeMessage : public Events_Message
   std::string myFeatureId; ///< Attribute's feature's unique id
   bool myIsObligatory; ///< Required to be set by user, else it's feature is invalid.
   bool myIsConcealment; ///< If true, conceals features used as input
-  std::string myCaseId; ///< Attribute's case's id, if it placed inside a paged containers
-  std::string mySwitchId; ///< Attribute's switch id, if it placed inside a paged containers
+  ///< a list of pairs, if the attribute is placed inside paged containers: (case, switch)
+  std::list<std::pair<std::string, std::string> > myCases;
 
- public:
+public:
   /// Same event as Config_FeatureMessage::MODEL_EVENT()
   inline static const char* MODEL_EVENT()
   {
@@ -47,10 +48,10 @@ class Config_AttributeMessage : public Events_Message
   CONFIG_EXPORT bool isObligatory() const;
   /// Returns true if attribute should conceal input features
   CONFIG_EXPORT bool isConcealment() const;
-  /// Returns id of a case which contain the attribute
-  CONFIG_EXPORT const std::string& caseId() const;
-  /// Returns id of a switch which contain the attribute
-  CONFIG_EXPORT const std::string& switchId() const;
+  /// Returns container of ids of pair of a case and switches
+  CONFIG_EXPORT const std::list<std::pair<std::string, std::string> >& getCases() const;
+  /// Sets ids of pair of a case and switches
+  CONFIG_EXPORT void setCases(const std::list<std::pair<std::string, std::string> >& theCases);
 
   /// Set attribute's unique id
   CONFIG_EXPORT void setAttributeId(const std::string& theId);
@@ -60,10 +61,6 @@ class Config_AttributeMessage : public Events_Message
   CONFIG_EXPORT void setConcealment(bool isConcealment);
   /// Set attribute's obligatory state
   CONFIG_EXPORT void setObligatory(bool isObligatory);
-  /// Set attribute's case
-  CONFIG_EXPORT void setCaseId(const std::string& id);
-  /// Set attribute's switch
-  CONFIG_EXPORT void setSwitchId(const std::string& id);
 };
 
 #endif // ATTRIBUTE_MESSAGE_H
index 7d2a3ba874e08e43ea979d924ece85027e53f225..ac274ada8ef73524c07911d8ca5f976664e4dc64 100644 (file)
@@ -143,24 +143,24 @@ bool hasParent(xmlNodePtr theNode, const char* theNodeName, ...)
   return false;\r
 }\r
 \r
-bool hasParentRecursive(xmlNodePtr theNode, const std::vector<const char*>& theNodeNames)\r
+xmlNodePtr hasParentRecursive(xmlNodePtr theNode, const std::vector<const char*>& theNodeNames)\r
 {\r
   if (!hasParent(theNode)) {\r
-    return false; // have no parents at all\r
+    return 0; // have no parents at all\r
   }\r
   xmlNodePtr aNode = theNode->parent;\r
   const xmlChar* aName = aNode->name;\r
   if (!aName || !isElementNode(aNode)) {\r
-    return false;\r
+    return 0;\r
   }\r
   for (size_t anIndex = 0; anIndex < theNodeNames.size(); ++anIndex) {\r
     if (!xmlStrcmp(aName, (const xmlChar *) theNodeNames[anIndex]))\r
-      return true;\r
+      return aNode;\r
   }\r
   return hasParentRecursive(aNode, theNodeNames);\r
 }\r
 \r
-bool hasParentRecursive(xmlNodePtr theNode, const char* theNodeName, ...)\r
+xmlNodePtr hasParentRecursive(xmlNodePtr theNode, const char* theNodeName, ...)\r
 {\r
   std::vector<const char*> aNodeNames;\r
   va_list args;  // define argument list variable\r
index 0998a6b73d6899c269951560757ee9fb559172c0..eb7cbc9fa9f2ef97be584f2437e95554b823ddce 100644 (file)
@@ -84,7 +84,7 @@ CONFIG_EXPORT bool hasParent(xmlNodePtr theNode, const char* theNodeName, ...);
 /*!
  * Checks if the given node has any valid parent in hierarchy with any of the given node names.
  */
-CONFIG_EXPORT bool hasParentRecursive(xmlNodePtr theNode, const char* theNodeName, ...);
+CONFIG_EXPORT xmlNodePtr hasParentRecursive(xmlNodePtr theNode, const char* theNodeName, ...);
 
 
 /*!
index 4f3b12cacaa5a042fad1abffc5c643ba77f65071..4797d9d4a2b9105b8615a96d63b044f480d2f441 100644 (file)
@@ -71,23 +71,31 @@ void Config_FeatureReader::processNode(xmlNodePtr theNode)
         aMessage->setAttributeId(anAttributeID);
         aMessage->setObligatory(getBooleanAttribute(theNode, ATTR_OBLIGATORY, true));
         aMessage->setConcealment(getBooleanAttribute(theNode, ATTR_CONCEALMENT, false));
-        if (hasParentRecursive(theNode, WDG_CHECK_GROUP, NULL)) {
-          const char* kWdgCase = WDG_CHECK_GROUP;
-          const char* kWdgSwitch = WDG_CHECK_GROUP;
-          aMessage->setCaseId(restoreAttribute(kWdgCase, _ID));
-          aMessage->setSwitchId(restoreAttribute(kWdgSwitch, _ID));
-        }
-        // nested "paged" widgets are not allowed, this issue may be resolved here:
-        else if (hasParentRecursive(theNode, WDG_SWITCH_CASE, WDG_TOOLBOX_BOX, NULL)) {
-          const char* kWdgCase = hasParentRecursive(theNode, WDG_SWITCH_CASE, NULL)
-                                 ? WDG_SWITCH_CASE
-                                 : WDG_TOOLBOX_BOX;
-          const char* kWdgSwitch = hasParentRecursive(theNode, WDG_SWITCH_CASE, NULL)
-                                   ? WDG_SWITCH
-                                   : WDG_TOOLBOX;
-          aMessage->setCaseId(restoreAttribute(kWdgCase, _ID));
-          aMessage->setSwitchId(restoreAttribute(kWdgSwitch, _ID));
+
+        std::list<std::pair<std::string, std::string> > aCases;
+        xmlNodePtr aCaseNode = hasParentRecursive(theNode, WDG_SWITCH_CASE, WDG_TOOLBOX_BOX, WDG_CHECK_GROUP, NULL);
+        while(aCaseNode) {
+          std::string aCaseNodeID = getProperty(aCaseNode, _ID);
+          std::string aSwitchNodeID = "";
+          const xmlChar* aName = aCaseNode->name;
+          xmlNodePtr aSwitchNode;
+          if (!xmlStrcmp(aName, (const xmlChar *) WDG_SWITCH_CASE)) {
+            aSwitchNode = hasParentRecursive(aCaseNode, WDG_SWITCH, NULL);
+          }
+          else if (!xmlStrcmp(aName, (const xmlChar *) WDG_TOOLBOX_BOX)) {
+            aSwitchNode = hasParentRecursive(aCaseNode, WDG_TOOLBOX, NULL);
+          }
+          if (!xmlStrcmp(aName, (const xmlChar *) WDG_CHECK_GROUP)) {
+            /// the box is optional, attribute is in case if the optional attribute value is not empty
+            aSwitchNode = aCaseNode;
+          }
+          if (aSwitchNode)
+            aSwitchNodeID = getProperty(aSwitchNode, _ID);
+
+          aCases.push_back(std::make_pair(aSwitchNodeID, aCaseNodeID));
+          aCaseNode = hasParentRecursive(aSwitchNode, WDG_SWITCH_CASE, WDG_TOOLBOX_BOX, WDG_CHECK_GROUP, NULL);
         }
+        aMessage->setCases(aCases);
         Events_Loop::loop()->send(aMessage);
       }
     // container pages, like "case" or "box"
index 44d24c0fa07aedd62d78b7d6890e0a6111166d27..ce6a26f9a81268becaf85d3e3a04b3a209d14b06 100644 (file)
@@ -375,9 +375,9 @@ void Model_Session::processEvent(const std::shared_ptr<Events_Message>& theMessa
         if(aMsgAttr->isConcealment()) {
           validators()->registerConcealment(aMsgAttr->featureId(), aMsgAttr->attributeId());
         }
-        if (!aMsgAttr->caseId().empty()) {
-          validators()->registerCase(aMsgAttr->featureId(), aMsgAttr->attributeId(),
-            aMsgAttr->switchId(), aMsgAttr->caseId());
+        const std::list<std::pair<std::string, std::string> >& aCases = aMsgAttr->getCases();
+        if (!aCases.empty()) {
+          validators()->registerCase(aMsgAttr->featureId(), aMsgAttr->attributeId(), aCases);
         }
       }
     }
index 1d420229faaad2c2985c8d6e2163cba9b8337971..ed7ffac935fbe369404336b7f315d183b0077ea8 100644 (file)
@@ -314,40 +314,55 @@ bool Model_ValidatorsFactory::isConcealed(std::string theFeature, std::string th
 }
 
 void Model_ValidatorsFactory::registerCase(std::string theFeature, std::string theAttribute,
-    std::string theSwitchId, std::string theCaseId)
+                            const std::list<std::pair<std::string, std::string> >& theCases)
 {
-  std::map<std::string, std::map<std::string, std::pair<std::string, std::set<std::string> > > >
+  std::map<std::string, std::map<std::string, std::map<std::string, std::set<std::string> > > >
     ::iterator aFindFeature = myCases.find(theFeature);
   if (aFindFeature == myCases.end()) {
-    myCases[theFeature] = std::map<std::string, std::pair<std::string, std::set<std::string> > >();
+    myCases[theFeature] = std::map<std::string, std::map<std::string, std::set<std::string> > >();
     aFindFeature = myCases.find(theFeature);
   }
-  std::map<std::string, std::pair<std::string, std::set<std::string> > >::iterator aFindAttrID =
+  std::map<std::string, std::map<std::string, std::set<std::string> > >::iterator aFindAttrID =
     aFindFeature->second.find(theAttribute);
+
   if (aFindAttrID == aFindFeature->second.end()) {
     aFindFeature->second[theAttribute] =
-      std::pair<std::string, std::set<std::string> >(theSwitchId, std::set<std::string>());
+      std::map<std::string, std::set<std::string> >();
     aFindAttrID = aFindFeature->second.find(theAttribute);
   }
-  aFindAttrID->second.second.insert(theCaseId);
+  std::list<std::pair<std::string, std::string> >::const_iterator aCasesIt = theCases.begin(),
+                                                                        aCasesLast = theCases.end();
+  std::map<std::string, std::set<std::string> > aFindCases = aFindAttrID->second;
+  for (; aCasesIt != aCasesLast; aCasesIt++) {
+    std::pair<std::string, std::string> aCasePair = *aCasesIt;
+    std::string aSwitch = aCasePair.first;
+    if (aFindAttrID->second.find(aSwitch) == aFindAttrID->second.end()) {
+      aFindAttrID->second[aSwitch] = std::set<std::string>();
+    }
+    aFindAttrID->second[aSwitch].insert(aCasePair.second);
+  }
 }
 
 bool Model_ValidatorsFactory::isCase(FeaturePtr theFeature, std::string theAttribute)
 {
-  std::map<std::string, std::map<std::string, std::pair<std::string, std::set<std::string> > > >
+  bool anInCase = true;
+  std::map<std::string, std::map<std::string, std::map<std::string, std::set<std::string> > > >
     ::iterator aFindFeature = myCases.find(theFeature->getKind());
   if (aFindFeature != myCases.end()) {
-    std::map<std::string, std::pair<std::string, std::set<std::string> > >::iterator
+    std::map<std::string, std::map<std::string, std::set<std::string> > >::iterator
       aFindAttrID = aFindFeature->second.find(theAttribute);
     if (aFindAttrID != aFindFeature->second.end()) {
-      // the the switch-attribute that contains the case value
-      AttributeStringPtr aSwitch = theFeature->string(aFindAttrID->second.first);
-      if (aSwitch.get()) {
-         // the second has the case identifier
-        return aFindAttrID->second.second.find(aSwitch->value()) != 
-               aFindAttrID->second.second.end();
+      std::map<std::string, std::set<std::string> >::iterator
+              aCasesIt = aFindAttrID->second.begin(), aCasesLast = aFindAttrID->second.end();
+      for (; aCasesIt != aCasesLast && anInCase; aCasesIt++) {
+        // the the switch-attribute that contains the case value
+        AttributeStringPtr aSwitch = theFeature->string(aCasesIt->first);
+        if (aSwitch.get()) {
+          // the second has the case identifier
+          anInCase =  aCasesIt->second.find(aSwitch->value()) != aCasesIt->second.end();
+        }
       }
     }
   }
-  return true; // if no additional conditions, this attribute is the case to be validated
+  return anInCase; // if no additional conditions, this attribute is the case to be validated
 }
index 2fd016478963d1f9f58fd5f11707297330d68c12..87a9b02da198fec2edf95b2d01b6c43df3fe770f 100644 (file)
@@ -41,7 +41,7 @@ class Model_ValidatorsFactory : public ModelAPI_ValidatorsFactory
   /// Map from feature kind to map of attribute IDs to pair 
   // (switchId (ID of the attribute) and case Ids (possible values of the switch attribute))
   std::map<std::string, std::map<std::string,
-    std::pair<std::string, std::set<std::string> > > > myCases;
+          std::map<std::string, std::set<std::string> > > > myCases;
 
  public:
   /// Registers the instance of the validator by the ID
@@ -94,9 +94,13 @@ class Model_ValidatorsFactory : public ModelAPI_ValidatorsFactory
   /// Returns true that it was registered that attribute conceals the referenced result
   virtual bool isConcealed(std::string theFeature, std::string theAttribute);
 
+  /// register the case-attribute (\a myCases set definition)
+  //virtual void registerCase(std::string theFeature, std::string theAttribute,
+  //  std::string theSwitchId, std::string theCaseId);
+
   /// register the case-attribute (\a myCases set definition)
   virtual void registerCase(std::string theFeature, std::string theAttribute,
-    std::string theSwitchId, std::string theCaseId);
+                            const std::list<std::pair<std::string, std::string> >& theCases);
 
   /// Returns true if the attribute must be checked (the case is selected)
   virtual bool isCase(FeaturePtr theFeature, std::string theAttribute);
index 7fddb71ac6a366e4516074e2c19f1e6e871d1319..0557333ba75079b3ae9ae5b4570d627d13becda9 100644 (file)
@@ -103,7 +103,7 @@ class MODELAPI_EXPORT ModelAPI_ValidatorsFactory
 
   /// Register the case-attribute: this attribute is checked only if its case is selected
   virtual void registerCase(std::string theFeature, std::string theAttribute,
-    std::string theSwitchId, std::string theCaseId) = 0;
+    const std::list<std::pair<std::string, std::string> >& theCases) = 0;
 
  /// Returns true if the attribute must be checked (the case is selected)
   virtual bool isCase(FeaturePtr theFeature, std::string theAttribute) = 0;
index 05f20230615ee5e4983521701cdc14a9382a8c7f..6ca136d04e358cf52080a9e0937ed2fc76d8e3fa 100755 (executable)
@@ -64,6 +64,9 @@ void ModuleBase_WidgetCheckGroupBox::onPageClicked()
 {
   storeValue();
   updateControlsVisibility();
+
+  if (!isEditingMode())
+    emit focusOutWidget(this);
 }
 
 void ModuleBase_WidgetCheckGroupBox::addPageStretch()