From 2f70266a7065a81d239198cf4ca0f507e46b96ff Mon Sep 17 00:00:00 2001 From: Vitaly SMETANNIKOV Date: Tue, 1 Nov 2016 18:28:02 +0300 Subject: [PATCH] Issue #1837: make all files with UNIX end lines --- findDOSfiles.sh | 27 + fixDOSfiles.sh | 5 + src/Config/Config_Common.cpp | 562 +-- src/Config/Config_FeatureMessage.h | 250 +- src/Config/Config_Keywords.h | 258 +- src/Config/Config_def.h | 38 +- src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp | 222 +- .../FeaturesPlugin_Validators.cpp | 1662 ++++---- .../FeaturesPlugin_Validators.h | 440 +- src/ModelAPI/ModelAPI_Tools.cpp | 1172 +++--- src/ModelAPI/ModelAPI_Tools.h | 322 +- src/ModelAPI/Test/TestUndoRedo.py | 74 +- src/ModuleBase/ModuleBase.h | 38 +- src/ModuleBase/ModuleBase_FilterValidated.cpp | 114 +- src/ModuleBase/ModuleBase_IModule.h | 746 ++-- src/ModuleBase/ModuleBase_ModelWidget.cpp | 904 ++--- .../ModuleBase_OperationDescription.h | 148 +- .../ModuleBase_WidgetConcealedObjects.cpp | 296 +- .../ModuleBase_WidgetConcealedObjects.h | 152 +- src/ModuleBase/ModuleBase_WidgetFactory.cpp | 682 ++-- .../ModuleBase_WidgetFeatureSelector.cpp | 350 +- .../ModuleBase_WidgetFeatureSelector.h | 212 +- src/ModuleBase/ModuleBase_WidgetSelector.h | 242 +- src/ModuleBase/ModuleBase_WidgetValidated.cpp | 812 ++-- src/ModuleBase/ModuleBase_WidgetValidated.h | 362 +- src/PartSet/PartSet.h | 38 +- src/PartSet/PartSet_SketcherMgr.cpp | 3614 ++++++++--------- src/PartSet/PartSet_SketcherReetntrantMgr.cpp | 2 +- src/XGUI/XGUI_OperationMgr.cpp | 1490 +++---- 29 files changed, 7633 insertions(+), 7601 deletions(-) create mode 100755 findDOSfiles.sh create mode 100755 fixDOSfiles.sh diff --git a/findDOSfiles.sh b/findDOSfiles.sh new file mode 100755 index 000000000..dca626b70 --- /dev/null +++ b/findDOSfiles.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +function isDOSFile +{ + local FILENAME="$1" + file "$FILENAME" | grep -q "CRLF line terminators" +} + +if git-rev-parse --verify HEAD >/dev/null 2>&1 ; then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 +fi + +# Find files with DOS line endings +FOUND=0 +for FILE in $(exec git diff-index --check --cached $against -- | sed '/^[+-]/d' | sed -r 's/:[0-9]+:.*//' | uniq) ; do + isDOSFile "$FILE" + if (( $? == 0 )) + then + echo "\"$FILE\" has DOS line endings" >&2 + FOUND=1 + fi +done + +exit $FOUND diff --git a/fixDOSfiles.sh b/fixDOSfiles.sh new file mode 100755 index 000000000..d6ac8843d --- /dev/null +++ b/fixDOSfiles.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +find src -type f -name "*.cpp" | xargs dos2unix $1 >/dev/null +find src -type f -name "*.h" | xargs dos2unix $1 >/dev/null +find src -type f -name "*.py" | xargs dos2unix $1 >/dev/null \ No newline at end of file diff --git a/src/Config/Config_Common.cpp b/src/Config/Config_Common.cpp index 4184449f7..46a3f3ce1 100644 --- a/src/Config/Config_Common.cpp +++ b/src/Config/Config_Common.cpp @@ -1,281 +1,281 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -/* - * Config_Common.cpp - * - * Created on: Apr 17, 2014 - * Author: sbh - */ - -#include "Config_Common.h" -#include - -#include -#include - -#include // for stringstream - -#include -#include // for std::transform -#include - -bool isElementNode(xmlNodePtr theNode) -{ - if (!theNode) - return false; - return theNode->type == XML_ELEMENT_NODE; -} - -bool isNode(xmlNodePtr theNode, const char* theNodeName, ...) -{ - const xmlChar* aName = theNode->name; - if (!aName || !isElementNode(theNode)) { - return false; - } - if (!xmlStrcmp(aName, (const xmlChar *) theNodeName)) { - return true; - } - va_list args; // define argument list variable - va_start(args, theNodeName); // init list; point to last defined argument - while (true) { - char *anArg = va_arg (args, char*); // get next argument - if (anArg == NULL) - break; - if (!xmlStrcmp(aName, (const xmlChar *) anArg)) { - va_end(args); // cleanup the system stack - return true; - } - } - va_end(args); // cleanup the system stack - return false; -} - -bool isAttributeNode(xmlNodePtr theNode) -{ - if(!isElementNode(theNode)) - return false; - // it's parent is "feature" or "source" or page ("case" or "box") - if(!hasParent(theNode, NODE_FEATURE, NODE_SOURCE, - WDG_GROUP, WDG_OPTIONALBOX, - WDG_TOOLBOX_BOX, WDG_SWITCH_CASE, NULL)) - return false; - - //it should not be a "source" or a "validator" node - bool isLogical = isNode(theNode, NODE_SOURCE, NODE_VALIDATOR, NODE_SELFILTER, NULL); - // here must be only widgets not connected to attributes - bool isPagedContainer = isNode(theNode, WDG_TOOLBOX_BOX, - WDG_GROUP, - WDG_SWITCH_CASE, NULL); - return !isLogical && !isPagedContainer; -} - -bool isWidgetNode(xmlNodePtr theNode) -{ - if(!isElementNode(theNode)) - return false; - // it's parent is "feature" or "source" or a page ("box", "case") - if(!hasParent(theNode, NODE_FEATURE, NODE_SOURCE, WDG_GROUP, WDG_OPTIONALBOX, - WDG_TOOLBOX_BOX, WDG_SWITCH_CASE, NULL)) - return false; - - //it should not be a "source" or a "validator" node - return !isNode(theNode, NODE_SOURCE, NODE_VALIDATOR, NODE_SELFILTER, NULL); -} - -// widget api? -bool isCaseNode(xmlNodePtr theNode) -{ - if(!isElementNode(theNode)) - return false; - - return isNode(theNode, WDG_OPTIONALBOX, WDG_SWITCH_CASE, WDG_TOOLBOX_BOX, NULL); -} - -bool hasChild(xmlNodePtr theNode) -{ - xmlNodePtr aNode = theNode->children; - for (; aNode; aNode = aNode->next) { - if (isElementNode(theNode)) { - return true; - } - } - return false; -} - -bool hasParent(xmlNodePtr theNode) -{ - xmlNodePtr aNode = theNode->parent; - if (!aNode) { - return false; - } - for (; aNode; aNode = aNode->next) { - if (isElementNode(theNode)) { - return true; - } - } - return false; -} - -bool hasParent(xmlNodePtr theNode, const char* theNodeName, ...) -{ - if (!hasParent(theNode)) { - return false; // have no parents at all - } - xmlNodePtr aNode = theNode->parent; - const xmlChar* aName = aNode->name; - if (!aName || !isElementNode(aNode)) { - return false; - } - if (!xmlStrcmp(aName, (const xmlChar *) theNodeName)) { - return true; - } - va_list args; // define argument list variable - va_start(args, theNodeName); // init list; point to last defined argument - while (true) { - char *anArg = va_arg (args, char*); // get next argument - if (anArg == NULL) - break; - if (!xmlStrcmp(aName, (const xmlChar *) anArg)) { - va_end(args); // cleanup the system stack - return true; - } - } - va_end(args); // cleanup the system stack - return false; -} - -xmlNodePtr hasParentRecursive(xmlNodePtr theNode, const std::vector& theNodeNames) -{ - if (!hasParent(theNode)) { - return 0; // have no parents at all - } - xmlNodePtr aNode = theNode->parent; - const xmlChar* aName = aNode->name; - if (!aName || !isElementNode(aNode)) { - return 0; - } - for (size_t anIndex = 0; anIndex < theNodeNames.size(); ++anIndex) { - if (!xmlStrcmp(aName, (const xmlChar *) theNodeNames[anIndex])) - return aNode; - } - return hasParentRecursive(aNode, theNodeNames); -} - -xmlNodePtr hasParentRecursive(xmlNodePtr theNode, const char* theNodeName, ...) -{ - std::vector aNodeNames; - va_list args; // define argument list variable - va_start(args, theNodeName); // init list; point to last defined argument - aNodeNames.push_back(theNodeName); - while (true) { - char *anArg = va_arg (args, char*); // get next argument - if (anArg == NULL) - break; - aNodeNames.push_back(anArg); - } - va_end(args); // cleanup the system stack - return hasParentRecursive(theNode, aNodeNames); -} - -bool getParametersInfo(xmlNodePtr theNode, std::string& outPropertyId, - std::list& outValidatorParameters) -{ - //Property id: - char* anIdProp = (char*) xmlGetProp(theNode, BAD_CAST _ID); - if (!anIdProp || anIdProp[0] == 0) { - return false; - } - outPropertyId = std::string(anIdProp); - - //Property parameters: - char* aParamProp = (char*) xmlGetProp(theNode, BAD_CAST _PARAMETERS); - if (aParamProp && aParamProp[0] != 0) { - std::string aPropString = std::string(aParamProp); - std::stringstream aPropStringStream(aPropString); - char COMMA_DELIM = ','; - std::string aParameter; - while (std::getline(aPropStringStream, aParameter, ',')) { - outValidatorParameters.push_back(aParameter); - } - } - return true; -} - -std::string library(const std::string& theLibName) -{ - if(theLibName.empty()) - return std::string(); - std::string aLibName = theLibName; -#ifndef WIN32 - static std::string aLibExt( ".so" ); - if (aLibName.size() < 3 || aLibName.substr(0, 3) !="lib") { - aLibName = "lib" + aLibName; - } -#else - static std::string aLibExt(".dll"); -#endif - std::string anExt = aLibName.substr(aLibName.size() - 4); - if (anExt != aLibExt) - aLibName += aLibExt; - - return aLibName; -} - -bool BothAreSpaces(char lhs, char rhs) { return (lhs == rhs) && (lhs == ' '); } - -std::string getProperty(xmlNodePtr theNode, const char* thePropName) -{ - std::string result = ""; - xmlChar* aPropChars = xmlGetProp(theNode, BAD_CAST thePropName); - if (!aPropChars || aPropChars[0] == 0) - return result; - result = std::string((char*)aPropChars); - xmlFree(aPropChars); - - std::string::iterator new_end = std::unique(result.begin(), result.end(), BothAreSpaces); - result.erase(new_end, result.end()); - - return result; -} - -std::string getContent(xmlNodePtr theNode) -{ - std::string result = ""; - xmlChar* aContent = xmlNodeGetContent(theNode); - if (!aContent || aContent[0] == 0) - return result; - result = std::string((char*)aContent); - xmlFree(aContent); - return result; -} - -std::string getNormalizedProperty(xmlNodePtr theNode, const char* thePropName) -{ - return normalize(getProperty(theNode, thePropName)); -} - -bool getBooleanAttribute(xmlNodePtr theNode, const char* theAttributeName, bool theDefault) -{ - std::string prop = normalize(getProperty(theNode, theAttributeName)); - bool result = theDefault; - if (prop == "true" || prop == "1") { - result = true; - } else if (prop == "false" || prop == "0") { - result = false; - } - return result; -} - -CONFIG_EXPORT std::string normalize(const char* theString) -{ - if (!theString) - return std::string(); - return normalize(std::string(theString)); -} - -CONFIG_EXPORT std::string normalize(const std::string& theString) -{ - std::string result = theString; - std::transform(result.begin(), result.end(), result.begin(), ::tolower); - return result; -} +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +/* + * Config_Common.cpp + * + * Created on: Apr 17, 2014 + * Author: sbh + */ + +#include "Config_Common.h" +#include + +#include +#include + +#include // for stringstream + +#include +#include // for std::transform +#include + +bool isElementNode(xmlNodePtr theNode) +{ + if (!theNode) + return false; + return theNode->type == XML_ELEMENT_NODE; +} + +bool isNode(xmlNodePtr theNode, const char* theNodeName, ...) +{ + const xmlChar* aName = theNode->name; + if (!aName || !isElementNode(theNode)) { + return false; + } + if (!xmlStrcmp(aName, (const xmlChar *) theNodeName)) { + return true; + } + va_list args; // define argument list variable + va_start(args, theNodeName); // init list; point to last defined argument + while (true) { + char *anArg = va_arg (args, char*); // get next argument + if (anArg == NULL) + break; + if (!xmlStrcmp(aName, (const xmlChar *) anArg)) { + va_end(args); // cleanup the system stack + return true; + } + } + va_end(args); // cleanup the system stack + return false; +} + +bool isAttributeNode(xmlNodePtr theNode) +{ + if(!isElementNode(theNode)) + return false; + // it's parent is "feature" or "source" or page ("case" or "box") + if(!hasParent(theNode, NODE_FEATURE, NODE_SOURCE, + WDG_GROUP, WDG_OPTIONALBOX, + WDG_TOOLBOX_BOX, WDG_SWITCH_CASE, NULL)) + return false; + + //it should not be a "source" or a "validator" node + bool isLogical = isNode(theNode, NODE_SOURCE, NODE_VALIDATOR, NODE_SELFILTER, NULL); + // here must be only widgets not connected to attributes + bool isPagedContainer = isNode(theNode, WDG_TOOLBOX_BOX, + WDG_GROUP, + WDG_SWITCH_CASE, NULL); + return !isLogical && !isPagedContainer; +} + +bool isWidgetNode(xmlNodePtr theNode) +{ + if(!isElementNode(theNode)) + return false; + // it's parent is "feature" or "source" or a page ("box", "case") + if(!hasParent(theNode, NODE_FEATURE, NODE_SOURCE, WDG_GROUP, WDG_OPTIONALBOX, + WDG_TOOLBOX_BOX, WDG_SWITCH_CASE, NULL)) + return false; + + //it should not be a "source" or a "validator" node + return !isNode(theNode, NODE_SOURCE, NODE_VALIDATOR, NODE_SELFILTER, NULL); +} + +// widget api? +bool isCaseNode(xmlNodePtr theNode) +{ + if(!isElementNode(theNode)) + return false; + + return isNode(theNode, WDG_OPTIONALBOX, WDG_SWITCH_CASE, WDG_TOOLBOX_BOX, NULL); +} + +bool hasChild(xmlNodePtr theNode) +{ + xmlNodePtr aNode = theNode->children; + for (; aNode; aNode = aNode->next) { + if (isElementNode(theNode)) { + return true; + } + } + return false; +} + +bool hasParent(xmlNodePtr theNode) +{ + xmlNodePtr aNode = theNode->parent; + if (!aNode) { + return false; + } + for (; aNode; aNode = aNode->next) { + if (isElementNode(theNode)) { + return true; + } + } + return false; +} + +bool hasParent(xmlNodePtr theNode, const char* theNodeName, ...) +{ + if (!hasParent(theNode)) { + return false; // have no parents at all + } + xmlNodePtr aNode = theNode->parent; + const xmlChar* aName = aNode->name; + if (!aName || !isElementNode(aNode)) { + return false; + } + if (!xmlStrcmp(aName, (const xmlChar *) theNodeName)) { + return true; + } + va_list args; // define argument list variable + va_start(args, theNodeName); // init list; point to last defined argument + while (true) { + char *anArg = va_arg (args, char*); // get next argument + if (anArg == NULL) + break; + if (!xmlStrcmp(aName, (const xmlChar *) anArg)) { + va_end(args); // cleanup the system stack + return true; + } + } + va_end(args); // cleanup the system stack + return false; +} + +xmlNodePtr hasParentRecursive(xmlNodePtr theNode, const std::vector& theNodeNames) +{ + if (!hasParent(theNode)) { + return 0; // have no parents at all + } + xmlNodePtr aNode = theNode->parent; + const xmlChar* aName = aNode->name; + if (!aName || !isElementNode(aNode)) { + return 0; + } + for (size_t anIndex = 0; anIndex < theNodeNames.size(); ++anIndex) { + if (!xmlStrcmp(aName, (const xmlChar *) theNodeNames[anIndex])) + return aNode; + } + return hasParentRecursive(aNode, theNodeNames); +} + +xmlNodePtr hasParentRecursive(xmlNodePtr theNode, const char* theNodeName, ...) +{ + std::vector aNodeNames; + va_list args; // define argument list variable + va_start(args, theNodeName); // init list; point to last defined argument + aNodeNames.push_back(theNodeName); + while (true) { + char *anArg = va_arg (args, char*); // get next argument + if (anArg == NULL) + break; + aNodeNames.push_back(anArg); + } + va_end(args); // cleanup the system stack + return hasParentRecursive(theNode, aNodeNames); +} + +bool getParametersInfo(xmlNodePtr theNode, std::string& outPropertyId, + std::list& outValidatorParameters) +{ + //Property id: + char* anIdProp = (char*) xmlGetProp(theNode, BAD_CAST _ID); + if (!anIdProp || anIdProp[0] == 0) { + return false; + } + outPropertyId = std::string(anIdProp); + + //Property parameters: + char* aParamProp = (char*) xmlGetProp(theNode, BAD_CAST _PARAMETERS); + if (aParamProp && aParamProp[0] != 0) { + std::string aPropString = std::string(aParamProp); + std::stringstream aPropStringStream(aPropString); + char COMMA_DELIM = ','; + std::string aParameter; + while (std::getline(aPropStringStream, aParameter, ',')) { + outValidatorParameters.push_back(aParameter); + } + } + return true; +} + +std::string library(const std::string& theLibName) +{ + if(theLibName.empty()) + return std::string(); + std::string aLibName = theLibName; +#ifndef WIN32 + static std::string aLibExt( ".so" ); + if (aLibName.size() < 3 || aLibName.substr(0, 3) !="lib") { + aLibName = "lib" + aLibName; + } +#else + static std::string aLibExt(".dll"); +#endif + std::string anExt = aLibName.substr(aLibName.size() - 4); + if (anExt != aLibExt) + aLibName += aLibExt; + + return aLibName; +} + +bool BothAreSpaces(char lhs, char rhs) { return (lhs == rhs) && (lhs == ' '); } + +std::string getProperty(xmlNodePtr theNode, const char* thePropName) +{ + std::string result = ""; + xmlChar* aPropChars = xmlGetProp(theNode, BAD_CAST thePropName); + if (!aPropChars || aPropChars[0] == 0) + return result; + result = std::string((char*)aPropChars); + xmlFree(aPropChars); + + std::string::iterator new_end = std::unique(result.begin(), result.end(), BothAreSpaces); + result.erase(new_end, result.end()); + + return result; +} + +std::string getContent(xmlNodePtr theNode) +{ + std::string result = ""; + xmlChar* aContent = xmlNodeGetContent(theNode); + if (!aContent || aContent[0] == 0) + return result; + result = std::string((char*)aContent); + xmlFree(aContent); + return result; +} + +std::string getNormalizedProperty(xmlNodePtr theNode, const char* thePropName) +{ + return normalize(getProperty(theNode, thePropName)); +} + +bool getBooleanAttribute(xmlNodePtr theNode, const char* theAttributeName, bool theDefault) +{ + std::string prop = normalize(getProperty(theNode, theAttributeName)); + bool result = theDefault; + if (prop == "true" || prop == "1") { + result = true; + } else if (prop == "false" || prop == "0") { + result = false; + } + return result; +} + +CONFIG_EXPORT std::string normalize(const char* theString) +{ + if (!theString) + return std::string(); + return normalize(std::string(theString)); +} + +CONFIG_EXPORT std::string normalize(const std::string& theString) +{ + std::string result = theString; + std::transform(result.begin(), result.end(), result.begin(), ::tolower); + return result; +} diff --git a/src/Config/Config_FeatureMessage.h b/src/Config/Config_FeatureMessage.h index d2f758513..f82a249b5 100644 --- a/src/Config/Config_FeatureMessage.h +++ b/src/Config/Config_FeatureMessage.h @@ -1,125 +1,125 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -#ifndef CONFIG_MESSAGE_H -#define CONFIG_MESSAGE_H - -#include -#include - -#include - -/*! - * \class Config_FeatureMessage - * \ingroup Config - * \brief Class to pass a feature entry extracted from xml file. - * Example of the feature entry: - * \code - * - * \endcode - */ -class Config_FeatureMessage : public Events_Message -{ - std::string myId; /// +#include + +#include + +/*! + * \class Config_FeatureMessage + * \ingroup Config + * \brief Class to pass a feature entry extracted from xml file. + * Example of the feature entry: + * \code + * + * \endcode + */ +class Config_FeatureMessage : public Events_Message +{ + std::string myId; /// - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include - -using namespace std; - -// the only created instance of this plugin -static FeaturesPlugin_Plugin* MY_FEATURES_INSTANCE = new FeaturesPlugin_Plugin(); - -FeaturesPlugin_Plugin::FeaturesPlugin_Plugin() -{ - SessionPtr aMgr = ModelAPI_Session::get(); - ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); - aFactory->registerValidator("FeaturesPlugin_ValidatorTransform", - new FeaturesPlugin_ValidatorTransform); - aFactory->registerValidator("FeaturesPlugin_ValidatorCompositeLauncher", - new FeaturesPlugin_ValidatorCompositeLauncher); - aFactory->registerValidator("FeaturesPlugin_ValidatorBaseForGeneration", - new FeaturesPlugin_ValidatorBaseForGeneration); - aFactory->registerValidator("FeaturesPlugin_ValidatorPipeLocations", - new FeaturesPlugin_ValidatorPipeLocations); - aFactory->registerValidator("FeaturesPlugin_ValidatorExtrusionDir", - new FeaturesPlugin_ValidatorExtrusionDir); - aFactory->registerValidator("FeaturesPlugin_ValidatorBooleanSelection", - new FeaturesPlugin_ValidatorBooleanSelection); - aFactory->registerValidator("FeaturesPlugin_ValidatorPartitionSelection", - new FeaturesPlugin_ValidatorPartitionSelection); - aFactory->registerValidator("FeaturesPlugin_ValidatorRemoveSubShapesSelection", - new FeaturesPlugin_ValidatorRemoveSubShapesSelection); - aFactory->registerValidator("FeaturesPlugin_ValidatorRemoveSubShapesResult", - new FeaturesPlugin_ValidatorRemoveSubShapesResult); - aFactory->registerValidator("FeaturesPlugin_ValidatorPipePath", - new FeaturesPlugin_ValidatorPipePath); - aFactory->registerValidator("FeaturesPlugin_ValidatorUnionSelection", - new FeaturesPlugin_ValidatorUnionSelection); - aFactory->registerValidator("FeaturesPlugin_ValidatorUnionArguments", - new FeaturesPlugin_ValidatorUnionArguments); - aFactory->registerValidator("FeaturesPlugin_ValidatorConcealedResult", - new FeaturesPlugin_ValidatorConcealedResult); - - // register this plugin - ModelAPI_Session::get()->registerPlugin(this); -} - -FeaturePtr FeaturesPlugin_Plugin::createFeature(string theFeatureID) -{ - if (theFeatureID == FeaturesPlugin_Extrusion::ID()) { - return FeaturePtr(new FeaturesPlugin_Extrusion); - } else if (theFeatureID == FeaturesPlugin_Revolution::ID()) { - return FeaturePtr(new FeaturesPlugin_Revolution); - } else if (theFeatureID == FeaturesPlugin_Rotation::ID()) { - return FeaturePtr(new FeaturesPlugin_Rotation); - } else if (theFeatureID == FeaturesPlugin_Translation::ID()) { - return FeaturePtr(new FeaturesPlugin_Translation); - } else if (theFeatureID == FeaturesPlugin_Boolean::ID()) { - return FeaturePtr(new FeaturesPlugin_Boolean); - } else if (theFeatureID == FeaturesPlugin_Group::ID()) { - return FeaturePtr(new FeaturesPlugin_Group); - } else if (theFeatureID == FeaturesPlugin_Intersection::ID()) { - return FeaturePtr(new FeaturesPlugin_Intersection); - } else if (theFeatureID == FeaturesPlugin_Partition::ID()) { - return FeaturePtr(new FeaturesPlugin_Partition); - } else if (theFeatureID == FeaturesPlugin_Pipe::ID()) { - return FeaturePtr(new FeaturesPlugin_Pipe); - } else if (theFeatureID == FeaturesPlugin_Placement::ID()) { - return FeaturePtr(new FeaturesPlugin_Placement); - } else if (theFeatureID == FeaturesPlugin_Recover::ID()) { - return FeaturePtr(new FeaturesPlugin_Recover); - } else if (theFeatureID == FeaturesPlugin_ExtrusionCut::ID()) { - return FeaturePtr(new FeaturesPlugin_ExtrusionCut); - } else if (theFeatureID == FeaturesPlugin_ExtrusionFuse::ID()) { - return FeaturePtr(new FeaturesPlugin_ExtrusionFuse); - } else if (theFeatureID == FeaturesPlugin_RevolutionCut::ID()) { - return FeaturePtr(new FeaturesPlugin_RevolutionCut); - } else if (theFeatureID == FeaturesPlugin_RevolutionFuse::ID()) { - return FeaturePtr(new FeaturesPlugin_RevolutionFuse); - } else if (theFeatureID == FeaturesPlugin_RemoveSubShapes::ID()) { - return FeaturePtr(new FeaturesPlugin_RemoveSubShapes); - } else if (theFeatureID == FeaturesPlugin_Union::ID()) { - return FeaturePtr(new FeaturesPlugin_Union); - } - - // feature of such kind is not found - return FeaturePtr(); -} +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +using namespace std; + +// the only created instance of this plugin +static FeaturesPlugin_Plugin* MY_FEATURES_INSTANCE = new FeaturesPlugin_Plugin(); + +FeaturesPlugin_Plugin::FeaturesPlugin_Plugin() +{ + SessionPtr aMgr = ModelAPI_Session::get(); + ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); + aFactory->registerValidator("FeaturesPlugin_ValidatorTransform", + new FeaturesPlugin_ValidatorTransform); + aFactory->registerValidator("FeaturesPlugin_ValidatorCompositeLauncher", + new FeaturesPlugin_ValidatorCompositeLauncher); + aFactory->registerValidator("FeaturesPlugin_ValidatorBaseForGeneration", + new FeaturesPlugin_ValidatorBaseForGeneration); + aFactory->registerValidator("FeaturesPlugin_ValidatorPipeLocations", + new FeaturesPlugin_ValidatorPipeLocations); + aFactory->registerValidator("FeaturesPlugin_ValidatorExtrusionDir", + new FeaturesPlugin_ValidatorExtrusionDir); + aFactory->registerValidator("FeaturesPlugin_ValidatorBooleanSelection", + new FeaturesPlugin_ValidatorBooleanSelection); + aFactory->registerValidator("FeaturesPlugin_ValidatorPartitionSelection", + new FeaturesPlugin_ValidatorPartitionSelection); + aFactory->registerValidator("FeaturesPlugin_ValidatorRemoveSubShapesSelection", + new FeaturesPlugin_ValidatorRemoveSubShapesSelection); + aFactory->registerValidator("FeaturesPlugin_ValidatorRemoveSubShapesResult", + new FeaturesPlugin_ValidatorRemoveSubShapesResult); + aFactory->registerValidator("FeaturesPlugin_ValidatorPipePath", + new FeaturesPlugin_ValidatorPipePath); + aFactory->registerValidator("FeaturesPlugin_ValidatorUnionSelection", + new FeaturesPlugin_ValidatorUnionSelection); + aFactory->registerValidator("FeaturesPlugin_ValidatorUnionArguments", + new FeaturesPlugin_ValidatorUnionArguments); + aFactory->registerValidator("FeaturesPlugin_ValidatorConcealedResult", + new FeaturesPlugin_ValidatorConcealedResult); + + // register this plugin + ModelAPI_Session::get()->registerPlugin(this); +} + +FeaturePtr FeaturesPlugin_Plugin::createFeature(string theFeatureID) +{ + if (theFeatureID == FeaturesPlugin_Extrusion::ID()) { + return FeaturePtr(new FeaturesPlugin_Extrusion); + } else if (theFeatureID == FeaturesPlugin_Revolution::ID()) { + return FeaturePtr(new FeaturesPlugin_Revolution); + } else if (theFeatureID == FeaturesPlugin_Rotation::ID()) { + return FeaturePtr(new FeaturesPlugin_Rotation); + } else if (theFeatureID == FeaturesPlugin_Translation::ID()) { + return FeaturePtr(new FeaturesPlugin_Translation); + } else if (theFeatureID == FeaturesPlugin_Boolean::ID()) { + return FeaturePtr(new FeaturesPlugin_Boolean); + } else if (theFeatureID == FeaturesPlugin_Group::ID()) { + return FeaturePtr(new FeaturesPlugin_Group); + } else if (theFeatureID == FeaturesPlugin_Intersection::ID()) { + return FeaturePtr(new FeaturesPlugin_Intersection); + } else if (theFeatureID == FeaturesPlugin_Partition::ID()) { + return FeaturePtr(new FeaturesPlugin_Partition); + } else if (theFeatureID == FeaturesPlugin_Pipe::ID()) { + return FeaturePtr(new FeaturesPlugin_Pipe); + } else if (theFeatureID == FeaturesPlugin_Placement::ID()) { + return FeaturePtr(new FeaturesPlugin_Placement); + } else if (theFeatureID == FeaturesPlugin_Recover::ID()) { + return FeaturePtr(new FeaturesPlugin_Recover); + } else if (theFeatureID == FeaturesPlugin_ExtrusionCut::ID()) { + return FeaturePtr(new FeaturesPlugin_ExtrusionCut); + } else if (theFeatureID == FeaturesPlugin_ExtrusionFuse::ID()) { + return FeaturePtr(new FeaturesPlugin_ExtrusionFuse); + } else if (theFeatureID == FeaturesPlugin_RevolutionCut::ID()) { + return FeaturePtr(new FeaturesPlugin_RevolutionCut); + } else if (theFeatureID == FeaturesPlugin_RevolutionFuse::ID()) { + return FeaturePtr(new FeaturesPlugin_RevolutionFuse); + } else if (theFeatureID == FeaturesPlugin_RemoveSubShapes::ID()) { + return FeaturePtr(new FeaturesPlugin_RemoveSubShapes); + } else if (theFeatureID == FeaturesPlugin_Union::ID()) { + return FeaturePtr(new FeaturesPlugin_Union); + } + + // feature of such kind is not found + return FeaturePtr(); +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp index b682efc1c..c29889567 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp @@ -1,831 +1,831 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> - -// File: FeaturesPlugin_Validators.cpp -// Created: 22 March 2016 -// Author: Dmitry Bobylev - -#include "FeaturesPlugin_Validators.h" - -#include "FeaturesPlugin_Union.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define _USE_MATH_DEFINES -#include - -//================================================================================================== -bool FeaturesPlugin_ValidatorPipePath::isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - Events_InfoMessage& theError) const -{ - AttributeSelectionPtr aPathAttrSelection = std::dynamic_pointer_cast(theAttribute); - if(!aPathAttrSelection.get()) { - theError = "Error: This validator can only work with path selector in \"Pipe\" feature."; - return false; - } - - GeomShapePtr aPathShape = aPathAttrSelection->value(); - ResultPtr aContext = aPathAttrSelection->context(); - if(!aContext.get()) { - theError = "Error: Empty context."; - return false; - } - GeomShapePtr aContextShape = aContext->shape(); - if(aPathShape.get() && aPathShape->shapeType() == GeomAPI_Shape::WIRE && !aPathShape->isEqual(aContextShape)) { - theError = "Error: Local selection of wires not allowed."; - return false; - } - - return true; -} - -//================================================================================================== -bool FeaturesPlugin_ValidatorPipeLocations::isValid(const std::shared_ptr& theFeature, - const std::list& theArguments, - Events_InfoMessage& theError) const -{ - static const std::string aCreationMethodID = "creation_method"; - static const std::string aBaseObjectsID = "base_objects"; - static const std::string aLocationsID = "locations_objects"; - - if(theFeature->getKind() != "Pipe") { - theError = "Error: Feature \"%1\" does not supported by this validator."; - theError.arg(theFeature->getKind()); - return false; - } - - AttributeStringPtr aCreationMethodAttr = theFeature->string(aCreationMethodID); - if(!aCreationMethodAttr.get()) { - theError = "Error: Could not get \"%1\" attribute."; - theError.arg(aCreationMethodID); - return false; - } - - if(aCreationMethodAttr->value() != "locations") { - return true; - } - - AttributeSelectionListPtr aBaseObjectsSelectionList = theFeature->selectionList(aBaseObjectsID); - if(!aBaseObjectsSelectionList.get()) { - theError = "Error: Could not get \"%1\" attribute."; - theError.arg(aBaseObjectsID); - return false; - } - - AttributeSelectionListPtr aLocationsSelectionList = theFeature->selectionList(aLocationsID); - if(!aLocationsSelectionList.get()) { - theError = "Error: Could not get \"%1\" attribute."; - theError.arg(aBaseObjectsID); - return false; - } - - if(aLocationsSelectionList->size() > 0 && aLocationsSelectionList->size() != aBaseObjectsSelectionList->size()) { - theError = "Error: Number of locations should be the same as base objects."; - return false; - } - - return true; -} - -//================================================================================================== -bool FeaturesPlugin_ValidatorPipeLocations::isNotObligatory(std::string theFeature, std::string theAttribute) -{ - return false; -} - -//================================================================================================== -bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - Events_InfoMessage& theError) const -{ - if(theArguments.empty()) { - theError = "Error: Validator parameters is empty."; - return false; - } - - // Checking attribute. - if(!isValidAttribute(theAttribute, theArguments, theError)) { - if(theError.empty()) { - theError = "Error: Attribute contains unacceptable shape."; - } - return false; - } - - std::set aSelectedSketches; - std::set aSelectedSketchesFromObjects; - GeomAPI_DataMapOfShapeShape aSelectedWiresFromObjects; - std::string anAttributeType = theAttribute->attributeType(); - if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) { - AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast(theAttribute); - for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) { - AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex); - ResultPtr aContext = aSelectionAttr->context(); - if(!aContext.get()) { - theError = "Error: Empty context."; - return false; - } - - ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast(aContext); - if(!aResultConstruction.get()) { - // It is not a result construction. If shape is compound check that it contains only faces and edges. - GeomShapePtr aShape = aSelectionAttr->value(); - if(!aShape.get()) { - aShape = aContext->shape(); - } - - if(aShape->shapeType() == GeomAPI_Shape::COMPOUND) { - for(GeomAPI_ShapeIterator anIt(aShape); anIt.more(); anIt.next()) { - GeomShapePtr aSubShape = anIt.current(); - if(aSubShape->shapeType() != GeomAPI_Shape::EDGE - && aSubShape->shapeType() != GeomAPI_Shape::FACE) { - theError = "Error: Compound should contain only faces and edges."; - return false; - } - } - } - - continue; - } - - GeomShapePtr aShape = aSelectionAttr->value(); - GeomShapePtr aContextShape = aResultConstruction->shape(); - if(!aShape.get()) { - // Whole sketch selected. - if(aSelectedSketchesFromObjects.find(aResultConstruction) != aSelectedSketchesFromObjects.cend()) { - theError = "Error: Object from this sketch is already selected. Sketch is not allowed for selection."; - return false; - } - - aSelectedSketches.insert(aResultConstruction); - } else { - // Object from sketch selected. - if(aSelectedSketches.find(aResultConstruction) != aSelectedSketches.cend()) { - theError = "Error: Whole sketch with this object is already selected. Don't allow to select this object."; - return false; - } - - for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) { - GeomShapePtr aWire = anExp.current(); - if(aWire->orientation() != GeomAPI_Shape::FORWARD) { - theError = "Error: Wire with wrong orientation selected."; - return false; - } - - if(aSelectedWiresFromObjects.isBound(aWire)) { - theError = "Error: Objects with such wire already selected. Don't allow to select this object."; - return false; - } - - aSelectedWiresFromObjects.bind(aWire, aWire); - aSelectedSketchesFromObjects.insert(aResultConstruction); - } - } - } - } - - return true; -} - -//================================================================================================== -bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const AttributePtr& theAttribute, - const std::list& theArguments, - Events_InfoMessage& theError) const -{ - if(!theAttribute.get()) { - theError = "Error: Empty attribute."; - return false; - } - - std::string anAttributeType = theAttribute->attributeType(); - if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) { - AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast(theAttribute); - for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) { - // If at least one attribute is invalid, the result is false. - if(!isValidAttribute(aListAttr->value(anIndex), theArguments, theError)) { - return false; - } - } - } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) { - // Getting context. - AttributeSelectionPtr anAttr = std::dynamic_pointer_cast(theAttribute); - ResultPtr aContext = anAttr->context(); - if(!aContext.get()) { - theError = "Error: Attribute have empty context."; - return false; - } - - GeomShapePtr aShape = anAttr->value(); - GeomShapePtr aContextShape = aContext->shape(); - if(!aShape.get()) { - aShape = aContextShape; - } - if(!aShape.get()) { - theError = "Error: Empty shape selected"; - return false; - } - - ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aContext); - if(aConstruction.get()) { - // Construciotn selected. Check that is is not infinite. - if(aConstruction->isInfinite()) { - theError = "Error: Infinite constructions is not allowed as base."; - return false; - } - - if(aShape->isEqual(aContextShape)) { - // Whole construction selected. Check that it have faces. - if(aConstruction->facesNum() > 0) { - return true; - } - } else { - // Shape on construction selected. Check that it is a face or wire. - if(aShape->shapeType() == GeomAPI_Shape::WIRE || aShape->shapeType() == GeomAPI_Shape::FACE) { - return true; - } - } - - return false; - } - - if(!aShape->isEqual(aContextShape)) { - // Local selection on body does not allowed. - theError = "Error: Selected shape is in the local selection. Only global selection is allowed."; - return false; - } - - // Check that object is a shape with allowed type. - GeomValidators_ShapeType aShapeTypeValidator; - if(!aShapeTypeValidator.isValid(anAttr, theArguments, theError)) { - theError = "Error: Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, whole sketch(if it has at least one face), and whole objects with shape types: %1"; - std::string anArgumentString; - for(auto anIt = theArguments.cbegin(); anIt != theArguments.cend(); ++anIt) { - if (!anArgumentString.empty()) - anArgumentString += ", "; - anArgumentString += *anIt; - } - theError.arg(anArgumentString); - return false; - } - - } else { - theError = "Error: Attribute \"%1\" does not supported by this validator."; - theError.arg(anAttributeType); - return false; - } - - return true; -} - -//================================================================================================== -bool FeaturesPlugin_ValidatorCompositeLauncher::isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - Events_InfoMessage& theError) const -{ - if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) { - theError = "Error: The attribute with the %1 type is not processed"; - theError.arg(theAttribute->attributeType()); - return false; - } - if (theArguments.size() != 2) { - theError = "Error: Wrong parameters in XML definition for %1 type"; - theError.arg(theAttribute->attributeType()); - return false; - } - // first argument is for the base attribute, second - for skipping feature kind - std::list::const_iterator anIt = theArguments.begin(); - std::string aBaseAttributeId = *anIt; - FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner()); - AttributePtr aBaseAttribute = aFeature->attribute(aBaseAttributeId); - if (!aBaseAttribute.get()) { - theError = "Wrong parameters in XML definition for %1 type"; - theError.arg(theAttribute->attributeType()); - return false; - } - if (aBaseAttribute->isInitialized()) // when base list of composite feature is already filled, - // this validator is not necessary anymore - return true; - - anIt++; - std::string aFeatureAttributeKind = *anIt; - GeomValidators_FeatureKind* aValidator = new GeomValidators_FeatureKind(); - // check whether the selection is on the sketch - std::list anArguments; - anArguments.push_back(aFeatureAttributeKind); - - bool aFeatureKind = aValidator->isValid(theAttribute, theArguments, theError); - bool aPlanarFace = false; - // check if selection has Face selected - GeomValidators_ShapeType* aShapeType = new GeomValidators_ShapeType(); - anArguments.clear(); - anArguments.push_back("face"); - aPlanarFace = aShapeType->isValid(theAttribute, anArguments, theError); - - bool aValid = !aFeatureKind && aPlanarFace; - return aValid; -} - -//================================================================================================== -bool FeaturesPlugin_ValidatorExtrusionDir::isValid(const std::shared_ptr& theFeature, - const std::list& theArguments, - Events_InfoMessage& theError) const -{ - if(theArguments.size() != 2) { - theError = "Error: Validator should be used with 2 parameters for extrusion."; - return false; - } - - std::list::const_iterator anArgsIt = theArguments.begin(), aLast = theArguments.end(); - - AttributePtr aCheckAttribute = theFeature->attribute(*anArgsIt); - ++anArgsIt; - - GeomShapePtr aDirShape; - AttributeSelectionPtr aSelAttr = theFeature->selection(*anArgsIt); - if(aSelAttr.get()) { - aDirShape = aSelAttr->value(); - if(!aDirShape.get()) { - ResultPtr aContext = aSelAttr->context(); - if(aContext.get()) { - aDirShape = aContext->shape(); - } - } - } - - if(!aDirShape.get()) { - // Check that dir can be empty. - if(!isShapesCanBeEmpty(aCheckAttribute, theError)) { - theError = "Error: Base objects list contains vertex or edge, so attribute \"%1\" can not be used with default value. Select direction for extrusion."; - theError.arg(*anArgsIt); - return false; - } else { - return true; - } - } - - std::shared_ptr aDirEdge(new GeomAPI_Edge(aDirShape)); - - // If faces selected check that direction not parallel with them. - AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast(aCheckAttribute); - for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) { - AttributeSelectionPtr anAttr = aListAttr->value(anIndex); - GeomShapePtr aShapeInList = anAttr->value(); - if(!aShapeInList.get()) { - aShapeInList = anAttr->context()->shape(); - } - bool isParallel = true; - if(aShapeInList->shapeType() == GeomAPI_Shape::FACE || aShapeInList->shapeType() == GeomAPI_Shape::SHELL) { - for(GeomAPI_ShapeExplorer anExp(aShapeInList, GeomAPI_Shape::FACE); anExp.more(); anExp.next()) { - std::shared_ptr aFace(new GeomAPI_Face(anExp.current())); - isParallel = GeomAlgoAPI_ShapeTools::isParallel(aDirEdge, aFace); - if(isParallel) { - break; - } - } - } else if(aShapeInList->shapeType() == GeomAPI_Shape::COMPOUND) { - std::shared_ptr aPlanarEdges = std::dynamic_pointer_cast(aShapeInList); - if(aPlanarEdges.get()) { - std::shared_ptr aSketchDir = aPlanarEdges->norm(); - if(aDirEdge->isLine()) { - std::shared_ptr aDir = aDirEdge->line()->direction(); - isParallel = fabs(aSketchDir->angle(aDir) - M_PI / 2.0) < 10e-7; - } else { - isParallel = false; - } - } else { - isParallel = false; - } - } else { - isParallel = false; - } - if(isParallel) { - theError = "Error: Direction is parallel to one of the selected face or face on selected shell."; - return false; - } - } - - return true; -} - -//================================================================================================== -bool FeaturesPlugin_ValidatorExtrusionDir::isNotObligatory(std::string theFeature, std::string theAttribute) -{ - return false; -} - -//================================================================================================== -bool FeaturesPlugin_ValidatorExtrusionDir::isShapesCanBeEmpty(const AttributePtr& theAttribute, - Events_InfoMessage& theError) const -{ - if(!theAttribute.get()) { - return true; - } - - std::string anAttributeType = theAttribute->attributeType(); - if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) { - AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast(theAttribute); - for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) { - // If at least one attribute is invalid, the result is false. - if(!isShapesCanBeEmpty(aListAttr->value(anIndex), theError)) { - return false; - } - } - } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) { - // Getting context. - AttributeSelectionPtr anAttr = std::dynamic_pointer_cast(theAttribute); - ResultPtr aContext = anAttr->context(); - if(!aContext.get()) { - return false; - } - - GeomShapePtr aShape = anAttr->value(); - GeomShapePtr aContextShape = aContext->shape(); - if(!aShape.get()) { - aShape = aContextShape; - } - if(!aShape.get()) { - return false; - } - - if(aShape->shapeType() == GeomAPI_Shape::VERTEX || - aShape->shapeType() == GeomAPI_Shape::EDGE || - !aShape->isPlanar()) { - return false; - } - } else { - return false; - } - - return true; -} - -//================================================================================================== -bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - Events_InfoMessage& theError) const -{ - AttributeSelectionListPtr anAttrSelectionList = std::dynamic_pointer_cast(theAttribute); - if(!anAttrSelectionList.get()) { - theError = "Error: This validator can only work with selection list attributes in \"Boolean\" feature."; - return false; - } - FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); - int anOperationType = aFeature->integer("bool_type")->value(); - - for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) { - AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex); - if(!anAttrSelection.get()) { - theError = "Error: Empty attribute selection."; - return false; - } - ResultPtr aContext = anAttrSelection->context(); - if(!aContext.get()) { - theError = "Error: Empty selection context."; - return false; - } - ResultConstructionPtr aResultConstruction = - std::dynamic_pointer_cast(aContext); - if(aResultConstruction.get()) { - theError = "Error: Result construction not allowed for selection."; - return false; - } - std::shared_ptr aShape = anAttrSelection->value(); - GeomShapePtr aContextShape = aContext->shape(); - if(!aShape.get()) { - aShape = aContextShape; - } - if(!aShape.get()) { - theError = "Error: Empty shape."; - return false; - } - if(!aShape->isEqual(aContextShape)) { - theError = "Error: Local selection not allowed."; - return false; - } - - int aShapeType = aShape->shapeType(); - if(anOperationType == 1) { - // Fuse operation. Allow to select edges, faces and solids. - if(aShapeType != GeomAPI_Shape::EDGE && - aShapeType != GeomAPI_Shape::FACE && - aShapeType != GeomAPI_Shape::SOLID && - aShapeType != GeomAPI_Shape::COMPSOLID && - aShapeType != GeomAPI_Shape::COMPOUND) { - theError = "Error: Selected shape has the wrong type."; - return false; - } - } else { - if(aShapeType != GeomAPI_Shape::SOLID && - aShapeType != GeomAPI_Shape::COMPSOLID && - aShapeType != GeomAPI_Shape::COMPOUND) { - theError = "Error: Selected shape has the wrong type."; - return false; - } - } - } - - return true; -} - -//================================================================================================== -bool FeaturesPlugin_ValidatorPartitionSelection::isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - Events_InfoMessage& theError) const -{ - AttributeSelectionListPtr anAttrSelectionList = std::dynamic_pointer_cast(theAttribute); - if(!anAttrSelectionList.get()) { - theError = "Error: This validator can only work with selection list in \"Partition\" feature."; - return false; - } - - for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) { - AttributeSelectionPtr aSelectAttr = anAttrSelectionList->value(anIndex); - - //GeomValidators_BodyShapes aBodyValidator; - //if(aBodyValidator.isValid(aSelectAttr, theArguments, theError)) { - // continue; - //} - - GeomValidators_FeatureKind aFeatureKindValidator; - if(aFeatureKindValidator.isValid(aSelectAttr, theArguments, theError)) { - continue; - } - - ResultPtr aContext = aSelectAttr->context(); - ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast(aContext); - if(aResultConstruction.get()) { - theError = "Error: Only body shapes and construction planes are allowed for selection."; - return false; - } - - ResultCompSolidPtr aResultCompsolid = std::dynamic_pointer_cast(aContext); - if(aResultCompsolid.get()) { - continue; - } - - theError = "Error: Only body shapes and construction planes are allowed for selection."; - return false; - } - - theError = ""; - return true; -} - -//================================================================================================== -bool FeaturesPlugin_ValidatorRemoveSubShapesSelection::isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - Events_InfoMessage& theError) const -{ - AttributeSelectionListPtr aSubShapesAttrList = std::dynamic_pointer_cast(theAttribute); - if(!aSubShapesAttrList.get()) { - theError = "Error: This validator can only work with selection list in \"Remove Sub-Shapes\" feature."; - return false; - } - - static const std::string aBaseShapeID = "base_shape"; - FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); - AttributeSelectionPtr aShapeAttrSelection = aFeature->selection(aBaseShapeID); - - if(!aShapeAttrSelection.get()) { - theError = "Error: Could not get \"%1\" attribute."; - theError.arg(aBaseShapeID); - return false; - } - - GeomShapePtr aBaseShape = aShapeAttrSelection->value(); - ResultPtr aContext = aShapeAttrSelection->context(); - if(!aContext.get()) { - theError = "Error: Empty context."; - return false; - } - if(!aBaseShape.get()) { - aBaseShape = aContext->shape(); - } - if(!aBaseShape.get()) { - theError = "Error: Empty base shape."; - return false; - } - - for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) { - bool isSameFound = false; - AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex); - GeomShapePtr aShapeToAdd = anAttrSelectionInList->value(); - for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) { - if(anIt.current()->isEqual(aShapeToAdd)) { - isSameFound = true; - break; - } - } - if(!isSameFound) { - theError = "Error: Only sub-shapes of selected shape is allowed for selection."; - return false; - } - } - - return true; -} - -//================================================================================================== -bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isValid(const std::shared_ptr& theFeature, - const std::list& theArguments, - Events_InfoMessage& theError) const -{ - static const std::string aBaseShapeID = "base_shape"; - static const std::string aSubShapesID = "subshapes"; - - if(theFeature->getKind() != "Remove_SubShapes") { - theError = "Error: Feature \"%1\" does not supported by this validator."; - theError.arg(theFeature->getKind()); - return false; - } - - AttributeSelectionPtr aShapeAttrSelection = theFeature->selection(aBaseShapeID); - if(!aShapeAttrSelection.get()) { - theError = "Error: Could not get \"%1\" attribute."; - theError.arg(aBaseShapeID); - return false; - } - - AttributeSelectionListPtr aSubShapesAttrList = theFeature->selectionList(aSubShapesID); - if(!aSubShapesAttrList.get()) { - theError = "Error: Could not get \"%1\" attribute."; - theError.arg(aSubShapesID); - return false; - } - - // Copy base shape. - GeomShapePtr aBaseShape = aShapeAttrSelection->value(); - if(!aBaseShape.get()) { - theError = "Error: Base shape is empty."; - return false; - } - GeomShapePtr aResultShape = aBaseShape->emptyCopied(); - - // Copy sub-shapes from list to new shape. - for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) { - AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex); - GeomShapePtr aShapeToAdd = anAttrSelectionInList->value(); - GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd); - } - - // Check new shape. - if(!GeomAlgoAPI_ShapeTools::isShapeValid(aResultShape)) { - theError = "Error: Resulting shape is not valid."; - return false; - } - - return true; -} - -//================================================================================================== -bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isNotObligatory(std::string theFeature, - std::string theAttribute) -{ - return false; -} - -//================================================================================================== -bool FeaturesPlugin_ValidatorUnionSelection::isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - Events_InfoMessage& theError) const -{ - AttributeSelectionListPtr aBaseObjectsAttrList = std::dynamic_pointer_cast(theAttribute); - if(!aBaseObjectsAttrList.get()) { - theError = "Error: This validator can only work with selection list in \"%1\" feature."; - theError.arg(FeaturesPlugin_Union::ID()); - return false; - } - - for(int anIndex = 0; anIndex < aBaseObjectsAttrList->size(); ++anIndex) { - bool isSameFound = false; - AttributeSelectionPtr anAttrSelectionInList = aBaseObjectsAttrList->value(anIndex); - ResultCompSolidPtr aResult = std::dynamic_pointer_cast(anAttrSelectionInList->context()); - if(!aResult.get()) { - continue; - } - if(aResult->numberOfSubs() > 0) { - theError = "Error: Whole compsolids not allowed for selection."; - return false; - } - } - - return true; -} - -//================================================================================================== -bool FeaturesPlugin_ValidatorUnionArguments::isValid(const std::shared_ptr& theFeature, - const std::list& theArguments, - Events_InfoMessage& theError) const -{ - // Check feature kind. - if(theFeature->getKind() != FeaturesPlugin_Union::ID()) { - theError = "Error: This validator supports only \"%1\" feature."; - theError.arg(FeaturesPlugin_Union::ID()); - return false; - } - - // Get base objects attribute list. - AttributeSelectionListPtr aBaseObejctsAttrList = theFeature->selectionList(FeaturesPlugin_Union::BASE_OBJECTS_ID()); - if(!aBaseObejctsAttrList.get()) { - theError = "Error: Could not get \"%1\" attribute."; - theError.arg(FeaturesPlugin_Union::BASE_OBJECTS_ID()); - return false; - } - - // Get all shapes. - ListOfShape aBaseShapesList; - for(int anIndex = 0; anIndex < aBaseObejctsAttrList->size(); ++anIndex) { - AttributeSelectionPtr anAttrSelectionInList = aBaseObejctsAttrList->value(anIndex); - GeomShapePtr aShape = anAttrSelectionInList->value(); - aBaseShapesList.push_back(aShape); - } - - // Make componud and find connected. - GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseShapesList); - ListOfShape aCombined, aFree; - GeomAlgoAPI_ShapeTools::combineShapes(aCompound, GeomAPI_Shape::COMPSOLID, aCombined, aFree); - - if(aFree.size() > 0 || aCombined.size() > 1) { - theError = "Error: Not all shapes have shared topology."; - return false; - } - - return true; -} - -//================================================================================================== -bool FeaturesPlugin_ValidatorUnionArguments::isNotObligatory(std::string theFeature, - std::string theAttribute) -{ - return false; -} - -bool FeaturesPlugin_ValidatorConcealedResult::isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - Events_InfoMessage& theError) const -{ - if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) { - theError = "Error: The attribute with the %1 type is not processed"; - theError.arg(theAttribute->attributeType()); - return false; - } - - AttributeReferencePtr aRefAttribute = std::dynamic_pointer_cast - (theAttribute); - ObjectPtr aRefObject = aRefAttribute->value(); - if (!aRefObject.get()) { - theError = "Error: Empty feature."; - return false; - } - - FeaturePtr aRefFeature = std::dynamic_pointer_cast(aRefObject); - if (!aRefFeature.get()) { - theError = "Error: Empty feature."; - return false; - } - std::list > aResults; - ModelAPI_Tools::getConcealedResults(aRefFeature, aResults); - - size_t aConcealedResults = aResults.size(); - if (!aConcealedResults && !theArguments.empty()) { - // find if these results are touched by the feature in another attribute - std::list::const_iterator anIt = theArguments.begin(); - std::string aRecoveredList = *anIt; - if (!aRecoveredList.empty()) { - std::shared_ptr aParameterList = - theAttribute->owner()->data()->reflist(aRecoveredList); - if (aParameterList.get()) - aConcealedResults = aParameterList->size(); - } - } - - if (aConcealedResults == 0) - theError = "Error: No concealed results."; - - return theError.empty(); -} +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: FeaturesPlugin_Validators.cpp +// Created: 22 March 2016 +// Author: Dmitry Bobylev + +#include "FeaturesPlugin_Validators.h" + +#include "FeaturesPlugin_Union.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define _USE_MATH_DEFINES +#include + +//================================================================================================== +bool FeaturesPlugin_ValidatorPipePath::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + AttributeSelectionPtr aPathAttrSelection = std::dynamic_pointer_cast(theAttribute); + if(!aPathAttrSelection.get()) { + theError = "Error: This validator can only work with path selector in \"Pipe\" feature."; + return false; + } + + GeomShapePtr aPathShape = aPathAttrSelection->value(); + ResultPtr aContext = aPathAttrSelection->context(); + if(!aContext.get()) { + theError = "Error: Empty context."; + return false; + } + GeomShapePtr aContextShape = aContext->shape(); + if(aPathShape.get() && aPathShape->shapeType() == GeomAPI_Shape::WIRE && !aPathShape->isEqual(aContextShape)) { + theError = "Error: Local selection of wires not allowed."; + return false; + } + + return true; +} + +//================================================================================================== +bool FeaturesPlugin_ValidatorPipeLocations::isValid(const std::shared_ptr& theFeature, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + static const std::string aCreationMethodID = "creation_method"; + static const std::string aBaseObjectsID = "base_objects"; + static const std::string aLocationsID = "locations_objects"; + + if(theFeature->getKind() != "Pipe") { + theError = "Error: Feature \"%1\" does not supported by this validator."; + theError.arg(theFeature->getKind()); + return false; + } + + AttributeStringPtr aCreationMethodAttr = theFeature->string(aCreationMethodID); + if(!aCreationMethodAttr.get()) { + theError = "Error: Could not get \"%1\" attribute."; + theError.arg(aCreationMethodID); + return false; + } + + if(aCreationMethodAttr->value() != "locations") { + return true; + } + + AttributeSelectionListPtr aBaseObjectsSelectionList = theFeature->selectionList(aBaseObjectsID); + if(!aBaseObjectsSelectionList.get()) { + theError = "Error: Could not get \"%1\" attribute."; + theError.arg(aBaseObjectsID); + return false; + } + + AttributeSelectionListPtr aLocationsSelectionList = theFeature->selectionList(aLocationsID); + if(!aLocationsSelectionList.get()) { + theError = "Error: Could not get \"%1\" attribute."; + theError.arg(aBaseObjectsID); + return false; + } + + if(aLocationsSelectionList->size() > 0 && aLocationsSelectionList->size() != aBaseObjectsSelectionList->size()) { + theError = "Error: Number of locations should be the same as base objects."; + return false; + } + + return true; +} + +//================================================================================================== +bool FeaturesPlugin_ValidatorPipeLocations::isNotObligatory(std::string theFeature, std::string theAttribute) +{ + return false; +} + +//================================================================================================== +bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + if(theArguments.empty()) { + theError = "Error: Validator parameters is empty."; + return false; + } + + // Checking attribute. + if(!isValidAttribute(theAttribute, theArguments, theError)) { + if(theError.empty()) { + theError = "Error: Attribute contains unacceptable shape."; + } + return false; + } + + std::set aSelectedSketches; + std::set aSelectedSketchesFromObjects; + GeomAPI_DataMapOfShapeShape aSelectedWiresFromObjects; + std::string anAttributeType = theAttribute->attributeType(); + if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) { + AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast(theAttribute); + for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) { + AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex); + ResultPtr aContext = aSelectionAttr->context(); + if(!aContext.get()) { + theError = "Error: Empty context."; + return false; + } + + ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast(aContext); + if(!aResultConstruction.get()) { + // It is not a result construction. If shape is compound check that it contains only faces and edges. + GeomShapePtr aShape = aSelectionAttr->value(); + if(!aShape.get()) { + aShape = aContext->shape(); + } + + if(aShape->shapeType() == GeomAPI_Shape::COMPOUND) { + for(GeomAPI_ShapeIterator anIt(aShape); anIt.more(); anIt.next()) { + GeomShapePtr aSubShape = anIt.current(); + if(aSubShape->shapeType() != GeomAPI_Shape::EDGE + && aSubShape->shapeType() != GeomAPI_Shape::FACE) { + theError = "Error: Compound should contain only faces and edges."; + return false; + } + } + } + + continue; + } + + GeomShapePtr aShape = aSelectionAttr->value(); + GeomShapePtr aContextShape = aResultConstruction->shape(); + if(!aShape.get()) { + // Whole sketch selected. + if(aSelectedSketchesFromObjects.find(aResultConstruction) != aSelectedSketchesFromObjects.cend()) { + theError = "Error: Object from this sketch is already selected. Sketch is not allowed for selection."; + return false; + } + + aSelectedSketches.insert(aResultConstruction); + } else { + // Object from sketch selected. + if(aSelectedSketches.find(aResultConstruction) != aSelectedSketches.cend()) { + theError = "Error: Whole sketch with this object is already selected. Don't allow to select this object."; + return false; + } + + for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) { + GeomShapePtr aWire = anExp.current(); + if(aWire->orientation() != GeomAPI_Shape::FORWARD) { + theError = "Error: Wire with wrong orientation selected."; + return false; + } + + if(aSelectedWiresFromObjects.isBound(aWire)) { + theError = "Error: Objects with such wire already selected. Don't allow to select this object."; + return false; + } + + aSelectedWiresFromObjects.bind(aWire, aWire); + aSelectedSketchesFromObjects.insert(aResultConstruction); + } + } + } + } + + return true; +} + +//================================================================================================== +bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + if(!theAttribute.get()) { + theError = "Error: Empty attribute."; + return false; + } + + std::string anAttributeType = theAttribute->attributeType(); + if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) { + AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast(theAttribute); + for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) { + // If at least one attribute is invalid, the result is false. + if(!isValidAttribute(aListAttr->value(anIndex), theArguments, theError)) { + return false; + } + } + } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) { + // Getting context. + AttributeSelectionPtr anAttr = std::dynamic_pointer_cast(theAttribute); + ResultPtr aContext = anAttr->context(); + if(!aContext.get()) { + theError = "Error: Attribute have empty context."; + return false; + } + + GeomShapePtr aShape = anAttr->value(); + GeomShapePtr aContextShape = aContext->shape(); + if(!aShape.get()) { + aShape = aContextShape; + } + if(!aShape.get()) { + theError = "Error: Empty shape selected"; + return false; + } + + ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aContext); + if(aConstruction.get()) { + // Construciotn selected. Check that is is not infinite. + if(aConstruction->isInfinite()) { + theError = "Error: Infinite constructions is not allowed as base."; + return false; + } + + if(aShape->isEqual(aContextShape)) { + // Whole construction selected. Check that it have faces. + if(aConstruction->facesNum() > 0) { + return true; + } + } else { + // Shape on construction selected. Check that it is a face or wire. + if(aShape->shapeType() == GeomAPI_Shape::WIRE || aShape->shapeType() == GeomAPI_Shape::FACE) { + return true; + } + } + + return false; + } + + if(!aShape->isEqual(aContextShape)) { + // Local selection on body does not allowed. + theError = "Error: Selected shape is in the local selection. Only global selection is allowed."; + return false; + } + + // Check that object is a shape with allowed type. + GeomValidators_ShapeType aShapeTypeValidator; + if(!aShapeTypeValidator.isValid(anAttr, theArguments, theError)) { + theError = "Error: Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, whole sketch(if it has at least one face), and whole objects with shape types: %1"; + std::string anArgumentString; + for(auto anIt = theArguments.cbegin(); anIt != theArguments.cend(); ++anIt) { + if (!anArgumentString.empty()) + anArgumentString += ", "; + anArgumentString += *anIt; + } + theError.arg(anArgumentString); + return false; + } + + } else { + theError = "Error: Attribute \"%1\" does not supported by this validator."; + theError.arg(anAttributeType); + return false; + } + + return true; +} + +//================================================================================================== +bool FeaturesPlugin_ValidatorCompositeLauncher::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) { + theError = "Error: The attribute with the %1 type is not processed"; + theError.arg(theAttribute->attributeType()); + return false; + } + if (theArguments.size() != 2) { + theError = "Error: Wrong parameters in XML definition for %1 type"; + theError.arg(theAttribute->attributeType()); + return false; + } + // first argument is for the base attribute, second - for skipping feature kind + std::list::const_iterator anIt = theArguments.begin(); + std::string aBaseAttributeId = *anIt; + FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner()); + AttributePtr aBaseAttribute = aFeature->attribute(aBaseAttributeId); + if (!aBaseAttribute.get()) { + theError = "Wrong parameters in XML definition for %1 type"; + theError.arg(theAttribute->attributeType()); + return false; + } + if (aBaseAttribute->isInitialized()) // when base list of composite feature is already filled, + // this validator is not necessary anymore + return true; + + anIt++; + std::string aFeatureAttributeKind = *anIt; + GeomValidators_FeatureKind* aValidator = new GeomValidators_FeatureKind(); + // check whether the selection is on the sketch + std::list anArguments; + anArguments.push_back(aFeatureAttributeKind); + + bool aFeatureKind = aValidator->isValid(theAttribute, theArguments, theError); + bool aPlanarFace = false; + // check if selection has Face selected + GeomValidators_ShapeType* aShapeType = new GeomValidators_ShapeType(); + anArguments.clear(); + anArguments.push_back("face"); + aPlanarFace = aShapeType->isValid(theAttribute, anArguments, theError); + + bool aValid = !aFeatureKind && aPlanarFace; + return aValid; +} + +//================================================================================================== +bool FeaturesPlugin_ValidatorExtrusionDir::isValid(const std::shared_ptr& theFeature, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + if(theArguments.size() != 2) { + theError = "Error: Validator should be used with 2 parameters for extrusion."; + return false; + } + + std::list::const_iterator anArgsIt = theArguments.begin(), aLast = theArguments.end(); + + AttributePtr aCheckAttribute = theFeature->attribute(*anArgsIt); + ++anArgsIt; + + GeomShapePtr aDirShape; + AttributeSelectionPtr aSelAttr = theFeature->selection(*anArgsIt); + if(aSelAttr.get()) { + aDirShape = aSelAttr->value(); + if(!aDirShape.get()) { + ResultPtr aContext = aSelAttr->context(); + if(aContext.get()) { + aDirShape = aContext->shape(); + } + } + } + + if(!aDirShape.get()) { + // Check that dir can be empty. + if(!isShapesCanBeEmpty(aCheckAttribute, theError)) { + theError = "Error: Base objects list contains vertex or edge, so attribute \"%1\" can not be used with default value. Select direction for extrusion."; + theError.arg(*anArgsIt); + return false; + } else { + return true; + } + } + + std::shared_ptr aDirEdge(new GeomAPI_Edge(aDirShape)); + + // If faces selected check that direction not parallel with them. + AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast(aCheckAttribute); + for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) { + AttributeSelectionPtr anAttr = aListAttr->value(anIndex); + GeomShapePtr aShapeInList = anAttr->value(); + if(!aShapeInList.get()) { + aShapeInList = anAttr->context()->shape(); + } + bool isParallel = true; + if(aShapeInList->shapeType() == GeomAPI_Shape::FACE || aShapeInList->shapeType() == GeomAPI_Shape::SHELL) { + for(GeomAPI_ShapeExplorer anExp(aShapeInList, GeomAPI_Shape::FACE); anExp.more(); anExp.next()) { + std::shared_ptr aFace(new GeomAPI_Face(anExp.current())); + isParallel = GeomAlgoAPI_ShapeTools::isParallel(aDirEdge, aFace); + if(isParallel) { + break; + } + } + } else if(aShapeInList->shapeType() == GeomAPI_Shape::COMPOUND) { + std::shared_ptr aPlanarEdges = std::dynamic_pointer_cast(aShapeInList); + if(aPlanarEdges.get()) { + std::shared_ptr aSketchDir = aPlanarEdges->norm(); + if(aDirEdge->isLine()) { + std::shared_ptr aDir = aDirEdge->line()->direction(); + isParallel = fabs(aSketchDir->angle(aDir) - M_PI / 2.0) < 10e-7; + } else { + isParallel = false; + } + } else { + isParallel = false; + } + } else { + isParallel = false; + } + if(isParallel) { + theError = "Error: Direction is parallel to one of the selected face or face on selected shell."; + return false; + } + } + + return true; +} + +//================================================================================================== +bool FeaturesPlugin_ValidatorExtrusionDir::isNotObligatory(std::string theFeature, std::string theAttribute) +{ + return false; +} + +//================================================================================================== +bool FeaturesPlugin_ValidatorExtrusionDir::isShapesCanBeEmpty(const AttributePtr& theAttribute, + Events_InfoMessage& theError) const +{ + if(!theAttribute.get()) { + return true; + } + + std::string anAttributeType = theAttribute->attributeType(); + if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) { + AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast(theAttribute); + for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) { + // If at least one attribute is invalid, the result is false. + if(!isShapesCanBeEmpty(aListAttr->value(anIndex), theError)) { + return false; + } + } + } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) { + // Getting context. + AttributeSelectionPtr anAttr = std::dynamic_pointer_cast(theAttribute); + ResultPtr aContext = anAttr->context(); + if(!aContext.get()) { + return false; + } + + GeomShapePtr aShape = anAttr->value(); + GeomShapePtr aContextShape = aContext->shape(); + if(!aShape.get()) { + aShape = aContextShape; + } + if(!aShape.get()) { + return false; + } + + if(aShape->shapeType() == GeomAPI_Shape::VERTEX || + aShape->shapeType() == GeomAPI_Shape::EDGE || + !aShape->isPlanar()) { + return false; + } + } else { + return false; + } + + return true; +} + +//================================================================================================== +bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + AttributeSelectionListPtr anAttrSelectionList = std::dynamic_pointer_cast(theAttribute); + if(!anAttrSelectionList.get()) { + theError = "Error: This validator can only work with selection list attributes in \"Boolean\" feature."; + return false; + } + FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); + int anOperationType = aFeature->integer("bool_type")->value(); + + for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) { + AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex); + if(!anAttrSelection.get()) { + theError = "Error: Empty attribute selection."; + return false; + } + ResultPtr aContext = anAttrSelection->context(); + if(!aContext.get()) { + theError = "Error: Empty selection context."; + return false; + } + ResultConstructionPtr aResultConstruction = + std::dynamic_pointer_cast(aContext); + if(aResultConstruction.get()) { + theError = "Error: Result construction not allowed for selection."; + return false; + } + std::shared_ptr aShape = anAttrSelection->value(); + GeomShapePtr aContextShape = aContext->shape(); + if(!aShape.get()) { + aShape = aContextShape; + } + if(!aShape.get()) { + theError = "Error: Empty shape."; + return false; + } + if(!aShape->isEqual(aContextShape)) { + theError = "Error: Local selection not allowed."; + return false; + } + + int aShapeType = aShape->shapeType(); + if(anOperationType == 1) { + // Fuse operation. Allow to select edges, faces and solids. + if(aShapeType != GeomAPI_Shape::EDGE && + aShapeType != GeomAPI_Shape::FACE && + aShapeType != GeomAPI_Shape::SOLID && + aShapeType != GeomAPI_Shape::COMPSOLID && + aShapeType != GeomAPI_Shape::COMPOUND) { + theError = "Error: Selected shape has the wrong type."; + return false; + } + } else { + if(aShapeType != GeomAPI_Shape::SOLID && + aShapeType != GeomAPI_Shape::COMPSOLID && + aShapeType != GeomAPI_Shape::COMPOUND) { + theError = "Error: Selected shape has the wrong type."; + return false; + } + } + } + + return true; +} + +//================================================================================================== +bool FeaturesPlugin_ValidatorPartitionSelection::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + AttributeSelectionListPtr anAttrSelectionList = std::dynamic_pointer_cast(theAttribute); + if(!anAttrSelectionList.get()) { + theError = "Error: This validator can only work with selection list in \"Partition\" feature."; + return false; + } + + for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) { + AttributeSelectionPtr aSelectAttr = anAttrSelectionList->value(anIndex); + + //GeomValidators_BodyShapes aBodyValidator; + //if(aBodyValidator.isValid(aSelectAttr, theArguments, theError)) { + // continue; + //} + + GeomValidators_FeatureKind aFeatureKindValidator; + if(aFeatureKindValidator.isValid(aSelectAttr, theArguments, theError)) { + continue; + } + + ResultPtr aContext = aSelectAttr->context(); + ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast(aContext); + if(aResultConstruction.get()) { + theError = "Error: Only body shapes and construction planes are allowed for selection."; + return false; + } + + ResultCompSolidPtr aResultCompsolid = std::dynamic_pointer_cast(aContext); + if(aResultCompsolid.get()) { + continue; + } + + theError = "Error: Only body shapes and construction planes are allowed for selection."; + return false; + } + + theError = ""; + return true; +} + +//================================================================================================== +bool FeaturesPlugin_ValidatorRemoveSubShapesSelection::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + AttributeSelectionListPtr aSubShapesAttrList = std::dynamic_pointer_cast(theAttribute); + if(!aSubShapesAttrList.get()) { + theError = "Error: This validator can only work with selection list in \"Remove Sub-Shapes\" feature."; + return false; + } + + static const std::string aBaseShapeID = "base_shape"; + FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); + AttributeSelectionPtr aShapeAttrSelection = aFeature->selection(aBaseShapeID); + + if(!aShapeAttrSelection.get()) { + theError = "Error: Could not get \"%1\" attribute."; + theError.arg(aBaseShapeID); + return false; + } + + GeomShapePtr aBaseShape = aShapeAttrSelection->value(); + ResultPtr aContext = aShapeAttrSelection->context(); + if(!aContext.get()) { + theError = "Error: Empty context."; + return false; + } + if(!aBaseShape.get()) { + aBaseShape = aContext->shape(); + } + if(!aBaseShape.get()) { + theError = "Error: Empty base shape."; + return false; + } + + for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) { + bool isSameFound = false; + AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex); + GeomShapePtr aShapeToAdd = anAttrSelectionInList->value(); + for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) { + if(anIt.current()->isEqual(aShapeToAdd)) { + isSameFound = true; + break; + } + } + if(!isSameFound) { + theError = "Error: Only sub-shapes of selected shape is allowed for selection."; + return false; + } + } + + return true; +} + +//================================================================================================== +bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isValid(const std::shared_ptr& theFeature, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + static const std::string aBaseShapeID = "base_shape"; + static const std::string aSubShapesID = "subshapes"; + + if(theFeature->getKind() != "Remove_SubShapes") { + theError = "Error: Feature \"%1\" does not supported by this validator."; + theError.arg(theFeature->getKind()); + return false; + } + + AttributeSelectionPtr aShapeAttrSelection = theFeature->selection(aBaseShapeID); + if(!aShapeAttrSelection.get()) { + theError = "Error: Could not get \"%1\" attribute."; + theError.arg(aBaseShapeID); + return false; + } + + AttributeSelectionListPtr aSubShapesAttrList = theFeature->selectionList(aSubShapesID); + if(!aSubShapesAttrList.get()) { + theError = "Error: Could not get \"%1\" attribute."; + theError.arg(aSubShapesID); + return false; + } + + // Copy base shape. + GeomShapePtr aBaseShape = aShapeAttrSelection->value(); + if(!aBaseShape.get()) { + theError = "Error: Base shape is empty."; + return false; + } + GeomShapePtr aResultShape = aBaseShape->emptyCopied(); + + // Copy sub-shapes from list to new shape. + for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) { + AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex); + GeomShapePtr aShapeToAdd = anAttrSelectionInList->value(); + GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd); + } + + // Check new shape. + if(!GeomAlgoAPI_ShapeTools::isShapeValid(aResultShape)) { + theError = "Error: Resulting shape is not valid."; + return false; + } + + return true; +} + +//================================================================================================== +bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isNotObligatory(std::string theFeature, + std::string theAttribute) +{ + return false; +} + +//================================================================================================== +bool FeaturesPlugin_ValidatorUnionSelection::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + AttributeSelectionListPtr aBaseObjectsAttrList = std::dynamic_pointer_cast(theAttribute); + if(!aBaseObjectsAttrList.get()) { + theError = "Error: This validator can only work with selection list in \"%1\" feature."; + theError.arg(FeaturesPlugin_Union::ID()); + return false; + } + + for(int anIndex = 0; anIndex < aBaseObjectsAttrList->size(); ++anIndex) { + bool isSameFound = false; + AttributeSelectionPtr anAttrSelectionInList = aBaseObjectsAttrList->value(anIndex); + ResultCompSolidPtr aResult = std::dynamic_pointer_cast(anAttrSelectionInList->context()); + if(!aResult.get()) { + continue; + } + if(aResult->numberOfSubs() > 0) { + theError = "Error: Whole compsolids not allowed for selection."; + return false; + } + } + + return true; +} + +//================================================================================================== +bool FeaturesPlugin_ValidatorUnionArguments::isValid(const std::shared_ptr& theFeature, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + // Check feature kind. + if(theFeature->getKind() != FeaturesPlugin_Union::ID()) { + theError = "Error: This validator supports only \"%1\" feature."; + theError.arg(FeaturesPlugin_Union::ID()); + return false; + } + + // Get base objects attribute list. + AttributeSelectionListPtr aBaseObejctsAttrList = theFeature->selectionList(FeaturesPlugin_Union::BASE_OBJECTS_ID()); + if(!aBaseObejctsAttrList.get()) { + theError = "Error: Could not get \"%1\" attribute."; + theError.arg(FeaturesPlugin_Union::BASE_OBJECTS_ID()); + return false; + } + + // Get all shapes. + ListOfShape aBaseShapesList; + for(int anIndex = 0; anIndex < aBaseObejctsAttrList->size(); ++anIndex) { + AttributeSelectionPtr anAttrSelectionInList = aBaseObejctsAttrList->value(anIndex); + GeomShapePtr aShape = anAttrSelectionInList->value(); + aBaseShapesList.push_back(aShape); + } + + // Make componud and find connected. + GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseShapesList); + ListOfShape aCombined, aFree; + GeomAlgoAPI_ShapeTools::combineShapes(aCompound, GeomAPI_Shape::COMPSOLID, aCombined, aFree); + + if(aFree.size() > 0 || aCombined.size() > 1) { + theError = "Error: Not all shapes have shared topology."; + return false; + } + + return true; +} + +//================================================================================================== +bool FeaturesPlugin_ValidatorUnionArguments::isNotObligatory(std::string theFeature, + std::string theAttribute) +{ + return false; +} + +bool FeaturesPlugin_ValidatorConcealedResult::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) { + theError = "Error: The attribute with the %1 type is not processed"; + theError.arg(theAttribute->attributeType()); + return false; + } + + AttributeReferencePtr aRefAttribute = std::dynamic_pointer_cast + (theAttribute); + ObjectPtr aRefObject = aRefAttribute->value(); + if (!aRefObject.get()) { + theError = "Error: Empty feature."; + return false; + } + + FeaturePtr aRefFeature = std::dynamic_pointer_cast(aRefObject); + if (!aRefFeature.get()) { + theError = "Error: Empty feature."; + return false; + } + std::list > aResults; + ModelAPI_Tools::getConcealedResults(aRefFeature, aResults); + + size_t aConcealedResults = aResults.size(); + if (!aConcealedResults && !theArguments.empty()) { + // find if these results are touched by the feature in another attribute + std::list::const_iterator anIt = theArguments.begin(); + std::string aRecoveredList = *anIt; + if (!aRecoveredList.empty()) { + std::shared_ptr aParameterList = + theAttribute->owner()->data()->reflist(aRecoveredList); + if (aParameterList.get()) + aConcealedResults = aParameterList->size(); + } + } + + if (aConcealedResults == 0) + theError = "Error: No concealed results."; + + return theError.empty(); +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.h b/src/FeaturesPlugin/FeaturesPlugin_Validators.h index 223519b77..d01605463 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.h @@ -1,220 +1,220 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> - -// File: FeaturesPlugin_Validators.h -// Created: 22 March 2016 -// Author: Dmitry Bobylev - -#ifndef FeaturesPlugin_Validators_H_ -#define FeaturesPlugin_Validators_H_ - -#include -#include - -/// \class FeaturesPlugin_ValidatorPipePath -/// \ingroup Validators -/// \brief A validator for selection pipe path. -class FeaturesPlugin_ValidatorPipePath: public ModelAPI_AttributeValidator -{ -public: - //! \return True if the attribute is valid. - //! \param[in] theAttribute the checked attribute. - //! \param[in] theArguments arguments of the attribute. - //! \param[out] theError error message. - virtual bool isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - Events_InfoMessage& theError) const; -}; - -/// \class FeaturesPlugin_ValidatorPipeLocations -/// \ingroup Validators -/// \brief Validator for the pipe locations. -class FeaturesPlugin_ValidatorPipeLocations: public ModelAPI_FeatureValidator -{ - public: - //! \return true if number of selected locations the same as number of selected bases, or empty. - //! \param theFeature the checked feature - //! \param theArguments arguments of the feature (not used) - //! \param theError error message - virtual bool isValid(const std::shared_ptr& theFeature, - const std::list& theArguments, - Events_InfoMessage& theError) const; - - /// Returns true if the attribute in feature is not obligatory for the feature execution - virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); -}; - -/// \class FeaturesPlugin_ValidatorBaseForGeneration -/// \ingroup Validators -/// \brief A validator for selection base for generation. Allows to select faces on sketch, -/// whole sketch(if it has at least one face), and following objects: vertex, edge, wire, face. -class FeaturesPlugin_ValidatorBaseForGeneration: public ModelAPI_AttributeValidator -{ -public: - //! \return true if attribute has selection type listed in the parameter arguments. - //! \param[in] theAttribute the checked attribute. - //! \param[in] theArguments arguments of the attribute. - //! \param[out] theError error message. - virtual bool isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - Events_InfoMessage& theError) const; - -private: - bool isValidAttribute(const AttributePtr& theAttribute, - const std::list& theArguments, - Events_InfoMessage& theError) const; -}; - -/// \class FeaturesPlugin_ValidatorCompositeLauncher -/// \ingroup Validators -/// \brief A validator for selection at composite feature start -class FeaturesPlugin_ValidatorCompositeLauncher: public ModelAPI_AttributeValidator -{ -public: - //! \return true if attribute has selection type listed in the parameter arguments. - //! \param[in] theAttribute the checked attribute. - //! \param[in] theArguments arguments of the attribute. - //! \param[out] theError error message. - virtual bool isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - Events_InfoMessage& theError) const; -}; - -/// \class FeaturesPlugin_ValidatorExtrusionDir -/// \ingroup Validators -/// \brief A validator for extrusion direction attribute. Allows it to be empty if base objects are -/// planar and do not contain vertices and edges. -class FeaturesPlugin_ValidatorExtrusionDir: public ModelAPI_FeatureValidator -{ -public: - //! \return true if attribute listed in the parameter arguments are planar. - //! \param[in] theFeature the checked feature. - //! \param[in] theArguments arguments of the attribute. - //! \param[out] theError error message. - virtual bool isValid(const std::shared_ptr& theFeature, - const std::list& theArguments, - Events_InfoMessage& theError) const; - - /// \return true if the attribute in feature is not obligatory for the feature execution - virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); - -private: - bool isShapesCanBeEmpty(const AttributePtr& theAttribute, - Events_InfoMessage& theError) const; -}; - -/// \class FeaturesPlugin_ValidatorBooleanSelection -/// \ingroup Validators -/// \brief Validates selection for boolean operation. -class FeaturesPlugin_ValidatorBooleanSelection: public ModelAPI_AttributeValidator -{ -public: - /// \return True if the attribute is valid. It checks whether the selection - /// is acceptable for boolean operation. - /// \param[in] theAttribute an attribute to check. - /// \param[in] theArguments a filter parameters. - /// \param[out] theError error message. - virtual bool isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - Events_InfoMessage& theError) const; -}; - -/// \class FeaturesPlugin_ValidatorPartitionSelection -/// \ingroup Validators -/// \brief Validates selection for partition. -class FeaturesPlugin_ValidatorPartitionSelection: public ModelAPI_AttributeValidator -{ -public: - /// \return True if the attribute is valid. It checks whether the selection - /// is acceptable for operation. - /// \param[in] theAttribute an attribute to check. - /// \param[in] theArguments a filter parameters. - /// \param[out] theError error message. - virtual bool isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - Events_InfoMessage& theError) const; -}; - -/// \class FeaturesPlugin_ValidatorRemoveSubShapesSelection -/// \ingroup Validators -/// \brief Validates selection for "Remove Sub-Shapes" feature. -class FeaturesPlugin_ValidatorRemoveSubShapesSelection: public ModelAPI_AttributeValidator -{ -public: - /// \return True if the attribute is valid. It checks whether the selection - /// is acceptable for operation. - /// \param[in] theAttribute an attribute to check. - /// \param[in] theArguments a filter parameters. - /// \param[out] theError error message. - virtual bool isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - Events_InfoMessage& theError) const; -}; - -/// \class FeaturesPlugin_ValidatorRemoveSubShapesResult -/// \ingroup Validators -/// \brief Validator for the Remove Sub-Shapes feature. -class FeaturesPlugin_ValidatorRemoveSubShapesResult: public ModelAPI_FeatureValidator -{ - public: - //! \return true if result is valid shape. - //! \param theFeature the checked feature - //! \param theArguments arguments of the feature (not used) - //! \param theError error message - virtual bool isValid(const std::shared_ptr& theFeature, - const std::list& theArguments, - Events_InfoMessage& theError) const; - - /// \return true if the attribute in feature is not obligatory for the feature execution - virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); -}; - -/// \class FeaturesPlugin_ValidatorUnionSelection -/// \ingroup Validators -/// \brief Validates selection for "Union" feature. -class FeaturesPlugin_ValidatorUnionSelection: public ModelAPI_AttributeValidator -{ -public: - /// \return True if the attribute is valid. It checks whether the selection - /// is acceptable for operation. - /// \param[in] theAttribute an attribute to check. - /// \param[in] theArguments a filter parameters. - /// \param[out] theError error message. - virtual bool isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - Events_InfoMessage& theError) const; -}; - -/// \class FeaturesPlugin_ValidatorUnionArguments -/// \ingroup Validators -/// \brief Validator for the "Union" feature. -class FeaturesPlugin_ValidatorUnionArguments: public ModelAPI_FeatureValidator -{ - public: - //! \return true if result is valid shape. - //! \param theFeature the checked feature - //! \param theArguments arguments of the feature (not used) - //! \param theError error message - virtual bool isValid(const std::shared_ptr& theFeature, - const std::list& theArguments, - Events_InfoMessage& theError) const; - - /// \return true if the attribute in feature is not obligatory for the feature execution - virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); -}; - -/// \class FeaturesPlugin_ValidatorConcealedResult -/// \ingroup Validators -/// \brief Validator for the "Recover" feature. -class FeaturesPlugin_ValidatorConcealedResult: public ModelAPI_AttributeValidator -{ - public: - //! \return True if the attribute is valid. - //! \param[in] theAttribute the checked attribute. - //! \param[in] theArguments arguments of the attribute. - //! \param[out] theError error message. - virtual bool isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - Events_InfoMessage& theError) const; -}; - -#endif +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: FeaturesPlugin_Validators.h +// Created: 22 March 2016 +// Author: Dmitry Bobylev + +#ifndef FeaturesPlugin_Validators_H_ +#define FeaturesPlugin_Validators_H_ + +#include +#include + +/// \class FeaturesPlugin_ValidatorPipePath +/// \ingroup Validators +/// \brief A validator for selection pipe path. +class FeaturesPlugin_ValidatorPipePath: public ModelAPI_AttributeValidator +{ +public: + //! \return True if the attribute is valid. + //! \param[in] theAttribute the checked attribute. + //! \param[in] theArguments arguments of the attribute. + //! \param[out] theError error message. + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const; +}; + +/// \class FeaturesPlugin_ValidatorPipeLocations +/// \ingroup Validators +/// \brief Validator for the pipe locations. +class FeaturesPlugin_ValidatorPipeLocations: public ModelAPI_FeatureValidator +{ + public: + //! \return true if number of selected locations the same as number of selected bases, or empty. + //! \param theFeature the checked feature + //! \param theArguments arguments of the feature (not used) + //! \param theError error message + virtual bool isValid(const std::shared_ptr& theFeature, + const std::list& theArguments, + Events_InfoMessage& theError) const; + + /// Returns true if the attribute in feature is not obligatory for the feature execution + virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); +}; + +/// \class FeaturesPlugin_ValidatorBaseForGeneration +/// \ingroup Validators +/// \brief A validator for selection base for generation. Allows to select faces on sketch, +/// whole sketch(if it has at least one face), and following objects: vertex, edge, wire, face. +class FeaturesPlugin_ValidatorBaseForGeneration: public ModelAPI_AttributeValidator +{ +public: + //! \return true if attribute has selection type listed in the parameter arguments. + //! \param[in] theAttribute the checked attribute. + //! \param[in] theArguments arguments of the attribute. + //! \param[out] theError error message. + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const; + +private: + bool isValidAttribute(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const; +}; + +/// \class FeaturesPlugin_ValidatorCompositeLauncher +/// \ingroup Validators +/// \brief A validator for selection at composite feature start +class FeaturesPlugin_ValidatorCompositeLauncher: public ModelAPI_AttributeValidator +{ +public: + //! \return true if attribute has selection type listed in the parameter arguments. + //! \param[in] theAttribute the checked attribute. + //! \param[in] theArguments arguments of the attribute. + //! \param[out] theError error message. + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const; +}; + +/// \class FeaturesPlugin_ValidatorExtrusionDir +/// \ingroup Validators +/// \brief A validator for extrusion direction attribute. Allows it to be empty if base objects are +/// planar and do not contain vertices and edges. +class FeaturesPlugin_ValidatorExtrusionDir: public ModelAPI_FeatureValidator +{ +public: + //! \return true if attribute listed in the parameter arguments are planar. + //! \param[in] theFeature the checked feature. + //! \param[in] theArguments arguments of the attribute. + //! \param[out] theError error message. + virtual bool isValid(const std::shared_ptr& theFeature, + const std::list& theArguments, + Events_InfoMessage& theError) const; + + /// \return true if the attribute in feature is not obligatory for the feature execution + virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); + +private: + bool isShapesCanBeEmpty(const AttributePtr& theAttribute, + Events_InfoMessage& theError) const; +}; + +/// \class FeaturesPlugin_ValidatorBooleanSelection +/// \ingroup Validators +/// \brief Validates selection for boolean operation. +class FeaturesPlugin_ValidatorBooleanSelection: public ModelAPI_AttributeValidator +{ +public: + /// \return True if the attribute is valid. It checks whether the selection + /// is acceptable for boolean operation. + /// \param[in] theAttribute an attribute to check. + /// \param[in] theArguments a filter parameters. + /// \param[out] theError error message. + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const; +}; + +/// \class FeaturesPlugin_ValidatorPartitionSelection +/// \ingroup Validators +/// \brief Validates selection for partition. +class FeaturesPlugin_ValidatorPartitionSelection: public ModelAPI_AttributeValidator +{ +public: + /// \return True if the attribute is valid. It checks whether the selection + /// is acceptable for operation. + /// \param[in] theAttribute an attribute to check. + /// \param[in] theArguments a filter parameters. + /// \param[out] theError error message. + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const; +}; + +/// \class FeaturesPlugin_ValidatorRemoveSubShapesSelection +/// \ingroup Validators +/// \brief Validates selection for "Remove Sub-Shapes" feature. +class FeaturesPlugin_ValidatorRemoveSubShapesSelection: public ModelAPI_AttributeValidator +{ +public: + /// \return True if the attribute is valid. It checks whether the selection + /// is acceptable for operation. + /// \param[in] theAttribute an attribute to check. + /// \param[in] theArguments a filter parameters. + /// \param[out] theError error message. + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const; +}; + +/// \class FeaturesPlugin_ValidatorRemoveSubShapesResult +/// \ingroup Validators +/// \brief Validator for the Remove Sub-Shapes feature. +class FeaturesPlugin_ValidatorRemoveSubShapesResult: public ModelAPI_FeatureValidator +{ + public: + //! \return true if result is valid shape. + //! \param theFeature the checked feature + //! \param theArguments arguments of the feature (not used) + //! \param theError error message + virtual bool isValid(const std::shared_ptr& theFeature, + const std::list& theArguments, + Events_InfoMessage& theError) const; + + /// \return true if the attribute in feature is not obligatory for the feature execution + virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); +}; + +/// \class FeaturesPlugin_ValidatorUnionSelection +/// \ingroup Validators +/// \brief Validates selection for "Union" feature. +class FeaturesPlugin_ValidatorUnionSelection: public ModelAPI_AttributeValidator +{ +public: + /// \return True if the attribute is valid. It checks whether the selection + /// is acceptable for operation. + /// \param[in] theAttribute an attribute to check. + /// \param[in] theArguments a filter parameters. + /// \param[out] theError error message. + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const; +}; + +/// \class FeaturesPlugin_ValidatorUnionArguments +/// \ingroup Validators +/// \brief Validator for the "Union" feature. +class FeaturesPlugin_ValidatorUnionArguments: public ModelAPI_FeatureValidator +{ + public: + //! \return true if result is valid shape. + //! \param theFeature the checked feature + //! \param theArguments arguments of the feature (not used) + //! \param theError error message + virtual bool isValid(const std::shared_ptr& theFeature, + const std::list& theArguments, + Events_InfoMessage& theError) const; + + /// \return true if the attribute in feature is not obligatory for the feature execution + virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); +}; + +/// \class FeaturesPlugin_ValidatorConcealedResult +/// \ingroup Validators +/// \brief Validator for the "Recover" feature. +class FeaturesPlugin_ValidatorConcealedResult: public ModelAPI_AttributeValidator +{ + public: + //! \return True if the attribute is valid. + //! \param[in] theAttribute the checked attribute. + //! \param[in] theArguments arguments of the attribute. + //! \param[out] theError error message. + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const; +}; + +#endif diff --git a/src/ModelAPI/ModelAPI_Tools.cpp b/src/ModelAPI/ModelAPI_Tools.cpp index 36fd94b66..ee9de24e1 100755 --- a/src/ModelAPI/ModelAPI_Tools.cpp +++ b/src/ModelAPI/ModelAPI_Tools.cpp @@ -1,586 +1,586 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: ModelAPI_Tools.cpp -// Created: 06 Aug 2014 -// Author: Vitaly Smetannikov - -#include "ModelAPI_Tools.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define RECURSE_TOP_LEVEL 50 - -//#define DEBUG_REMOVE_FEATURES -//#define DEBUG_REMOVE_FEATURES_RECURSE -//#define DEBUG_CYCLING_1550 - -#ifdef DEBUG_REMOVE_FEATURES_RECURSE -#include -std::string getFeatureInfo(FeaturePtr theFeature) -{ - if (!theFeature.get()) - return ""; - //std::ostringstream aPtrStr; - //aPtrStr << "[" << theFeature.get() << "] "; - std::string aFeatureInfo = /*aPtrStr.str() + */theFeature->name(); - CompositeFeaturePtr aComposite = ModelAPI_Tools::compositeOwner(theFeature); - if (aComposite.get()) { - aFeatureInfo = aFeatureInfo + "[in " + aComposite->name() + "]"; - } - return aFeatureInfo; -} -#endif - -#ifdef DEBUG_REMOVE_FEATURES -void printMapInfo(const std::map >& theMainList, - const std::string& thePrefix) -{ - std::map >::const_iterator aMainIt = theMainList.begin(), - aMainLast = theMainList.end(); - std::string anInfo; - for (; aMainIt != aMainLast; aMainIt++) { - FeaturePtr aMainListFeature = aMainIt->first; - std::set aMainRefList = aMainIt->second; - std::set::const_iterator anIt = aMainRefList.begin(), aLast = aMainRefList.end(); - std::string aRefsInfo; - for (; anIt != aLast; anIt++) { - aRefsInfo += (*anIt)->name().c_str(); - if (anIt != aLast) - aRefsInfo += ", "; - } - if (!aRefsInfo.empty()) { - anInfo = anInfo + aMainListFeature->name().c_str() + ": " + aRefsInfo + "\n"; - } - } - std::cout << thePrefix.c_str() << " [feature: references to]: \n" << anInfo.c_str() << std::endl; -} - -void printListInfo(const std::set& theMainList, - const std::string& thePrefix) -{ - std::set::const_iterator aMainIt = theMainList.begin(), - aMainLast = theMainList.end(); - std::string anInfo; - for (; aMainIt != aMainLast; aMainIt++) { - FeaturePtr aRefFeature = *aMainIt; - anInfo += aRefFeature->name().c_str(); - if (aMainIt != aMainLast) - anInfo += ", "; - } - std::cout << thePrefix.c_str() << ": " << anInfo.c_str() << std::endl; -} -#endif - -namespace ModelAPI_Tools { - -std::shared_ptr shape(const ResultPtr& theResult) -{ - return theResult->shape(); -} - -void shapesOfType(const FeaturePtr& theFeature, - const GeomAPI_Shape::ShapeType& theType, - std::set& theShapes) -{ - std::list aResults = theFeature->results(); - std::list::const_iterator aRIter = aResults.cbegin(); - for (; aRIter != aResults.cend(); aRIter++) { - ResultPtr aResult = *aRIter; - GeomShapePtr aShape = aResult->shape(); - if (aShape.get() && aShape->shapeType() == theType) - theShapes.insert(aShape); - } -} - -const char* toString(ModelAPI_ExecState theExecState) -{ -#define TO_STRING(__NAME__) case __NAME__: return #__NAME__; - switch (theExecState) { - TO_STRING(ModelAPI_StateDone) - TO_STRING(ModelAPI_StateMustBeUpdated) - TO_STRING(ModelAPI_StateExecFailed) - TO_STRING(ModelAPI_StateInvalidArgument) - TO_STRING(ModelAPI_StateNothing) - default: return "Unknown ExecState."; - } -#undef TO_STRING -} - -std::string getFeatureError(const FeaturePtr& theFeature) -{ - std::string anError; - if (!theFeature.get() || !theFeature->data()->isValid() || theFeature->isAction()) - return anError; - - // to be removed later, this error should be got from the feature - if (theFeature->data()->execState() == ModelAPI_StateDone || - theFeature->data()->execState() == ModelAPI_StateMustBeUpdated) - return anError; - - // set error indication - anError = theFeature->error(); - if (anError.empty()) { - bool isDone = ( theFeature->data()->execState() == ModelAPI_StateDone - || theFeature->data()->execState() == ModelAPI_StateMustBeUpdated ); - if (!isDone) { - anError = toString(theFeature->data()->execState()); - // If the feature is Composite and error is StateInvalidArgument, - // error text should include error of first invalid sub-feature. Otherwise - // it is not clear what is the reason of the invalid argument. - if (theFeature->data()->execState() == ModelAPI_StateInvalidArgument) { - CompositeFeaturePtr aComposite = - std::dynamic_pointer_cast(theFeature); - if (aComposite) { - for (int i = 0, aSize = aComposite->numberOfSubs(); i < aSize; i++) { - FeaturePtr aSubFeature = aComposite->subFeature(i); - std::string aSubFeatureError = getFeatureError(aSubFeature); - if (!aSubFeatureError.empty()) { - anError = anError + " in " + aSubFeature->getKind() + ".\n" + aSubFeatureError; - break; - } - } - } - } - } - } - - return anError; -} - -ObjectPtr objectByName(const DocumentPtr& theDocument, const std::string& theGroup, const std::string& theName) -{ - for (int anIndex = 0; anIndex < theDocument->size(theGroup); ++anIndex) { - ObjectPtr anObject = theDocument->object(theGroup, anIndex); - if (anObject->data()->name() == theName) - return anObject; - } - // not found - return ObjectPtr(); -} - -bool findVariable(const DocumentPtr& theDocument, FeaturePtr theSearcher, - const std::string& theName, double& outValue, ResultParameterPtr& theParam) -{ - ObjectPtr aParamObj = objectByName(theDocument, ModelAPI_ResultParameter::group(), theName); - theParam = std::dynamic_pointer_cast(aParamObj); - if (!theParam.get()) - return false; - // avoid usage of parameters created later than the initial parameter - if (theSearcher.get() && theDocument->isLater(theDocument->feature(theParam), theSearcher)) - return false; - AttributeDoublePtr aValueAttribute = theParam->data()->real(ModelAPI_ResultParameter::VALUE()); - outValue = aValueAttribute->value(); - return true; -} - -bool findVariable(FeaturePtr theSearcher, const std::string& theName, double& outValue, ResultParameterPtr& theParam, - const DocumentPtr& theDocument) -{ - SessionPtr aSession = ModelAPI_Session::get(); - std::list aDocList; - DocumentPtr aDocument = theDocument.get() ? theDocument : aSession->activeDocument(); - if (findVariable(aDocument, theSearcher, theName, outValue, theParam)) - return true; - DocumentPtr aRootDocument = aSession->moduleDocument(); - if (aDocument != aRootDocument) { - // any parameters in PartSet is okindependently on the Part position (issu #1504) - if (findVariable(aRootDocument, FeaturePtr(), theName, outValue, theParam)) - return true; - } - return false; -} - -ResultPtr findPartResult(const DocumentPtr& theMain, const DocumentPtr& theSub) -{ - if (theMain != theSub) { // to optimize and avoid of crash on partset document close (don't touch the sub-document structure) - for (int a = theMain->size(ModelAPI_ResultPart::group()) - 1; a >= 0; a--) { - ResultPartPtr aPart = std::dynamic_pointer_cast( - theMain->object(ModelAPI_ResultPart::group(), a)); - if (aPart && aPart->data()->document(ModelAPI_ResultPart::DOC_REF())->value() == theSub) { - return aPart; - } - } - } - return ResultPtr(); -} - -FeaturePtr findPartFeature(const DocumentPtr& theMain, const DocumentPtr& theSub) -{ - if (theMain != theSub) { // to optimize and avoid of crash on partset document close (don't touch the sub-document structure) - for (int a = theMain->size(ModelAPI_Feature::group()) - 1; a >= 0; a--) { - FeaturePtr aPartFeat = std::dynamic_pointer_cast( - theMain->object(ModelAPI_Feature::group(), a)); - if (aPartFeat.get()) { - const std::list >& aResList = aPartFeat->results(); - std::list >::const_iterator aRes = aResList.begin(); - for(; aRes != aResList.end(); aRes++) { - ResultPartPtr aPart = std::dynamic_pointer_cast(*aRes); - if (aPart.get()) { - if (aPart->isActivated() && aPart->partDoc() == theSub) - return aPartFeat; - } else break; // if the first is not Part, others are also not - } - } - } - } - return FeaturePtr(); -} - -CompositeFeaturePtr compositeOwner(const FeaturePtr& theFeature) -{ - if (theFeature.get() && theFeature->data()->isValid()) { - const std::set >& aRefs = theFeature->data()->refsToMe(); - std::set >::const_iterator aRefIter = aRefs.begin(); - for(; aRefIter != aRefs.end(); aRefIter++) { - CompositeFeaturePtr aComp = std::dynamic_pointer_cast - ((*aRefIter)->owner()); - if (aComp.get() && aComp->data()->isValid() && aComp->isSub(theFeature)) - return aComp; - } - } - return CompositeFeaturePtr(); // not found -} - -ResultCompSolidPtr compSolidOwner(const ResultPtr& theSub) -{ - ResultBodyPtr aBody = std::dynamic_pointer_cast(theSub); - if (aBody.get()) { - FeaturePtr aFeatureOwner = aBody->document()->feature(aBody); - if (aFeatureOwner.get()) { - std::list >::const_iterator aResIter = - aFeatureOwner->results().cbegin(); - for(; aResIter != aFeatureOwner->results().cend(); aResIter++) { - ResultCompSolidPtr aComp = std::dynamic_pointer_cast(*aResIter); - if (aComp && aComp->isSub(aBody)) - return aComp; - } - } - } - return ResultCompSolidPtr(); // not found -} - -bool hasSubResults(const ResultPtr& theResult) -{ - ResultCompSolidPtr aCompSolid = std::dynamic_pointer_cast(theResult); - return aCompSolid.get() && aCompSolid->numberOfSubs() > 0; -} - -void allResults(const FeaturePtr& theFeature, std::list& theResults) -{ - if (!theFeature.get()) // safety: for empty feature no results - return; - const std::list >& aResults = theFeature->results(); - std::list >::const_iterator aRIter = aResults.begin(); - for (; aRIter != aResults.cend(); aRIter++) { - theResults.push_back(*aRIter); - // iterate sub-bodies of compsolid - ResultCompSolidPtr aComp = std::dynamic_pointer_cast(*aRIter); - if (aComp.get()) { - int aNumSub = aComp->numberOfSubs(); - for(int a = 0; a < aNumSub; a++) { - theResults.push_back(aComp->subResult(a)); - } - } - } -} - -//****************************************************************** -bool allDocumentsActivated(std::string& theNotActivatedNames) -{ - theNotActivatedNames = ""; - bool anAllPartActivated = true; - - DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument(); - int aSize = aRootDoc->size(ModelAPI_ResultPart::group()); - for (int i = 0; i < aSize; i++) { - ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), i); - ResultPartPtr aPart = std::dynamic_pointer_cast(aObject); - if (!aPart->isActivated()) { - anAllPartActivated = false; - if (!theNotActivatedNames.empty()) - theNotActivatedNames += ", "; - theNotActivatedNames += aObject->data()->name().c_str(); - } - } - return anAllPartActivated; -} - -bool removeFeaturesAndReferences(const std::set& theFeatures, - const bool theFlushRedisplay, - const bool theUseComposite, - const bool theUseRecursion) -{ -#ifdef DEBUG_REMOVE_FEATURES - printListInfo(theFeatures, "selection: "); -#endif - - std::map > aReferences; - ModelAPI_Tools::findAllReferences(theFeatures, aReferences, theUseComposite, theUseRecursion); -#ifdef DEBUG_REMOVE_FEATURES - printMapInfo(aReferences, "allDependencies: "); -#endif - - std::set aFeaturesRefsTo; - ModelAPI_Tools::findRefsToFeatures(theFeatures, aReferences, aFeaturesRefsTo); -#ifdef DEBUG_REMOVE_FEATURES - printListInfo(aFeaturesRefsTo, "references: "); -#endif - - std::set aFeatures = theFeatures; - if (!aFeaturesRefsTo.empty()) - aFeatures.insert(aFeaturesRefsTo.begin(), aFeaturesRefsTo.end()); -#ifdef DEBUG_REMOVE_FEATURES - printListInfo(aFeatures, "removeFeatures: "); -#endif - - return ModelAPI_Tools::removeFeatures(aFeatures, false); -} - -bool removeFeatures(const std::set& theFeatures, - const bool theFlushRedisplay) -{ - bool isDone = false; - std::set::const_iterator anIt = theFeatures.begin(), - aLast = theFeatures.end(); - for (; anIt != aLast; anIt++) { - FeaturePtr aFeature = *anIt; - if (aFeature.get()) { - DocumentPtr aDoc = aFeature->document(); - // flush REDISPLAY signal after remove feature - aDoc->removeFeature(aFeature); - isDone = true; - } - } - if (isDone && theFlushRedisplay) { - // the redisplay signal should be flushed in order to erase the feature presentation in the viewer - // if should be done after removeFeature() of document - Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)); - } - return true; -} - -// Fills the references list by all references of the feature from the references map. -// This is a recusive method to find references by next found feature in the map of references. -// \param theFeature a feature to find references -// \param theReferencesMap a map of references -// \param theReferences an out container of references -void addRefsToFeature(const FeaturePtr& theFeature, - const std::map >& theReferencesMap, - std::map >& theProcessedReferences, - int theRecLevel, - std::set& theReferences) -{ - if (theRecLevel > RECURSE_TOP_LEVEL) - return; - theRecLevel++; - - // if the feature is already processed, get the ready references from the map - if (theProcessedReferences.find(theFeature) != theProcessedReferences.end()) { - std::set aReferences = theProcessedReferences.at(theFeature); - theReferences.insert(aReferences.begin(), aReferences.end()); - return; - } - - if (theReferencesMap.find(theFeature) == theReferencesMap.end()) - return; // this feature is not in the selection list, so exists without references to it - std::set aMainReferences = theReferencesMap.at(theFeature); - - std::set::const_iterator anIt = aMainReferences.begin(), - aLast = aMainReferences.end(); -#ifdef DEBUG_REMOVE_FEATURES_RECURSE - std::string aSpacing; - for (int i = 0; i < theRecLevel; i++) - aSpacing.append(" "); -#endif - - for (; anIt != aLast; anIt++) { - FeaturePtr aRefFeature = *anIt; -#ifdef DEBUG_REMOVE_FEATURES_RECURSE - std::cout << aSpacing << " Ref: " << getFeatureInfo(aRefFeature) << std::endl; -#endif - if (theReferences.find(aRefFeature) == theReferences.end()) - theReferences.insert(aRefFeature); - addRefsToFeature(aRefFeature, theReferencesMap, theProcessedReferences, theRecLevel, theReferences); - } -} - -// For each feature from the feature list it searches references to the feature and append them -// to the references map. This is a recusive method. -// \param theFeature a feature to find references -// \param theReferencesMap a map of references -// \param theReferences an out container of references -void findReferences(const std::set& theFeatures, - std::map >& theReferences, - const bool theUseComposite, const bool theUseRecursion, int theRecLevel) -{ - if (theRecLevel > RECURSE_TOP_LEVEL) - return; - theRecLevel++; - std::set::const_iterator anIt = theFeatures.begin(), - aLast = theFeatures.end(); - for (; anIt != aLast; anIt++) { - FeaturePtr aFeature = *anIt; - if (aFeature.get() && theReferences.find(aFeature) == theReferences.end()) { - DocumentPtr aSelFeatureDoc = aFeature->document(); - std::set aSelRefFeatures; - aSelFeatureDoc->refsToFeature(aFeature, aSelRefFeatures, false/*do not emit signals*/); - if (theUseComposite) { // do not filter selection - theReferences[aFeature] = aSelRefFeatures; - } - else { // filter references to skip composition features of the current feature - std::set aFilteredFeatures; - std::set::const_iterator anIt = aSelRefFeatures.begin(), - aLast = aSelRefFeatures.end(); - for (; anIt != aLast; anIt++) { - FeaturePtr aCFeature = *anIt; - CompositeFeaturePtr aComposite = std::dynamic_pointer_cast(aCFeature); - if (aComposite.get() && aComposite->isSub(aFeature)) - continue; /// composite of the current feature should be skipped - aFilteredFeatures.insert(aCFeature); - } - theReferences[aFeature] = aFilteredFeatures; - } - if (theUseRecursion) { -#ifdef DEBUG_CYCLING_1550 - findReferences(aSelRefFeatures, theReferences, theUseComposite, theUseRecursion, theRecLevel); -#else - findReferences(theReferences[aFeature], theReferences, theUseComposite, theUseRecursion, - theRecLevel); -#endif - } - } - } -} - -void findAllReferences(const std::set& theFeatures, - std::map >& theReferences, - const bool theUseComposite, - const bool theUseRecursion) -{ - // For dependencies, find main_list: - // sk_1(ext_1, vertex_1) - // ext_1(bool_1, sk_3) - // vertex_1() - // sk_2(ext_2) - // ext_2(bool_2) - // sk_3() - // Information: bool_1 is not selected, ext_2(bool_2) exists - // find all referenced features - std::map > aMainList; - int aRecLevel = 0; - findReferences(theFeatures, aMainList, theUseComposite, theUseRecursion, aRecLevel); - -#ifdef DEBUG_REMOVE_FEATURES - printMapInfo(aMainList, "firstDependencies"); -#endif - // find all dependencies for each object: - // sk_1(ext_1, vertex_1) + (sk_3, bool_1) - // ext_1(bool_1, sk_3) - // vertex_1() - // sk_2(ext_2) + (bool_1) - // ext_2(bool_1) - // sk_3() - std::map >::const_iterator aMainIt = aMainList.begin(), - aMainLast = aMainList.end(); - for (; aMainIt != aMainLast; aMainIt++) { - FeaturePtr aMainListFeature = aMainIt->first; - - //std::string aName = aMainListFeature->name(); - std::set aMainRefList = aMainIt->second; - -#ifdef DEBUG_REMOVE_FEATURES_RECURSE - char aBuf[50]; - int n = sprintf(aBuf, "%d", aMainRefList.size()); - std::string aSize(aBuf); - std::cout << "_findAllReferences for the Feature: " << getFeatureInfo(aMainListFeature) - << ", references size = " << aSize << std::endl; -#endif - std::set::const_iterator anIt = aMainRefList.begin(), - aLast = aMainRefList.end(); - std::set aResultRefList; - aResultRefList.insert(aMainRefList.begin(), aMainRefList.end()); - for (; anIt != aLast; anIt++) { - FeaturePtr aFeature = *anIt; - int aRecLevel = 0; -#ifdef DEBUG_REMOVE_FEATURES_RECURSE - std::cout << " Ref: " << getFeatureInfo(aFeature) << std::endl; -#endif - aRecLevel++; - addRefsToFeature(aFeature, aMainList, theReferences, aRecLevel, aResultRefList/*aMainRefList*/); - } - theReferences[aMainListFeature] = aResultRefList; - } -#ifdef DEBUG_REMOVE_FEATURES_RECURSE - std::cout << std::endl; -#endif - -#ifdef DEBUG_REMOVE_FEATURES - printMapInfo(theReferences, "allDependencies"); -#endif -} - -void findRefsToFeatures(const std::set& theFeatures, - const std::map >& theReferences, - std::set& theFeaturesRefsTo) -{ - std::set::const_iterator anIt = theFeatures.begin(), - aLast = theFeatures.end(); - for (; anIt != aLast; anIt++) { - FeaturePtr aFeature = *anIt; - if (theReferences.find(aFeature) == theReferences.end()) - continue; - std::set aRefList = theReferences.at(aFeature); - std::set::const_iterator aRefIt = aRefList.begin(), aRefLast = aRefList.end(); - for (; aRefIt != aRefLast; aRefIt++) { - FeaturePtr aRefFeature = *aRefIt; - CompositeFeaturePtr aComposite = std::dynamic_pointer_cast(aRefFeature); - if (aComposite.get() && aComposite->isSub(aFeature)) - continue; /// composite of the current feature should not be removed - - if (theFeatures.find(aRefFeature) == theFeatures.end() && // it is not selected - theFeaturesRefsTo.find(aRefFeature) == theFeaturesRefsTo.end()) // it is not added - theFeaturesRefsTo.insert(aRefFeature); - } - } -} - -void getConcealedResults(const FeaturePtr& theFeature, - std::list >& theResults) -{ - SessionPtr aSession = ModelAPI_Session::get(); - - std::list > > > aRefs; - theFeature->data()->referencesToObjects(aRefs); - std::list > >::const_iterator - anIt = aRefs.begin(), aLast = aRefs.end(); - std::set alreadyThere; // to avoid duplications - for (; anIt != aLast; anIt++) { - if (!aSession->validators()->isConcealed(theFeature->getKind(), anIt->first)) - continue; // use only concealed attributes - std::list anObjects = (*anIt).second; - std::list::const_iterator anOIt = anObjects.begin(), anOLast = anObjects.end(); - for (; anOIt != anOLast; anOIt++) { - ResultPtr aResult = std::dynamic_pointer_cast(*anOIt); - if (aResult && aResult->isConcealed()) { - if (alreadyThere.find(aResult) == alreadyThere.end()) // issue 1712, avoid duplicates - alreadyThere.insert(aResult); - else continue; - theResults.push_back(aResult); - } - } - } -} - -} // namespace ModelAPI_Tools +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: ModelAPI_Tools.cpp +// Created: 06 Aug 2014 +// Author: Vitaly Smetannikov + +#include "ModelAPI_Tools.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define RECURSE_TOP_LEVEL 50 + +//#define DEBUG_REMOVE_FEATURES +//#define DEBUG_REMOVE_FEATURES_RECURSE +//#define DEBUG_CYCLING_1550 + +#ifdef DEBUG_REMOVE_FEATURES_RECURSE +#include +std::string getFeatureInfo(FeaturePtr theFeature) +{ + if (!theFeature.get()) + return ""; + //std::ostringstream aPtrStr; + //aPtrStr << "[" << theFeature.get() << "] "; + std::string aFeatureInfo = /*aPtrStr.str() + */theFeature->name(); + CompositeFeaturePtr aComposite = ModelAPI_Tools::compositeOwner(theFeature); + if (aComposite.get()) { + aFeatureInfo = aFeatureInfo + "[in " + aComposite->name() + "]"; + } + return aFeatureInfo; +} +#endif + +#ifdef DEBUG_REMOVE_FEATURES +void printMapInfo(const std::map >& theMainList, + const std::string& thePrefix) +{ + std::map >::const_iterator aMainIt = theMainList.begin(), + aMainLast = theMainList.end(); + std::string anInfo; + for (; aMainIt != aMainLast; aMainIt++) { + FeaturePtr aMainListFeature = aMainIt->first; + std::set aMainRefList = aMainIt->second; + std::set::const_iterator anIt = aMainRefList.begin(), aLast = aMainRefList.end(); + std::string aRefsInfo; + for (; anIt != aLast; anIt++) { + aRefsInfo += (*anIt)->name().c_str(); + if (anIt != aLast) + aRefsInfo += ", "; + } + if (!aRefsInfo.empty()) { + anInfo = anInfo + aMainListFeature->name().c_str() + ": " + aRefsInfo + "\n"; + } + } + std::cout << thePrefix.c_str() << " [feature: references to]: \n" << anInfo.c_str() << std::endl; +} + +void printListInfo(const std::set& theMainList, + const std::string& thePrefix) +{ + std::set::const_iterator aMainIt = theMainList.begin(), + aMainLast = theMainList.end(); + std::string anInfo; + for (; aMainIt != aMainLast; aMainIt++) { + FeaturePtr aRefFeature = *aMainIt; + anInfo += aRefFeature->name().c_str(); + if (aMainIt != aMainLast) + anInfo += ", "; + } + std::cout << thePrefix.c_str() << ": " << anInfo.c_str() << std::endl; +} +#endif + +namespace ModelAPI_Tools { + +std::shared_ptr shape(const ResultPtr& theResult) +{ + return theResult->shape(); +} + +void shapesOfType(const FeaturePtr& theFeature, + const GeomAPI_Shape::ShapeType& theType, + std::set& theShapes) +{ + std::list aResults = theFeature->results(); + std::list::const_iterator aRIter = aResults.cbegin(); + for (; aRIter != aResults.cend(); aRIter++) { + ResultPtr aResult = *aRIter; + GeomShapePtr aShape = aResult->shape(); + if (aShape.get() && aShape->shapeType() == theType) + theShapes.insert(aShape); + } +} + +const char* toString(ModelAPI_ExecState theExecState) +{ +#define TO_STRING(__NAME__) case __NAME__: return #__NAME__; + switch (theExecState) { + TO_STRING(ModelAPI_StateDone) + TO_STRING(ModelAPI_StateMustBeUpdated) + TO_STRING(ModelAPI_StateExecFailed) + TO_STRING(ModelAPI_StateInvalidArgument) + TO_STRING(ModelAPI_StateNothing) + default: return "Unknown ExecState."; + } +#undef TO_STRING +} + +std::string getFeatureError(const FeaturePtr& theFeature) +{ + std::string anError; + if (!theFeature.get() || !theFeature->data()->isValid() || theFeature->isAction()) + return anError; + + // to be removed later, this error should be got from the feature + if (theFeature->data()->execState() == ModelAPI_StateDone || + theFeature->data()->execState() == ModelAPI_StateMustBeUpdated) + return anError; + + // set error indication + anError = theFeature->error(); + if (anError.empty()) { + bool isDone = ( theFeature->data()->execState() == ModelAPI_StateDone + || theFeature->data()->execState() == ModelAPI_StateMustBeUpdated ); + if (!isDone) { + anError = toString(theFeature->data()->execState()); + // If the feature is Composite and error is StateInvalidArgument, + // error text should include error of first invalid sub-feature. Otherwise + // it is not clear what is the reason of the invalid argument. + if (theFeature->data()->execState() == ModelAPI_StateInvalidArgument) { + CompositeFeaturePtr aComposite = + std::dynamic_pointer_cast(theFeature); + if (aComposite) { + for (int i = 0, aSize = aComposite->numberOfSubs(); i < aSize; i++) { + FeaturePtr aSubFeature = aComposite->subFeature(i); + std::string aSubFeatureError = getFeatureError(aSubFeature); + if (!aSubFeatureError.empty()) { + anError = anError + " in " + aSubFeature->getKind() + ".\n" + aSubFeatureError; + break; + } + } + } + } + } + } + + return anError; +} + +ObjectPtr objectByName(const DocumentPtr& theDocument, const std::string& theGroup, const std::string& theName) +{ + for (int anIndex = 0; anIndex < theDocument->size(theGroup); ++anIndex) { + ObjectPtr anObject = theDocument->object(theGroup, anIndex); + if (anObject->data()->name() == theName) + return anObject; + } + // not found + return ObjectPtr(); +} + +bool findVariable(const DocumentPtr& theDocument, FeaturePtr theSearcher, + const std::string& theName, double& outValue, ResultParameterPtr& theParam) +{ + ObjectPtr aParamObj = objectByName(theDocument, ModelAPI_ResultParameter::group(), theName); + theParam = std::dynamic_pointer_cast(aParamObj); + if (!theParam.get()) + return false; + // avoid usage of parameters created later than the initial parameter + if (theSearcher.get() && theDocument->isLater(theDocument->feature(theParam), theSearcher)) + return false; + AttributeDoublePtr aValueAttribute = theParam->data()->real(ModelAPI_ResultParameter::VALUE()); + outValue = aValueAttribute->value(); + return true; +} + +bool findVariable(FeaturePtr theSearcher, const std::string& theName, double& outValue, ResultParameterPtr& theParam, + const DocumentPtr& theDocument) +{ + SessionPtr aSession = ModelAPI_Session::get(); + std::list aDocList; + DocumentPtr aDocument = theDocument.get() ? theDocument : aSession->activeDocument(); + if (findVariable(aDocument, theSearcher, theName, outValue, theParam)) + return true; + DocumentPtr aRootDocument = aSession->moduleDocument(); + if (aDocument != aRootDocument) { + // any parameters in PartSet is okindependently on the Part position (issu #1504) + if (findVariable(aRootDocument, FeaturePtr(), theName, outValue, theParam)) + return true; + } + return false; +} + +ResultPtr findPartResult(const DocumentPtr& theMain, const DocumentPtr& theSub) +{ + if (theMain != theSub) { // to optimize and avoid of crash on partset document close (don't touch the sub-document structure) + for (int a = theMain->size(ModelAPI_ResultPart::group()) - 1; a >= 0; a--) { + ResultPartPtr aPart = std::dynamic_pointer_cast( + theMain->object(ModelAPI_ResultPart::group(), a)); + if (aPart && aPart->data()->document(ModelAPI_ResultPart::DOC_REF())->value() == theSub) { + return aPart; + } + } + } + return ResultPtr(); +} + +FeaturePtr findPartFeature(const DocumentPtr& theMain, const DocumentPtr& theSub) +{ + if (theMain != theSub) { // to optimize and avoid of crash on partset document close (don't touch the sub-document structure) + for (int a = theMain->size(ModelAPI_Feature::group()) - 1; a >= 0; a--) { + FeaturePtr aPartFeat = std::dynamic_pointer_cast( + theMain->object(ModelAPI_Feature::group(), a)); + if (aPartFeat.get()) { + const std::list >& aResList = aPartFeat->results(); + std::list >::const_iterator aRes = aResList.begin(); + for(; aRes != aResList.end(); aRes++) { + ResultPartPtr aPart = std::dynamic_pointer_cast(*aRes); + if (aPart.get()) { + if (aPart->isActivated() && aPart->partDoc() == theSub) + return aPartFeat; + } else break; // if the first is not Part, others are also not + } + } + } + } + return FeaturePtr(); +} + +CompositeFeaturePtr compositeOwner(const FeaturePtr& theFeature) +{ + if (theFeature.get() && theFeature->data()->isValid()) { + const std::set >& aRefs = theFeature->data()->refsToMe(); + std::set >::const_iterator aRefIter = aRefs.begin(); + for(; aRefIter != aRefs.end(); aRefIter++) { + CompositeFeaturePtr aComp = std::dynamic_pointer_cast + ((*aRefIter)->owner()); + if (aComp.get() && aComp->data()->isValid() && aComp->isSub(theFeature)) + return aComp; + } + } + return CompositeFeaturePtr(); // not found +} + +ResultCompSolidPtr compSolidOwner(const ResultPtr& theSub) +{ + ResultBodyPtr aBody = std::dynamic_pointer_cast(theSub); + if (aBody.get()) { + FeaturePtr aFeatureOwner = aBody->document()->feature(aBody); + if (aFeatureOwner.get()) { + std::list >::const_iterator aResIter = + aFeatureOwner->results().cbegin(); + for(; aResIter != aFeatureOwner->results().cend(); aResIter++) { + ResultCompSolidPtr aComp = std::dynamic_pointer_cast(*aResIter); + if (aComp && aComp->isSub(aBody)) + return aComp; + } + } + } + return ResultCompSolidPtr(); // not found +} + +bool hasSubResults(const ResultPtr& theResult) +{ + ResultCompSolidPtr aCompSolid = std::dynamic_pointer_cast(theResult); + return aCompSolid.get() && aCompSolid->numberOfSubs() > 0; +} + +void allResults(const FeaturePtr& theFeature, std::list& theResults) +{ + if (!theFeature.get()) // safety: for empty feature no results + return; + const std::list >& aResults = theFeature->results(); + std::list >::const_iterator aRIter = aResults.begin(); + for (; aRIter != aResults.cend(); aRIter++) { + theResults.push_back(*aRIter); + // iterate sub-bodies of compsolid + ResultCompSolidPtr aComp = std::dynamic_pointer_cast(*aRIter); + if (aComp.get()) { + int aNumSub = aComp->numberOfSubs(); + for(int a = 0; a < aNumSub; a++) { + theResults.push_back(aComp->subResult(a)); + } + } + } +} + +//****************************************************************** +bool allDocumentsActivated(std::string& theNotActivatedNames) +{ + theNotActivatedNames = ""; + bool anAllPartActivated = true; + + DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument(); + int aSize = aRootDoc->size(ModelAPI_ResultPart::group()); + for (int i = 0; i < aSize; i++) { + ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), i); + ResultPartPtr aPart = std::dynamic_pointer_cast(aObject); + if (!aPart->isActivated()) { + anAllPartActivated = false; + if (!theNotActivatedNames.empty()) + theNotActivatedNames += ", "; + theNotActivatedNames += aObject->data()->name().c_str(); + } + } + return anAllPartActivated; +} + +bool removeFeaturesAndReferences(const std::set& theFeatures, + const bool theFlushRedisplay, + const bool theUseComposite, + const bool theUseRecursion) +{ +#ifdef DEBUG_REMOVE_FEATURES + printListInfo(theFeatures, "selection: "); +#endif + + std::map > aReferences; + ModelAPI_Tools::findAllReferences(theFeatures, aReferences, theUseComposite, theUseRecursion); +#ifdef DEBUG_REMOVE_FEATURES + printMapInfo(aReferences, "allDependencies: "); +#endif + + std::set aFeaturesRefsTo; + ModelAPI_Tools::findRefsToFeatures(theFeatures, aReferences, aFeaturesRefsTo); +#ifdef DEBUG_REMOVE_FEATURES + printListInfo(aFeaturesRefsTo, "references: "); +#endif + + std::set aFeatures = theFeatures; + if (!aFeaturesRefsTo.empty()) + aFeatures.insert(aFeaturesRefsTo.begin(), aFeaturesRefsTo.end()); +#ifdef DEBUG_REMOVE_FEATURES + printListInfo(aFeatures, "removeFeatures: "); +#endif + + return ModelAPI_Tools::removeFeatures(aFeatures, false); +} + +bool removeFeatures(const std::set& theFeatures, + const bool theFlushRedisplay) +{ + bool isDone = false; + std::set::const_iterator anIt = theFeatures.begin(), + aLast = theFeatures.end(); + for (; anIt != aLast; anIt++) { + FeaturePtr aFeature = *anIt; + if (aFeature.get()) { + DocumentPtr aDoc = aFeature->document(); + // flush REDISPLAY signal after remove feature + aDoc->removeFeature(aFeature); + isDone = true; + } + } + if (isDone && theFlushRedisplay) { + // the redisplay signal should be flushed in order to erase the feature presentation in the viewer + // if should be done after removeFeature() of document + Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)); + } + return true; +} + +// Fills the references list by all references of the feature from the references map. +// This is a recusive method to find references by next found feature in the map of references. +// \param theFeature a feature to find references +// \param theReferencesMap a map of references +// \param theReferences an out container of references +void addRefsToFeature(const FeaturePtr& theFeature, + const std::map >& theReferencesMap, + std::map >& theProcessedReferences, + int theRecLevel, + std::set& theReferences) +{ + if (theRecLevel > RECURSE_TOP_LEVEL) + return; + theRecLevel++; + + // if the feature is already processed, get the ready references from the map + if (theProcessedReferences.find(theFeature) != theProcessedReferences.end()) { + std::set aReferences = theProcessedReferences.at(theFeature); + theReferences.insert(aReferences.begin(), aReferences.end()); + return; + } + + if (theReferencesMap.find(theFeature) == theReferencesMap.end()) + return; // this feature is not in the selection list, so exists without references to it + std::set aMainReferences = theReferencesMap.at(theFeature); + + std::set::const_iterator anIt = aMainReferences.begin(), + aLast = aMainReferences.end(); +#ifdef DEBUG_REMOVE_FEATURES_RECURSE + std::string aSpacing; + for (int i = 0; i < theRecLevel; i++) + aSpacing.append(" "); +#endif + + for (; anIt != aLast; anIt++) { + FeaturePtr aRefFeature = *anIt; +#ifdef DEBUG_REMOVE_FEATURES_RECURSE + std::cout << aSpacing << " Ref: " << getFeatureInfo(aRefFeature) << std::endl; +#endif + if (theReferences.find(aRefFeature) == theReferences.end()) + theReferences.insert(aRefFeature); + addRefsToFeature(aRefFeature, theReferencesMap, theProcessedReferences, theRecLevel, theReferences); + } +} + +// For each feature from the feature list it searches references to the feature and append them +// to the references map. This is a recusive method. +// \param theFeature a feature to find references +// \param theReferencesMap a map of references +// \param theReferences an out container of references +void findReferences(const std::set& theFeatures, + std::map >& theReferences, + const bool theUseComposite, const bool theUseRecursion, int theRecLevel) +{ + if (theRecLevel > RECURSE_TOP_LEVEL) + return; + theRecLevel++; + std::set::const_iterator anIt = theFeatures.begin(), + aLast = theFeatures.end(); + for (; anIt != aLast; anIt++) { + FeaturePtr aFeature = *anIt; + if (aFeature.get() && theReferences.find(aFeature) == theReferences.end()) { + DocumentPtr aSelFeatureDoc = aFeature->document(); + std::set aSelRefFeatures; + aSelFeatureDoc->refsToFeature(aFeature, aSelRefFeatures, false/*do not emit signals*/); + if (theUseComposite) { // do not filter selection + theReferences[aFeature] = aSelRefFeatures; + } + else { // filter references to skip composition features of the current feature + std::set aFilteredFeatures; + std::set::const_iterator anIt = aSelRefFeatures.begin(), + aLast = aSelRefFeatures.end(); + for (; anIt != aLast; anIt++) { + FeaturePtr aCFeature = *anIt; + CompositeFeaturePtr aComposite = std::dynamic_pointer_cast(aCFeature); + if (aComposite.get() && aComposite->isSub(aFeature)) + continue; /// composite of the current feature should be skipped + aFilteredFeatures.insert(aCFeature); + } + theReferences[aFeature] = aFilteredFeatures; + } + if (theUseRecursion) { +#ifdef DEBUG_CYCLING_1550 + findReferences(aSelRefFeatures, theReferences, theUseComposite, theUseRecursion, theRecLevel); +#else + findReferences(theReferences[aFeature], theReferences, theUseComposite, theUseRecursion, + theRecLevel); +#endif + } + } + } +} + +void findAllReferences(const std::set& theFeatures, + std::map >& theReferences, + const bool theUseComposite, + const bool theUseRecursion) +{ + // For dependencies, find main_list: + // sk_1(ext_1, vertex_1) + // ext_1(bool_1, sk_3) + // vertex_1() + // sk_2(ext_2) + // ext_2(bool_2) + // sk_3() + // Information: bool_1 is not selected, ext_2(bool_2) exists + // find all referenced features + std::map > aMainList; + int aRecLevel = 0; + findReferences(theFeatures, aMainList, theUseComposite, theUseRecursion, aRecLevel); + +#ifdef DEBUG_REMOVE_FEATURES + printMapInfo(aMainList, "firstDependencies"); +#endif + // find all dependencies for each object: + // sk_1(ext_1, vertex_1) + (sk_3, bool_1) + // ext_1(bool_1, sk_3) + // vertex_1() + // sk_2(ext_2) + (bool_1) + // ext_2(bool_1) + // sk_3() + std::map >::const_iterator aMainIt = aMainList.begin(), + aMainLast = aMainList.end(); + for (; aMainIt != aMainLast; aMainIt++) { + FeaturePtr aMainListFeature = aMainIt->first; + + //std::string aName = aMainListFeature->name(); + std::set aMainRefList = aMainIt->second; + +#ifdef DEBUG_REMOVE_FEATURES_RECURSE + char aBuf[50]; + int n = sprintf(aBuf, "%d", aMainRefList.size()); + std::string aSize(aBuf); + std::cout << "_findAllReferences for the Feature: " << getFeatureInfo(aMainListFeature) + << ", references size = " << aSize << std::endl; +#endif + std::set::const_iterator anIt = aMainRefList.begin(), + aLast = aMainRefList.end(); + std::set aResultRefList; + aResultRefList.insert(aMainRefList.begin(), aMainRefList.end()); + for (; anIt != aLast; anIt++) { + FeaturePtr aFeature = *anIt; + int aRecLevel = 0; +#ifdef DEBUG_REMOVE_FEATURES_RECURSE + std::cout << " Ref: " << getFeatureInfo(aFeature) << std::endl; +#endif + aRecLevel++; + addRefsToFeature(aFeature, aMainList, theReferences, aRecLevel, aResultRefList/*aMainRefList*/); + } + theReferences[aMainListFeature] = aResultRefList; + } +#ifdef DEBUG_REMOVE_FEATURES_RECURSE + std::cout << std::endl; +#endif + +#ifdef DEBUG_REMOVE_FEATURES + printMapInfo(theReferences, "allDependencies"); +#endif +} + +void findRefsToFeatures(const std::set& theFeatures, + const std::map >& theReferences, + std::set& theFeaturesRefsTo) +{ + std::set::const_iterator anIt = theFeatures.begin(), + aLast = theFeatures.end(); + for (; anIt != aLast; anIt++) { + FeaturePtr aFeature = *anIt; + if (theReferences.find(aFeature) == theReferences.end()) + continue; + std::set aRefList = theReferences.at(aFeature); + std::set::const_iterator aRefIt = aRefList.begin(), aRefLast = aRefList.end(); + for (; aRefIt != aRefLast; aRefIt++) { + FeaturePtr aRefFeature = *aRefIt; + CompositeFeaturePtr aComposite = std::dynamic_pointer_cast(aRefFeature); + if (aComposite.get() && aComposite->isSub(aFeature)) + continue; /// composite of the current feature should not be removed + + if (theFeatures.find(aRefFeature) == theFeatures.end() && // it is not selected + theFeaturesRefsTo.find(aRefFeature) == theFeaturesRefsTo.end()) // it is not added + theFeaturesRefsTo.insert(aRefFeature); + } + } +} + +void getConcealedResults(const FeaturePtr& theFeature, + std::list >& theResults) +{ + SessionPtr aSession = ModelAPI_Session::get(); + + std::list > > > aRefs; + theFeature->data()->referencesToObjects(aRefs); + std::list > >::const_iterator + anIt = aRefs.begin(), aLast = aRefs.end(); + std::set alreadyThere; // to avoid duplications + for (; anIt != aLast; anIt++) { + if (!aSession->validators()->isConcealed(theFeature->getKind(), anIt->first)) + continue; // use only concealed attributes + std::list anObjects = (*anIt).second; + std::list::const_iterator anOIt = anObjects.begin(), anOLast = anObjects.end(); + for (; anOIt != anOLast; anOIt++) { + ResultPtr aResult = std::dynamic_pointer_cast(*anOIt); + if (aResult && aResult->isConcealed()) { + if (alreadyThere.find(aResult) == alreadyThere.end()) // issue 1712, avoid duplicates + alreadyThere.insert(aResult); + else continue; + theResults.push_back(aResult); + } + } + } +} + +} // namespace ModelAPI_Tools diff --git a/src/ModelAPI/ModelAPI_Tools.h b/src/ModelAPI/ModelAPI_Tools.h index 4d1c7a65f..d9c685d6e 100755 --- a/src/ModelAPI/ModelAPI_Tools.h +++ b/src/ModelAPI/ModelAPI_Tools.h @@ -1,161 +1,161 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: ModelAPI_Tools.h -// Created: 06 Aug 2014 -// Author: Vitaly Smetannikov - -#ifndef ModelAPI_Tools_HeaderFile -#define ModelAPI_Tools_HeaderFile - -#include "ModelAPI.h" - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -namespace ModelAPI_Tools { -/// Returns shape from the given Result object -MODELAPI_EXPORT std::shared_ptr shape(const ResultPtr& theResult); - -/// Creates a container of shape of the feature results satisfied the given shape type -/// \param theFeature a source feature -/// \param theType shape type -/// \param an output container for shapes -MODELAPI_EXPORT void shapesOfType(const FeaturePtr& theFeature, - const GeomAPI_Shape::ShapeType& theType, - std::set& theShapes); - -/*! Returns the feature error generated according to feature error and exec state - * \param theFeature a feature - * \return error value or empty string - */ -MODELAPI_EXPORT std::string getFeatureError(const FeaturePtr& theFeature); - -/*! - * Searches for variable with name \param theName in \param theDocument. - * If found, set it value in the \param outValue and returns true. - * theSearcher must be located later in the history than the found variable. - */ -MODELAPI_EXPORT bool findVariable(const DocumentPtr& theDocument, FeaturePtr theSearcher, - const std::string& theName, double& outValue, ResultParameterPtr& theParam); - -/*! - * Searches for variable with name \param theName in the active document (Part), when - * in the root document (PartSet). If found, set it value in the \param outValue - * and returns true. If \param theDocument is empty active document is used. - * theSearcher must be located later in the history than the found variable. - */ -MODELAPI_EXPORT bool findVariable(FeaturePtr theSearcher, const std::string& theName, - double& outValue, ResultParameterPtr& theParam, - const DocumentPtr& theDocument = DocumentPtr()); - -/*! - * Searches for Part result that contains the reference to the given document. - * The result must be presented in the tree. - * \param theMain document that contains the searched feature - * \param theSub document that is searched, the resulting feature references to it - * \returns null if not found - */ -MODELAPI_EXPORT ResultPtr findPartResult(const DocumentPtr& theMain, const DocumentPtr& theSub); - -/*! - * Searches for Part the feature that contains in result the reference to the given document. - * The result may be disabled. - * \param theMain document that contains the searched feature - * \param theSub document that is searched, the resulting feature references to it - * \returns null if not found - */ -MODELAPI_EXPORT FeaturePtr findPartFeature(const DocumentPtr& theMain, const DocumentPtr& theSub); - -/*! - * Returns the composite feature - parent of this feature. - * \param theFeature the sub-element of composite - * \returns null if it is not sub-element of composite - */ -MODELAPI_EXPORT CompositeFeaturePtr compositeOwner(const FeaturePtr& theFeature); - -/*! - * Returns the compsolid result - parent of this result. - * \param theSub the sub-element of comp-solid - * \returns null if it is not sub-element of composite - */ -MODELAPI_EXPORT ResultCompSolidPtr compSolidOwner(const ResultPtr& theSub); - -/*! -* Returns true if the result contains a not empty list of sub results. It processes result compsolid. -* \param theResult a result object -* \returns boolean value -*/ -MODELAPI_EXPORT bool hasSubResults(const ResultPtr& theResult); - -/*! -* Adds the results of the given feature to theResults list: including disabled and sub-results -*/ -MODELAPI_EXPORT void allResults(const FeaturePtr& theFeature, std::list& theResults); - -/*! - Returns true if there are no parts in the document, which are not activated - \param theNotActivatedNames out string which contains not activated names - \return a boolean value - */ -MODELAPI_EXPORT bool allDocumentsActivated(std::string& theNotActivatedNames); - - -/*! Removes features from the document -* \param theFeatures a list of features to be removed -* \param theFlushRedisplay a boolean value if the redisplay signal should be flushed -* \return true if at least one feature is removed -*/ -MODELAPI_EXPORT bool removeFeaturesAndReferences(const std::set& theFeatures, - const bool theFlushRedisplay = false, - const bool theUseComposite = false, - const bool theUseRecursion = true); - -/*! Removes features from the document -* \param theFeatures a list of features to be removed -* \param theFlushRedisplay a boolean value if the redisplay signal should be flushed -* \return true if at least one feature is removed -*/ -MODELAPI_EXPORT bool removeFeatures(const std::set& theFeatures, - const bool theFlushRedisplay); - -/*! Build a map of references for the given set of features -* \param theFeatures a list of features -* \param theReferences a map of all references to the features -* \param theUseComposite state if the composite features of the reference should be in the map -* \param theUseRecursion state if references for features out of the sources feature - list are put into the result container. E.g. if theFeatures contains "Sketch_2", map will - contain references to this feature also. -*/ -MODELAPI_EXPORT void findAllReferences(const std::set& theFeatures, - std::map >& theReferences, - const bool theUseComposite = true, - const bool theUseRecursion = true); - -/*! In the map of references find all features referenced to the source feature -* \param theFeatures a list of features to find references -* \param theReferences a map of all references to the features -* \param theFeaturesRefsTo an out list of referenced features -*/ -MODELAPI_EXPORT void findRefsToFeatures(const std::set& aFeatures, - const std::map >& aReferences, - std::set& aFeaturesRefsTo); - -/*! Finds referenced of the feature to objects and collects concealed results. -* \param theFeatures a model feature -* \param theResults container for concealed results. It has no duplications -*/ -MODELAPI_EXPORT void getConcealedResults(const FeaturePtr& theFeature, - std::list >& theResults); -} - -#endif +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: ModelAPI_Tools.h +// Created: 06 Aug 2014 +// Author: Vitaly Smetannikov + +#ifndef ModelAPI_Tools_HeaderFile +#define ModelAPI_Tools_HeaderFile + +#include "ModelAPI.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +namespace ModelAPI_Tools { +/// Returns shape from the given Result object +MODELAPI_EXPORT std::shared_ptr shape(const ResultPtr& theResult); + +/// Creates a container of shape of the feature results satisfied the given shape type +/// \param theFeature a source feature +/// \param theType shape type +/// \param an output container for shapes +MODELAPI_EXPORT void shapesOfType(const FeaturePtr& theFeature, + const GeomAPI_Shape::ShapeType& theType, + std::set& theShapes); + +/*! Returns the feature error generated according to feature error and exec state + * \param theFeature a feature + * \return error value or empty string + */ +MODELAPI_EXPORT std::string getFeatureError(const FeaturePtr& theFeature); + +/*! + * Searches for variable with name \param theName in \param theDocument. + * If found, set it value in the \param outValue and returns true. + * theSearcher must be located later in the history than the found variable. + */ +MODELAPI_EXPORT bool findVariable(const DocumentPtr& theDocument, FeaturePtr theSearcher, + const std::string& theName, double& outValue, ResultParameterPtr& theParam); + +/*! + * Searches for variable with name \param theName in the active document (Part), when + * in the root document (PartSet). If found, set it value in the \param outValue + * and returns true. If \param theDocument is empty active document is used. + * theSearcher must be located later in the history than the found variable. + */ +MODELAPI_EXPORT bool findVariable(FeaturePtr theSearcher, const std::string& theName, + double& outValue, ResultParameterPtr& theParam, + const DocumentPtr& theDocument = DocumentPtr()); + +/*! + * Searches for Part result that contains the reference to the given document. + * The result must be presented in the tree. + * \param theMain document that contains the searched feature + * \param theSub document that is searched, the resulting feature references to it + * \returns null if not found + */ +MODELAPI_EXPORT ResultPtr findPartResult(const DocumentPtr& theMain, const DocumentPtr& theSub); + +/*! + * Searches for Part the feature that contains in result the reference to the given document. + * The result may be disabled. + * \param theMain document that contains the searched feature + * \param theSub document that is searched, the resulting feature references to it + * \returns null if not found + */ +MODELAPI_EXPORT FeaturePtr findPartFeature(const DocumentPtr& theMain, const DocumentPtr& theSub); + +/*! + * Returns the composite feature - parent of this feature. + * \param theFeature the sub-element of composite + * \returns null if it is not sub-element of composite + */ +MODELAPI_EXPORT CompositeFeaturePtr compositeOwner(const FeaturePtr& theFeature); + +/*! + * Returns the compsolid result - parent of this result. + * \param theSub the sub-element of comp-solid + * \returns null if it is not sub-element of composite + */ +MODELAPI_EXPORT ResultCompSolidPtr compSolidOwner(const ResultPtr& theSub); + +/*! +* Returns true if the result contains a not empty list of sub results. It processes result compsolid. +* \param theResult a result object +* \returns boolean value +*/ +MODELAPI_EXPORT bool hasSubResults(const ResultPtr& theResult); + +/*! +* Adds the results of the given feature to theResults list: including disabled and sub-results +*/ +MODELAPI_EXPORT void allResults(const FeaturePtr& theFeature, std::list& theResults); + +/*! + Returns true if there are no parts in the document, which are not activated + \param theNotActivatedNames out string which contains not activated names + \return a boolean value + */ +MODELAPI_EXPORT bool allDocumentsActivated(std::string& theNotActivatedNames); + + +/*! Removes features from the document +* \param theFeatures a list of features to be removed +* \param theFlushRedisplay a boolean value if the redisplay signal should be flushed +* \return true if at least one feature is removed +*/ +MODELAPI_EXPORT bool removeFeaturesAndReferences(const std::set& theFeatures, + const bool theFlushRedisplay = false, + const bool theUseComposite = false, + const bool theUseRecursion = true); + +/*! Removes features from the document +* \param theFeatures a list of features to be removed +* \param theFlushRedisplay a boolean value if the redisplay signal should be flushed +* \return true if at least one feature is removed +*/ +MODELAPI_EXPORT bool removeFeatures(const std::set& theFeatures, + const bool theFlushRedisplay); + +/*! Build a map of references for the given set of features +* \param theFeatures a list of features +* \param theReferences a map of all references to the features +* \param theUseComposite state if the composite features of the reference should be in the map +* \param theUseRecursion state if references for features out of the sources feature + list are put into the result container. E.g. if theFeatures contains "Sketch_2", map will + contain references to this feature also. +*/ +MODELAPI_EXPORT void findAllReferences(const std::set& theFeatures, + std::map >& theReferences, + const bool theUseComposite = true, + const bool theUseRecursion = true); + +/*! In the map of references find all features referenced to the source feature +* \param theFeatures a list of features to find references +* \param theReferences a map of all references to the features +* \param theFeaturesRefsTo an out list of referenced features +*/ +MODELAPI_EXPORT void findRefsToFeatures(const std::set& aFeatures, + const std::map >& aReferences, + std::set& aFeaturesRefsTo); + +/*! Finds referenced of the feature to objects and collects concealed results. +* \param theFeatures a model feature +* \param theResults container for concealed results. It has no duplications +*/ +MODELAPI_EXPORT void getConcealedResults(const FeaturePtr& theFeature, + std::list >& theResults); +} + +#endif diff --git a/src/ModelAPI/Test/TestUndoRedo.py b/src/ModelAPI/Test/TestUndoRedo.py index 3981f30d4..db93001c3 100644 --- a/src/ModelAPI/Test/TestUndoRedo.py +++ b/src/ModelAPI/Test/TestUndoRedo.py @@ -1,37 +1,37 @@ -from ModelAPI import * -aSession = ModelAPI_Session.get() -aDoc = aSession.moduleDocument() -assert(not aSession.canUndo()) -assert(not aSession.canRedo()) - -aSession.startOperation() -aFeature = aDoc.addFeature("Point") -# Since validators are introduced we have to initialize all -# the feature's attributes -# aFeature.string("creation_method").setValue("by_xyz") -aFeature.real("x").setValue(1.) -aFeature.real("y").setValue(-1.) -aFeature.real("z").setValue(0.) -aFeatureName = aFeature.name() -# "2" is because Origin is the first point -assert(aFeatureName == "Point_2") - -aFeature.execute() -aSession.finishOperation() - -assert(aDoc.size("Construction") == 8) -assert(aSession.canUndo()) -assert(not aSession.canRedo()) - -aSession.undo() -assert(aDoc.size("Construction") == 7) -assert(not aSession.canUndo()) -assert(aSession.canRedo()) - -aSession.redo() -assert(aDoc.size("Construction") == 8) -assert(aSession.canUndo()) -assert(not aSession.canRedo()) - -import model -assert(model.checkPythonDump()) +from ModelAPI import * +aSession = ModelAPI_Session.get() +aDoc = aSession.moduleDocument() +assert(not aSession.canUndo()) +assert(not aSession.canRedo()) + +aSession.startOperation() +aFeature = aDoc.addFeature("Point") +# Since validators are introduced we have to initialize all +# the feature's attributes +# aFeature.string("creation_method").setValue("by_xyz") +aFeature.real("x").setValue(1.) +aFeature.real("y").setValue(-1.) +aFeature.real("z").setValue(0.) +aFeatureName = aFeature.name() +# "2" is because Origin is the first point +assert(aFeatureName == "Point_2") + +aFeature.execute() +aSession.finishOperation() + +assert(aDoc.size("Construction") == 8) +assert(aSession.canUndo()) +assert(not aSession.canRedo()) + +aSession.undo() +assert(aDoc.size("Construction") == 7) +assert(not aSession.canUndo()) +assert(aSession.canRedo()) + +aSession.redo() +assert(aDoc.size("Construction") == 8) +assert(aSession.canUndo()) +assert(not aSession.canRedo()) + +import model +assert(model.checkPythonDump()) diff --git a/src/ModuleBase/ModuleBase.h b/src/ModuleBase/ModuleBase.h index 6152b63ec..436de02dd 100644 --- a/src/ModuleBase/ModuleBase.h +++ b/src/ModuleBase/ModuleBase.h @@ -1,20 +1,20 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -#ifndef MODULEBASE_H -#define MODULEBASE_H - -#if defined MODULEBASE_EXPORTS -#if defined WIN32 -#define MODULEBASE_EXPORT __declspec( dllexport ) -#else -#define MODULEBASE_EXPORT -#endif -#else -#if defined WIN32 -#define MODULEBASE_EXPORT __declspec( dllimport ) -#else -#define MODULEBASE_EXPORT -#endif -#endif - +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +#ifndef MODULEBASE_H +#define MODULEBASE_H + +#if defined MODULEBASE_EXPORTS +#if defined WIN32 +#define MODULEBASE_EXPORT __declspec( dllexport ) +#else +#define MODULEBASE_EXPORT +#endif +#else +#if defined WIN32 +#define MODULEBASE_EXPORT __declspec( dllimport ) +#else +#define MODULEBASE_EXPORT +#endif +#endif + #endif //MODULEBASE_H \ No newline at end of file diff --git a/src/ModuleBase/ModuleBase_FilterValidated.cpp b/src/ModuleBase/ModuleBase_FilterValidated.cpp index b9238538c..097eb60cb 100644 --- a/src/ModuleBase/ModuleBase_FilterValidated.cpp +++ b/src/ModuleBase/ModuleBase_FilterValidated.cpp @@ -1,57 +1,57 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: ModuleBase_FilterValidated.cpp -// Created: 17 Mar 2015 -// Author: Natalia ERMOLAEVA - -#include "ModuleBase_FilterValidated.h" -#include "ModuleBase_IWorkshop.h" -#include "ModuleBase_IViewer.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -IMPLEMENT_STANDARD_HANDLE(ModuleBase_FilterValidated, SelectMgr_Filter); -IMPLEMENT_STANDARD_RTTIEXT(ModuleBase_FilterValidated, SelectMgr_Filter); - -Standard_Boolean ModuleBase_FilterValidated::IsOk(const Handle(SelectMgr_EntityOwner)& theOwner) const -{ - bool aValid = true; - ModuleBase_Operation* anOperation = myWorkshop->module()->currentOperation(); - if (anOperation) { - ModuleBase_IViewer* aViewer = myWorkshop->viewer(); - Handle(AIS_InteractiveContext) aContext = aViewer->AISContext(); - - ModuleBase_Tools::selectionInfo(aContext, "ModuleBase_FilterValidated::IsOk"); - - ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel(); - ModuleBase_ModelWidget* aCurrentWidget = aPanel->preselectionWidget(); - if (!aCurrentWidget) - aCurrentWidget = myWorkshop->module()->activeWidget(); - if (aCurrentWidget) { - ModuleBase_ViewerPrsPtr aPrs(new ModuleBase_ViewerPrs()); - myWorkshop->selection()->fillPresentation(aPrs, theOwner); - ModuleBase_WidgetValidated* aWidgetValidated = dynamic_cast - (aCurrentWidget); - if (aWidgetValidated) - aValid = !aWidgetValidated || aWidgetValidated->isValidSelection(aPrs); - else{ - ModuleBase_WidgetValidator* aWidgetValidator = aCurrentWidget->widgetValidator(); - if (aWidgetValidator) - aValid = aWidgetValidator->isValidSelection(aPrs); - } - } - } - -#ifdef DEBUG_FILTERS - qDebug(QString("ModuleBase_FilterValidated::IsOk = %1").arg(aValid).toStdString().c_str()); -#endif - return aValid; -} - +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: ModuleBase_FilterValidated.cpp +// Created: 17 Mar 2015 +// Author: Natalia ERMOLAEVA + +#include "ModuleBase_FilterValidated.h" +#include "ModuleBase_IWorkshop.h" +#include "ModuleBase_IViewer.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +IMPLEMENT_STANDARD_HANDLE(ModuleBase_FilterValidated, SelectMgr_Filter); +IMPLEMENT_STANDARD_RTTIEXT(ModuleBase_FilterValidated, SelectMgr_Filter); + +Standard_Boolean ModuleBase_FilterValidated::IsOk(const Handle(SelectMgr_EntityOwner)& theOwner) const +{ + bool aValid = true; + ModuleBase_Operation* anOperation = myWorkshop->module()->currentOperation(); + if (anOperation) { + ModuleBase_IViewer* aViewer = myWorkshop->viewer(); + Handle(AIS_InteractiveContext) aContext = aViewer->AISContext(); + + ModuleBase_Tools::selectionInfo(aContext, "ModuleBase_FilterValidated::IsOk"); + + ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel(); + ModuleBase_ModelWidget* aCurrentWidget = aPanel->preselectionWidget(); + if (!aCurrentWidget) + aCurrentWidget = myWorkshop->module()->activeWidget(); + if (aCurrentWidget) { + ModuleBase_ViewerPrsPtr aPrs(new ModuleBase_ViewerPrs()); + myWorkshop->selection()->fillPresentation(aPrs, theOwner); + ModuleBase_WidgetValidated* aWidgetValidated = dynamic_cast + (aCurrentWidget); + if (aWidgetValidated) + aValid = !aWidgetValidated || aWidgetValidated->isValidSelection(aPrs); + else{ + ModuleBase_WidgetValidator* aWidgetValidator = aCurrentWidget->widgetValidator(); + if (aWidgetValidator) + aValid = aWidgetValidator->isValidSelection(aPrs); + } + } + } + +#ifdef DEBUG_FILTERS + qDebug(QString("ModuleBase_FilterValidated::IsOk = %1").arg(aValid).toStdString().c_str()); +#endif + return aValid; +} + diff --git a/src/ModuleBase/ModuleBase_IModule.h b/src/ModuleBase/ModuleBase_IModule.h index 75cd6e62a..41a37c0b4 100755 --- a/src/ModuleBase/ModuleBase_IModule.h +++ b/src/ModuleBase/ModuleBase_IModule.h @@ -1,373 +1,373 @@ - // Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -#ifndef ModuleBase_IModule_H -#define ModuleBase_IModule_H - -#include "ModuleBase.h" -#include "ModuleBase_IWorkshop.h" - -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -class QAction; -class QMouseEvent; -class QKeyEvent; -class QMenu; -class Config_WidgetAPI; -class ModuleBase_ModelWidget; -class ModuleBase_Operation; -class ModuleBase_IWorkshop; -class ModelAPI_Result; - -class Handle_AIS_InteractiveObject; - -/** - * \ingroup GUI - * Interface to a module - */ -class MODULEBASE_EXPORT ModuleBase_IModule : public QObject -{ - Q_OBJECT - public: - /// enumeration to know which objects should be customized - enum ModuleBase_CustomizeFlag { - CustomizeArguments = 0, /// references of other objects referenced to the current feature - CustomizeResults, /// results of the current feature - CustomizeHighlightedObjects /// highlighted objects of the active widget - }; - - /// Constructor - /// \param theParent instance of workshop interface - ModuleBase_IModule(ModuleBase_IWorkshop* theParent); - - virtual ~ModuleBase_IModule() {} - - /// Add default selection filters of the module to the current viewer - virtual void activateSelectionFilters() {}; - - /// Remove default selection filters of the module from the current viewer - virtual void deactivateSelectionFilters() {}; - - /// Stores the current selection - virtual void storeSelection() {}; - - /// Restores the current selection - virtual void restoreSelection() {}; - - /// Reads description of features from XML file - virtual void createFeatures(); - - /// Called on creation of menu item in desktop - virtual void actionCreated(QAction*); - - /// Launching of a edit operation on the feature - /// \param theFeature feature for editing - virtual void editFeature(FeaturePtr theFeature); - - /// Returns true if the operation can be committed. Result in default implementation is true. - /// \return boolean value - virtual bool canCommitOperation() const { return true; } - - /// Creates an operation and send it to loop - /// \param theCmdId the operation name - virtual void launchOperation(const QString& theCmdId); - - /// Executes feature as a modal dialog box - /// \param theCmdId the operation name - virtual void launchModal(const QString& theCmdId); - - /// Realizes some functionality by an operation start - /// \param theOperation a started operation - virtual void operationStarted(ModuleBase_Operation* theOperation) {} - - /// Realizes some functionality by an operation resume - /// By default it emits operationResumed signal - /// \param theOperation a resumed operation - virtual void operationResumed(ModuleBase_Operation* theOperation); - - /// Realizes some functionality by an operation stop - virtual void operationStopped(ModuleBase_Operation* theOperation) {} - - /// Realizes some functionality by an operation commit - virtual void operationCommitted(ModuleBase_Operation* theOperation) {} - - /// Realizes some functionality by an operation abort - virtual void operationAborted(ModuleBase_Operation* theOperation) {} - - /// Realizes some functionality by an operation start - virtual ModuleBase_Operation* currentOperation() const = 0; - - /// Add menu items for viewer into the actions map - /// \param theStdActions a map of standard actions - /// \param theParent a parent widget - /// \param theMenuActions map of action/menu for the desirable index in the viewer menu - /// \return true if items are added and there is no necessity to provide standard menu - virtual bool addViewerMenu(const QMap& theStdActions, - QWidget* theParent, - QMap& theMenuActions) const - { return false; } - - /// Add menu items for object browser into the given menu - /// \param theMenu a popup menu to be shown in the object browser - virtual void addObjectBrowserMenu(QMenu* theMenu) const {}; - - /// Creates custom widgets for property panel - /// \param theType a type of widget - /// \param theParent the parent object - /// \param theWidgetApi the widget configuration. The attribute of the model widget is obtained from - virtual ModuleBase_ModelWidget* createWidgetByType(const std::string& theType, QWidget* theParent, - Config_WidgetAPI* theWidgetApi) - { - return 0; - } - - /// Returns the active widget, by default it is the property panel active widget - virtual ModuleBase_ModelWidget* activeWidget() const = 0; - - /// Returns current workshop - ModuleBase_IWorkshop* workshop() const { return myWorkshop; } - - /// Call back forlast tuning of property panel before operation performance - /// It is called as on clearing of property panel as on filling with new widgets - virtual void propertyPanelDefined(ModuleBase_Operation* theOperation) {} - - /// Have an opportunity to create widgets for the current operation instead of standard creation in workshop - /// \param theOperation a started operation - /// \param theWidgets a list of created widgets - /// \return boolean result, false by default - virtual bool createWidgets(ModuleBase_Operation* theOperation, - QList& theWidgets) const { return false; } - - //! Returns True if there are available Undos and there is not an active operation - virtual bool canUndo() const; - - //! Returns True if there are available Redos and there is not an active operation - virtual bool canRedo() const; - - /// Returns true if the action can be applyed to the object - /// \param theObject a checked object - /// \param theActionId an identifier of action, to be found in the menu manager like "DELETE_CMD" - /// \return the a boolean result - virtual bool canApplyAction(const ObjectPtr& theObject, const QString& theActionId) const = 0; - - /// Returns True if the current operation can be committed. By default it is true. - /// \return a boolean value - //virtual bool canCommitOperation() const; - - /// Returns whether the object can be erased. The default realization returns true. - /// \param theObject a model object - virtual bool canEraseObject(const ObjectPtr& theObject) const; - - /// Returns whether the object can be displayed. The default realization returns true. - /// \param theObject a model object - virtual bool canDisplayObject(const ObjectPtr& theObject) const; - - /// Make some functionality after the objects are hidden in viewer - /// \param theObjects a list of hidden objects - //virtual void processHiddenObject(const std::list& theObjects) {}; - - /// Returns true if selection for the object can be activate. - /// By default a result or feature of the current operation can not be activated - /// \param theObject a model object - virtual bool canActivateSelection(const ObjectPtr& theObject) const; - - /// Reacts to the delete action in module - /// \returns true if the action is processed - virtual bool deleteObjects() { return false; }; - - /// Performs functionality on closing document - virtual void closeDocument() = 0; - - /// Clears specific presentations in the viewer - virtual void clearViewer() = 0; - - /// Returns a list of modes, where the AIS objects should be activated - /// \param theModes a list of modes - virtual void activeSelectionModes(QIntList& theModes) {} - - /// Appends specific selection modes for the module to the list of types - /// \param theTypes a selection modes to be extended - virtual void customSubShapesSelectionModes(QIntList& theTypes) {} - - /// Return true if the custom presentation is activated - /// \param theFlag a flag of level of customization, which means that only part of sub-elements - /// \return boolean value - virtual bool isCustomPrsActivated(const ModuleBase_CustomizeFlag& theFlag) const { return false; }; - - /// Activate custom presentation for the object. Default realization is empty. - /// \param theFeature a feature instance - /// \param theFlag a flag of level of customization, which means that only part of sub-elements - /// \param theUpdateViewer the parameter whether the viewer should be update immediately - virtual void activateCustomPrs(const FeaturePtr& theFeature, - const ModuleBase_CustomizeFlag& theFlag, - const bool theUpdateViewer) {} - - /// Deactivate custom presentation for the object. Default realization is empty. - /// \param theFlag a flag of level of customization, which means that only part of sub-elements - /// \param theUpdateViewer the parameter whether the viewer should be update immediately - virtual void deactivateCustomPrs(const ModuleBase_CustomizeFlag& theFlag, - const bool theUpdateViewer) {} - - /// Modifies the given presentation in the custom way. - virtual bool customisePresentation(std::shared_ptr theResult, AISObjectPtr thePrs, - GeomCustomPrsPtr theCustomPrs) { return false; }; - - /// Update the object presentable properties such as color, lines width and other - /// If the object is result with the color attribute value set, it is used, - /// otherwise the customize is applyed to the object's feature if it is a custom prs - /// \param theObject an object instance - /// \param theFlag a flag of level of customization, which means that only part of sub-elements - /// should be updated(e.g. only highlighted elements) - /// \param theUpdateViewer the parameter whether the viewer should be update immediately - /// \returns true if the object is modified - virtual bool customizeObject(ObjectPtr theObject, const ModuleBase_CustomizeFlag& theFlag, - const bool theUpdateViewer); - - /// This method is called on object browser creation for customization of module specific features - /// \param theObjectBrowser a pinter on Object Browser widget - virtual void customizeObjectBrowser(QWidget* theObjectBrowser) {} - - /// Creates a new operation - /// \param theCmdId the operation name - virtual ModuleBase_Operation* createOperation(const std::string& theCmdId); - - /// Create specific for the module presentation - /// \param theResult an object for presentation - /// \return created presentation or NULL(default value) - virtual Handle_AIS_InteractiveObject createPresentation( - const std::shared_ptr& theResult); - - //! Returns data object by AIS - virtual ObjectPtr findPresentedObject(const AISObjectPtr& theAIS) const = 0; - - //! Returns true if the presentation can be shown in shading mode - //! \param theAIS presentation to be checked - //! \return boolean value - virtual bool canBeShaded(Handle(AIS_InteractiveObject) theAIS) const; - - /// Update state of pop-up menu items in object browser - /// \param theStdActions - a map of standard actions - virtual void updateObjectBrowserMenu(const QMap& theStdActions) {} - - /// Update state of pop-up menu items in viewer - /// \param theStdActions - a map of standard actions - virtual void updateViewerMenu(const QMap& theStdActions) {} - - /// Returns true if the action should be always enabled - /// \param theActionId an action index: Accept or Accept All - /// \return boolean value - virtual bool isActionEnableStateFixed(const int theActionId) const { return false; } - - //! Returns the feature error if the current state of the feature in the module is not correct - //! If the feature is correct, it returns an empty value - //! \return string value - virtual QString getFeatureError(const FeaturePtr& theFeature); - - /// Returns list of granted operation indices - virtual void grantedOperationIds(ModuleBase_Operation* theOperation, QStringList& theIds) const; - - /// Connects or disconnects to the value changed signal of the property panel widgets - /// \param theWidget a property contol widget - /// \param isToConnect a boolean value whether connect or disconnect - virtual void connectToPropertyPanel(ModuleBase_ModelWidget* theWidget, const bool isToConnect) {}; - - /// Validates the operation to change the "Apply" button state. - /// \param thePreviousState the previous state of the widget - virtual void widgetStateChanged(int thePreviousState) {}; - - /// Returns true if the event is processed. - /// \param thePreviousAttributeID an index of the previous active attribute - virtual bool processEnter(const std::string& thePreviousAttributeID) { return false; }; - - /// Performs some GUI actions before an operation transaction is stopped - /// Default realization is empty - virtual void beforeOperationStopped(ModuleBase_Operation* theOperation) {}; - - /// Finds a shape by attribute if it is possible - /// \param theAttribute an attribute - /// \return a geom shape - virtual GeomShapePtr findShape(const AttributePtr& theAttribute) = 0; - - /// Finds an attribute by geom shape if it is possible - /// \param theObject an object of the attribute - /// \param theGeomShape a geom shape - /// \return theAttribute - virtual AttributePtr findAttribute(const ObjectPtr& theObject, - const GeomShapePtr& theGeomShape) = 0; - - /// Returns XML information by the feature index - /// \param theFeatureId a feature id - /// \param theXmlCfg XML configuration - /// \param theDescription feature description - void getXMLRepresentation(const std::string& theFeatureId, std::string& theXmlCfg, - std::string& theDescription); - -signals: - /// Signal which is emitted when operation is launched - void operationLaunched(); - - /// Segnal emitted when an operation is resumed - /// \param theOp a resumed operation - void resumed(ModuleBase_Operation* theOp); - -public slots: - /// Called on call of command corresponded to a feature - virtual void onFeatureTriggered(); - - /// Slot called on object display - /// \param theObject a data object - /// \param theAIS a presentation object - virtual void onObjectDisplayed(ObjectPtr theObject, AISObjectPtr theAIS) {} - - /// Slot called on before object erase - /// \param theObject a data object - /// \param theAIS a presentation object - virtual void onBeforeObjectErase(ObjectPtr theObject, AISObjectPtr theAIS) {} - -protected slots: - /// Called on selection changed event - virtual void onSelectionChanged() {} - -protected: - /// Register validators for this module - virtual void registerValidators() {} - - /// Register selection filters for this module - virtual void registerFilters() {} - - /// Register properties of this module - virtual void registerProperties() {} - - /// Returns new instance of operation object (used in createOperation for customization) - virtual ModuleBase_Operation* getNewOperation(const std::string& theFeatureId); - -protected: - /// Reference to workshop - ModuleBase_IWorkshop* myWorkshop; - - /// Map of features in XML - std::map myFeaturesInFiles; -}; - - - -//! This function must return a new module instance. -extern "C" { -typedef ModuleBase_IModule* (*CREATE_FUNC)(ModuleBase_IWorkshop*); -} - -#define CREATE_MODULE "createModule" - -#endif //ModuleBase_IModule + // Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +#ifndef ModuleBase_IModule_H +#define ModuleBase_IModule_H + +#include "ModuleBase.h" +#include "ModuleBase_IWorkshop.h" + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +class QAction; +class QMouseEvent; +class QKeyEvent; +class QMenu; +class Config_WidgetAPI; +class ModuleBase_ModelWidget; +class ModuleBase_Operation; +class ModuleBase_IWorkshop; +class ModelAPI_Result; + +class Handle_AIS_InteractiveObject; + +/** + * \ingroup GUI + * Interface to a module + */ +class MODULEBASE_EXPORT ModuleBase_IModule : public QObject +{ + Q_OBJECT + public: + /// enumeration to know which objects should be customized + enum ModuleBase_CustomizeFlag { + CustomizeArguments = 0, /// references of other objects referenced to the current feature + CustomizeResults, /// results of the current feature + CustomizeHighlightedObjects /// highlighted objects of the active widget + }; + + /// Constructor + /// \param theParent instance of workshop interface + ModuleBase_IModule(ModuleBase_IWorkshop* theParent); + + virtual ~ModuleBase_IModule() {} + + /// Add default selection filters of the module to the current viewer + virtual void activateSelectionFilters() {}; + + /// Remove default selection filters of the module from the current viewer + virtual void deactivateSelectionFilters() {}; + + /// Stores the current selection + virtual void storeSelection() {}; + + /// Restores the current selection + virtual void restoreSelection() {}; + + /// Reads description of features from XML file + virtual void createFeatures(); + + /// Called on creation of menu item in desktop + virtual void actionCreated(QAction*); + + /// Launching of a edit operation on the feature + /// \param theFeature feature for editing + virtual void editFeature(FeaturePtr theFeature); + + /// Returns true if the operation can be committed. Result in default implementation is true. + /// \return boolean value + virtual bool canCommitOperation() const { return true; } + + /// Creates an operation and send it to loop + /// \param theCmdId the operation name + virtual void launchOperation(const QString& theCmdId); + + /// Executes feature as a modal dialog box + /// \param theCmdId the operation name + virtual void launchModal(const QString& theCmdId); + + /// Realizes some functionality by an operation start + /// \param theOperation a started operation + virtual void operationStarted(ModuleBase_Operation* theOperation) {} + + /// Realizes some functionality by an operation resume + /// By default it emits operationResumed signal + /// \param theOperation a resumed operation + virtual void operationResumed(ModuleBase_Operation* theOperation); + + /// Realizes some functionality by an operation stop + virtual void operationStopped(ModuleBase_Operation* theOperation) {} + + /// Realizes some functionality by an operation commit + virtual void operationCommitted(ModuleBase_Operation* theOperation) {} + + /// Realizes some functionality by an operation abort + virtual void operationAborted(ModuleBase_Operation* theOperation) {} + + /// Realizes some functionality by an operation start + virtual ModuleBase_Operation* currentOperation() const = 0; + + /// Add menu items for viewer into the actions map + /// \param theStdActions a map of standard actions + /// \param theParent a parent widget + /// \param theMenuActions map of action/menu for the desirable index in the viewer menu + /// \return true if items are added and there is no necessity to provide standard menu + virtual bool addViewerMenu(const QMap& theStdActions, + QWidget* theParent, + QMap& theMenuActions) const + { return false; } + + /// Add menu items for object browser into the given menu + /// \param theMenu a popup menu to be shown in the object browser + virtual void addObjectBrowserMenu(QMenu* theMenu) const {}; + + /// Creates custom widgets for property panel + /// \param theType a type of widget + /// \param theParent the parent object + /// \param theWidgetApi the widget configuration. The attribute of the model widget is obtained from + virtual ModuleBase_ModelWidget* createWidgetByType(const std::string& theType, QWidget* theParent, + Config_WidgetAPI* theWidgetApi) + { + return 0; + } + + /// Returns the active widget, by default it is the property panel active widget + virtual ModuleBase_ModelWidget* activeWidget() const = 0; + + /// Returns current workshop + ModuleBase_IWorkshop* workshop() const { return myWorkshop; } + + /// Call back forlast tuning of property panel before operation performance + /// It is called as on clearing of property panel as on filling with new widgets + virtual void propertyPanelDefined(ModuleBase_Operation* theOperation) {} + + /// Have an opportunity to create widgets for the current operation instead of standard creation in workshop + /// \param theOperation a started operation + /// \param theWidgets a list of created widgets + /// \return boolean result, false by default + virtual bool createWidgets(ModuleBase_Operation* theOperation, + QList& theWidgets) const { return false; } + + //! Returns True if there are available Undos and there is not an active operation + virtual bool canUndo() const; + + //! Returns True if there are available Redos and there is not an active operation + virtual bool canRedo() const; + + /// Returns true if the action can be applyed to the object + /// \param theObject a checked object + /// \param theActionId an identifier of action, to be found in the menu manager like "DELETE_CMD" + /// \return the a boolean result + virtual bool canApplyAction(const ObjectPtr& theObject, const QString& theActionId) const = 0; + + /// Returns True if the current operation can be committed. By default it is true. + /// \return a boolean value + //virtual bool canCommitOperation() const; + + /// Returns whether the object can be erased. The default realization returns true. + /// \param theObject a model object + virtual bool canEraseObject(const ObjectPtr& theObject) const; + + /// Returns whether the object can be displayed. The default realization returns true. + /// \param theObject a model object + virtual bool canDisplayObject(const ObjectPtr& theObject) const; + + /// Make some functionality after the objects are hidden in viewer + /// \param theObjects a list of hidden objects + //virtual void processHiddenObject(const std::list& theObjects) {}; + + /// Returns true if selection for the object can be activate. + /// By default a result or feature of the current operation can not be activated + /// \param theObject a model object + virtual bool canActivateSelection(const ObjectPtr& theObject) const; + + /// Reacts to the delete action in module + /// \returns true if the action is processed + virtual bool deleteObjects() { return false; }; + + /// Performs functionality on closing document + virtual void closeDocument() = 0; + + /// Clears specific presentations in the viewer + virtual void clearViewer() = 0; + + /// Returns a list of modes, where the AIS objects should be activated + /// \param theModes a list of modes + virtual void activeSelectionModes(QIntList& theModes) {} + + /// Appends specific selection modes for the module to the list of types + /// \param theTypes a selection modes to be extended + virtual void customSubShapesSelectionModes(QIntList& theTypes) {} + + /// Return true if the custom presentation is activated + /// \param theFlag a flag of level of customization, which means that only part of sub-elements + /// \return boolean value + virtual bool isCustomPrsActivated(const ModuleBase_CustomizeFlag& theFlag) const { return false; }; + + /// Activate custom presentation for the object. Default realization is empty. + /// \param theFeature a feature instance + /// \param theFlag a flag of level of customization, which means that only part of sub-elements + /// \param theUpdateViewer the parameter whether the viewer should be update immediately + virtual void activateCustomPrs(const FeaturePtr& theFeature, + const ModuleBase_CustomizeFlag& theFlag, + const bool theUpdateViewer) {} + + /// Deactivate custom presentation for the object. Default realization is empty. + /// \param theFlag a flag of level of customization, which means that only part of sub-elements + /// \param theUpdateViewer the parameter whether the viewer should be update immediately + virtual void deactivateCustomPrs(const ModuleBase_CustomizeFlag& theFlag, + const bool theUpdateViewer) {} + + /// Modifies the given presentation in the custom way. + virtual bool customisePresentation(std::shared_ptr theResult, AISObjectPtr thePrs, + GeomCustomPrsPtr theCustomPrs) { return false; }; + + /// Update the object presentable properties such as color, lines width and other + /// If the object is result with the color attribute value set, it is used, + /// otherwise the customize is applyed to the object's feature if it is a custom prs + /// \param theObject an object instance + /// \param theFlag a flag of level of customization, which means that only part of sub-elements + /// should be updated(e.g. only highlighted elements) + /// \param theUpdateViewer the parameter whether the viewer should be update immediately + /// \returns true if the object is modified + virtual bool customizeObject(ObjectPtr theObject, const ModuleBase_CustomizeFlag& theFlag, + const bool theUpdateViewer); + + /// This method is called on object browser creation for customization of module specific features + /// \param theObjectBrowser a pinter on Object Browser widget + virtual void customizeObjectBrowser(QWidget* theObjectBrowser) {} + + /// Creates a new operation + /// \param theCmdId the operation name + virtual ModuleBase_Operation* createOperation(const std::string& theCmdId); + + /// Create specific for the module presentation + /// \param theResult an object for presentation + /// \return created presentation or NULL(default value) + virtual Handle_AIS_InteractiveObject createPresentation( + const std::shared_ptr& theResult); + + //! Returns data object by AIS + virtual ObjectPtr findPresentedObject(const AISObjectPtr& theAIS) const = 0; + + //! Returns true if the presentation can be shown in shading mode + //! \param theAIS presentation to be checked + //! \return boolean value + virtual bool canBeShaded(Handle(AIS_InteractiveObject) theAIS) const; + + /// Update state of pop-up menu items in object browser + /// \param theStdActions - a map of standard actions + virtual void updateObjectBrowserMenu(const QMap& theStdActions) {} + + /// Update state of pop-up menu items in viewer + /// \param theStdActions - a map of standard actions + virtual void updateViewerMenu(const QMap& theStdActions) {} + + /// Returns true if the action should be always enabled + /// \param theActionId an action index: Accept or Accept All + /// \return boolean value + virtual bool isActionEnableStateFixed(const int theActionId) const { return false; } + + //! Returns the feature error if the current state of the feature in the module is not correct + //! If the feature is correct, it returns an empty value + //! \return string value + virtual QString getFeatureError(const FeaturePtr& theFeature); + + /// Returns list of granted operation indices + virtual void grantedOperationIds(ModuleBase_Operation* theOperation, QStringList& theIds) const; + + /// Connects or disconnects to the value changed signal of the property panel widgets + /// \param theWidget a property contol widget + /// \param isToConnect a boolean value whether connect or disconnect + virtual void connectToPropertyPanel(ModuleBase_ModelWidget* theWidget, const bool isToConnect) {}; + + /// Validates the operation to change the "Apply" button state. + /// \param thePreviousState the previous state of the widget + virtual void widgetStateChanged(int thePreviousState) {}; + + /// Returns true if the event is processed. + /// \param thePreviousAttributeID an index of the previous active attribute + virtual bool processEnter(const std::string& thePreviousAttributeID) { return false; }; + + /// Performs some GUI actions before an operation transaction is stopped + /// Default realization is empty + virtual void beforeOperationStopped(ModuleBase_Operation* theOperation) {}; + + /// Finds a shape by attribute if it is possible + /// \param theAttribute an attribute + /// \return a geom shape + virtual GeomShapePtr findShape(const AttributePtr& theAttribute) = 0; + + /// Finds an attribute by geom shape if it is possible + /// \param theObject an object of the attribute + /// \param theGeomShape a geom shape + /// \return theAttribute + virtual AttributePtr findAttribute(const ObjectPtr& theObject, + const GeomShapePtr& theGeomShape) = 0; + + /// Returns XML information by the feature index + /// \param theFeatureId a feature id + /// \param theXmlCfg XML configuration + /// \param theDescription feature description + void getXMLRepresentation(const std::string& theFeatureId, std::string& theXmlCfg, + std::string& theDescription); + +signals: + /// Signal which is emitted when operation is launched + void operationLaunched(); + + /// Segnal emitted when an operation is resumed + /// \param theOp a resumed operation + void resumed(ModuleBase_Operation* theOp); + +public slots: + /// Called on call of command corresponded to a feature + virtual void onFeatureTriggered(); + + /// Slot called on object display + /// \param theObject a data object + /// \param theAIS a presentation object + virtual void onObjectDisplayed(ObjectPtr theObject, AISObjectPtr theAIS) {} + + /// Slot called on before object erase + /// \param theObject a data object + /// \param theAIS a presentation object + virtual void onBeforeObjectErase(ObjectPtr theObject, AISObjectPtr theAIS) {} + +protected slots: + /// Called on selection changed event + virtual void onSelectionChanged() {} + +protected: + /// Register validators for this module + virtual void registerValidators() {} + + /// Register selection filters for this module + virtual void registerFilters() {} + + /// Register properties of this module + virtual void registerProperties() {} + + /// Returns new instance of operation object (used in createOperation for customization) + virtual ModuleBase_Operation* getNewOperation(const std::string& theFeatureId); + +protected: + /// Reference to workshop + ModuleBase_IWorkshop* myWorkshop; + + /// Map of features in XML + std::map myFeaturesInFiles; +}; + + + +//! This function must return a new module instance. +extern "C" { +typedef ModuleBase_IModule* (*CREATE_FUNC)(ModuleBase_IWorkshop*); +} + +#define CREATE_MODULE "createModule" + +#endif //ModuleBase_IModule diff --git a/src/ModuleBase/ModuleBase_ModelWidget.cpp b/src/ModuleBase/ModuleBase_ModelWidget.cpp index 97abfaec8..66d1c8c96 100644 --- a/src/ModuleBase/ModuleBase_ModelWidget.cpp +++ b/src/ModuleBase/ModuleBase_ModelWidget.cpp @@ -1,452 +1,452 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: ModuleBase_ModelWidget.cpp -// Created: 25 Apr 2014 -// Author: Natalia ERMOLAEVA - -#include "ModuleBase_ModelWidget.h" -#include "ModuleBase_ViewerPrs.h" -#include "ModuleBase_Tools.h" -#include "ModuleBase_WidgetValidator.h" - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -//#define DEBUG_VALUE_STATE - -//#define DEBUG_WIDGET_INSTANCE -//#define DEBUG_ENABLE_SKETCH_INPUT_FIELDS - -ModuleBase_ModelWidget::ModuleBase_ModelWidget(QWidget* theParent, - const Config_WidgetAPI* theData) - : QWidget(theParent), - myIsEditing(false), - myState(Stored), - myIsValueStateBlocked(false), - myFlushUpdateBlocked(false), - myWidgetValidator(0) -{ -#ifdef DEBUG_WIDGET_INSTANCE - qDebug("ModuleBase_ModelWidget::ModuleBase_ModelWidget"); -#endif - - myIsInternal = theData->getBooleanAttribute(ATTR_INTERNAL, false); - - myDefaultValue = theData->getProperty(ATTR_DEFAULT); - myUseReset = theData->getBooleanAttribute(ATTR_USE_RESET, true); - myIsComputedDefault = theData->getProperty(ATTR_DEFAULT) == DOUBLE_WDG_DEFAULT_COMPUTED; - myAttributeID = theData ? theData->widgetId() : ""; - myIsObligatory = theData->getBooleanAttribute(ATTR_OBLIGATORY, true); - - myIsValueEnabled = On; // not defined or "true" - std::string anEnableValue = theData->getProperty(DOUBLE_WDG_ENABLE_VALUE); - if (anEnableValue == "false") - myIsValueEnabled = Off; - if (anEnableValue == DOUBLE_WDG_ENABLE_VALUE_BY_PREFERENCES) - myIsValueEnabled = DefinedInPreferences; - - connect(this, SIGNAL(valuesChanged()), this, SLOT(onWidgetValuesChanged())); - connect(this, SIGNAL(valuesModified()), this, SLOT(onWidgetValuesModified())); -} - -ModuleBase_ModelWidget::~ModuleBase_ModelWidget() -{ -#ifdef DEBUG_WIDGET_INSTANCE - qDebug("ModuleBase_ModelWidget::~ModuleBase_ModelWidget"); -#endif -} - -bool ModuleBase_ModelWidget::reset() -{ - bool aResult = resetCustom(); - if (aResult) - setValueState(Reset); - - return aResult; -} - -bool ModuleBase_ModelWidget::isInitialized(ObjectPtr theObject) const -{ - return theObject->data()->attribute(attributeID())->isInitialized(); -} - -bool ModuleBase_ModelWidget::isValueEnabled() const -{ - bool anEnabled = true; - if (myIsValueEnabled == DefinedInPreferences) { -#ifdef DEBUG_ENABLE_SKETCH_INPUT_FIELDS - bool aCanDisable = false; -#else - bool aCanDisable = true;//Config_PropManager::boolean(SKETCH_TAB_NAME, "disable_input_fields", "true"); -#endif - if (aCanDisable) - anEnabled = false; - } - else if (myIsValueEnabled == Off) - anEnabled = false; - return anEnabled; -} - -void ModuleBase_ModelWidget::processValueState() -{ - if (myState == ModifiedInPP || myState == ModifiedInViewer) - storeValue(); -} - -QString ModuleBase_ModelWidget::getValueStateError() const -{ - QString anError = ""; - - ModuleBase_ModelWidget::ValueState aState = getValueState(); - if (aState != ModuleBase_ModelWidget::Stored) { - AttributePtr anAttr = feature()->attribute(attributeID()); - if (anAttr.get()) { - QString anAttributeName = anAttr->id().c_str(); - switch (aState) { - case ModuleBase_ModelWidget::ModifiedInViewer: - anError = "Attribute \"" + anAttributeName + - "\" is locked by modification value in the viewer."; - break; - case ModuleBase_ModelWidget::Reset: - anError = "Attribute \"" + anAttributeName + "\" is not initialized."; - break; - case ModuleBase_ModelWidget::ModifiedInPP: // Apply should be enabled in this mode - default: - break; - } - } - } - return anError; -} - -QString ModuleBase_ModelWidget::getError(const bool theValueStateChecked) const -{ - QString anError; - - if (!feature().get()) - return anError; - - std::string anAttributeID = attributeID(); - AttributePtr anAttribute = feature()->attribute(anAttributeID); - if (!anAttribute.get()) - return anError; - - std::string aValidatorID; - Events_InfoMessage anErrorMsg; - - static ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators(); - if (!aValidators->validate(anAttribute, aValidatorID, anErrorMsg)) { - if (anErrorMsg.empty()) - anErrorMsg = "unknown error."; - anErrorMsg = anAttributeID + " - " + aValidatorID + ": " + anErrorMsg.messageString(); - } - - if (!anErrorMsg.empty()) { - std::string aStr = Config_Translator::translate(anErrorMsg); - std::string aCodec = Config_Translator::codec(anErrorMsg.context()); - anError = QTextCodec::codecForName(aCodec.c_str())->toUnicode(aStr.c_str()); - } - - if (anError.isEmpty() && theValueStateChecked) - anError = getValueStateError(); - - anError = translateString(anError); - return anError; -} - - -QString ModuleBase_ModelWidget::translateString(const QString& theMsg) const -{ - if (!theMsg.isEmpty()) { - std::string aContext = feature()->getKind(); - std::string aStr = Config_Translator::translate(aContext, theMsg.toStdString().c_str()); - std::string aCodec = Config_Translator::codec(aContext); - return QTextCodec::codecForName(aCodec.c_str())->toUnicode(aStr.c_str()); - } - return theMsg; -} - - -void ModuleBase_ModelWidget::enableFocusProcessing() -{ - QList aMyControls = getControls(); - foreach(QWidget* eachControl, aMyControls) { - eachControl->setFocusPolicy(Qt::StrongFocus); - eachControl->installEventFilter(this); - } -} - -void ModuleBase_ModelWidget::setHighlighted(bool isHighlighted) -{ - QList aWidgetList = getControls(); - foreach(QWidget* aWidget, aWidgetList) { - QLabel* aLabel = qobject_cast(aWidget); - // We won't set the effect to QLabels - it looks ugly - if(aLabel) continue; - // If effect is the installed on a different widget, setGraphicsEffect() will - // remove the effect from the widget and install it on this widget. - // That's why we create a new effect for each widget - ModuleBase_Tools::setShadowEffect(aWidget, isHighlighted); - } -} - -void ModuleBase_ModelWidget::setFeature(const FeaturePtr& theFeature, const bool theToStoreValue, - const bool isUpdateFlushed) -{ - /// it is possible to give this flag as parameter in storeValue/storeCustomValue - /// after debug, it may be corrected - myFlushUpdateBlocked = !isUpdateFlushed; - myFeature = theFeature; - if (theToStoreValue) { - /// it is possible that the attribute is filled before the operation is started, - /// e.g. by reentrant operation case some attributes are filled by values of - /// feature of previous operation, we should not lost them here - if (!theFeature->data()->attribute(attributeID())->isInitialized()) - storeValue(); - } - myFlushUpdateBlocked = false; -} - -bool ModuleBase_ModelWidget::focusTo() -{ -#ifdef DEBUG_WIDGET_INSTANCE - qDebug("ModuleBase_ModelWidget::focusTo"); -#endif - QList aControls = getControls(); - QList::const_iterator anIt = aControls.begin(), aLast = aControls.end(); - bool isFocusAccepted = false; - for (; anIt != aLast && !isFocusAccepted; anIt++) { - QWidget* aWidget = *anIt; - if (aWidget && aWidget->focusPolicy() != Qt::NoFocus) { - ModuleBase_Tools::setFocus(aWidget, "ModuleBase_ModelWidget::focusTo()"); - isFocusAccepted = true; - } - } - return isFocusAccepted; -} - -void ModuleBase_ModelWidget::activate() -{ -#ifdef DEBUG_WIDGET_INSTANCE - qDebug("ModuleBase_ModelWidget::activate"); -#endif - // the control value is stored to the mode by the focus in on the widget - // we need the value is initialized in order to enable the apply button in the property panel. - // It should happens in the creation mode only because all fields are filled in the edition mode - if (!isEditingMode()) { - AttributePtr anAttribute = myFeature->data()->attribute(myAttributeID); - if (anAttribute.get() != NULL && !anAttribute->isInitialized()) - initializeValueByActivate(); - } - - if (myWidgetValidator) - myWidgetValidator->activateFilters(true); - - activateCustom(); -} - -void ModuleBase_ModelWidget::deactivate() -{ -#ifdef DEBUG_WIDGET_INSTANCE - qDebug("ModuleBase_ModelWidget::deactivate"); -#endif - myIsValueStateBlocked = false; - myState = Stored; - if (myWidgetValidator) - myWidgetValidator->activateFilters(false); -} - -void ModuleBase_ModelWidget::initializeValueByActivate() -{ - if (isComputedDefault()) { - if (myFeature->compute(myAttributeID)) { - restoreValue(); - } - } - else { - storeValue(); - } -} - -QWidget* ModuleBase_ModelWidget::getControlAcceptingFocus(const bool isFirst) -{ - QWidget* aControl = 0; - - QList aControls = getControls(); - int aSize = aControls.size(); - - if (isFirst) { - for (int i = 0; i < aSize && !aControl; i++) { - if (aControls[i]->focusPolicy() != Qt::NoFocus) - aControl = aControls[i]; - } - } - else { - for (int i = aSize - 1; i >= 0 && !aControl; i--) { - if (aControls[i]->focusPolicy() != Qt::NoFocus) - aControl = aControls[i]; - } - } - return aControl; -} - -void ModuleBase_ModelWidget::setDefaultValue(const std::string& theValue) -{ - myDefaultValue = theValue; -} - -bool ModuleBase_ModelWidget::storeValue() -{ - setValueState(Stored); - - emit beforeValuesChanged(); - bool isDone = storeValueCustom(); - emit afterValuesChanged(); - - return isDone; -} -#ifdef DEBUG_VALUE_STATE -std::string getDebugInfo(const ModuleBase_ModelWidget::ValueState& theState) -{ - std::string anInfo; - switch (theState) { - case ModuleBase_ModelWidget::Stored: anInfo = "Stored "; break; - case ModuleBase_ModelWidget::ModifiedInPP: anInfo = "ModifiedInPP "; break; - case ModuleBase_ModelWidget::ModifiedInViewer: anInfo = "ModifiedInViewer"; break; - case ModuleBase_ModelWidget::Reset: anInfo = "Reset "; break; - default: break; - } - return anInfo; -} - -#endif -ModuleBase_ModelWidget::ValueState ModuleBase_ModelWidget::setValueState - (const ModuleBase_ModelWidget::ValueState& theState) -{ - ValueState aState = myState; - - if (myState != theState && !myIsValueStateBlocked) { -#ifdef DEBUG_VALUE_STATE - qDebug(QString("setValueState: previous state = %1,\t new state = %2") - .arg(getDebugInfo(myState).c_str()) - .arg(getDebugInfo(theState).c_str()).toStdString().c_str()); -#endif - myState = theState; - emit valueStateChanged(aState); - } - return aState; -} - -bool ModuleBase_ModelWidget::blockValueState(const bool theBlocked) -{ - bool isBlocked = myIsValueStateBlocked; - myIsValueStateBlocked = theBlocked; - return isBlocked; -} - -bool ModuleBase_ModelWidget::restoreValue() -{ - emit beforeValuesRestored(); - bool isDone = restoreValueCustom(); - emit afterValuesRestored(); - - return isDone; -} - -void ModuleBase_ModelWidget::updateObject(ObjectPtr theObject) -{ - if (!myFlushUpdateBlocked) { -#ifdef DEBUG_WIDGET_INSTANCE - qDebug("ModuleBase_ModelWidget::updateObject"); -#endif - ModuleBase_Tools::flushUpdated(theObject); - emit objectUpdated(); - } -} - -void ModuleBase_ModelWidget::moveObject(ObjectPtr theObj) -{ - //blockUpdateViewer(true); -#ifdef DEBUG_WIDGET_INSTANCE - qDebug("ModuleBase_ModelWidget::moveObject"); -#endif - - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED); - ModelAPI_EventCreator::get()->sendUpdated(theObj, anEvent); - Events_Loop::loop()->flush(anEvent); - - //blockUpdateViewer(false); -} - -bool ModuleBase_ModelWidget::processEnter() -{ - return false; -} - -bool ModuleBase_ModelWidget::processDelete() -{ - // we consider that model objects eats delete key in order to - // do nothing by for example symbol delete in line edit or spin box - return true; -} - -bool ModuleBase_ModelWidget::eventFilter(QObject* theObject, QEvent *theEvent) -{ - QWidget* aWidget = qobject_cast(theObject); - if (theEvent->type() == QEvent::FocusIn) { - #ifdef _DEBUG - // The following two lines are for debugging purpose only - QFocusEvent* aFocusEvent = dynamic_cast(theEvent); - bool isWinFocus = aFocusEvent->reason() == Qt::ActiveWindowFocusReason; - #endif - if (getControls().contains(aWidget)) { - emit focusInWidget(this); - } - } - else if (theEvent->type() == QEvent::FocusOut) { - QFocusEvent* aFocusEvent = dynamic_cast(theEvent); - - Qt::FocusReason aReason = aFocusEvent->reason(); - bool aMouseOrKey = aReason == Qt::MouseFocusReason || - aReason == Qt::TabFocusReason || - aReason == Qt::BacktabFocusReason || - aReason == Qt::OtherFocusReason; // to process widget->setFocus() - if (aMouseOrKey && getControls().contains(aWidget)) { - if (getValueState() == ModifiedInPP) { - storeValue(); - } - } - } - // pass the event on to the parent class - - return QObject::eventFilter(theObject, theEvent); -} - -//************************************************************** -void ModuleBase_ModelWidget::onWidgetValuesChanged() -{ - storeValue(); -} - -//************************************************************** -void ModuleBase_ModelWidget::onWidgetValuesModified() -{ - setValueState(ModifiedInPP); -} +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: ModuleBase_ModelWidget.cpp +// Created: 25 Apr 2014 +// Author: Natalia ERMOLAEVA + +#include "ModuleBase_ModelWidget.h" +#include "ModuleBase_ViewerPrs.h" +#include "ModuleBase_Tools.h" +#include "ModuleBase_WidgetValidator.h" + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +//#define DEBUG_VALUE_STATE + +//#define DEBUG_WIDGET_INSTANCE +//#define DEBUG_ENABLE_SKETCH_INPUT_FIELDS + +ModuleBase_ModelWidget::ModuleBase_ModelWidget(QWidget* theParent, + const Config_WidgetAPI* theData) + : QWidget(theParent), + myIsEditing(false), + myState(Stored), + myIsValueStateBlocked(false), + myFlushUpdateBlocked(false), + myWidgetValidator(0) +{ +#ifdef DEBUG_WIDGET_INSTANCE + qDebug("ModuleBase_ModelWidget::ModuleBase_ModelWidget"); +#endif + + myIsInternal = theData->getBooleanAttribute(ATTR_INTERNAL, false); + + myDefaultValue = theData->getProperty(ATTR_DEFAULT); + myUseReset = theData->getBooleanAttribute(ATTR_USE_RESET, true); + myIsComputedDefault = theData->getProperty(ATTR_DEFAULT) == DOUBLE_WDG_DEFAULT_COMPUTED; + myAttributeID = theData ? theData->widgetId() : ""; + myIsObligatory = theData->getBooleanAttribute(ATTR_OBLIGATORY, true); + + myIsValueEnabled = On; // not defined or "true" + std::string anEnableValue = theData->getProperty(DOUBLE_WDG_ENABLE_VALUE); + if (anEnableValue == "false") + myIsValueEnabled = Off; + if (anEnableValue == DOUBLE_WDG_ENABLE_VALUE_BY_PREFERENCES) + myIsValueEnabled = DefinedInPreferences; + + connect(this, SIGNAL(valuesChanged()), this, SLOT(onWidgetValuesChanged())); + connect(this, SIGNAL(valuesModified()), this, SLOT(onWidgetValuesModified())); +} + +ModuleBase_ModelWidget::~ModuleBase_ModelWidget() +{ +#ifdef DEBUG_WIDGET_INSTANCE + qDebug("ModuleBase_ModelWidget::~ModuleBase_ModelWidget"); +#endif +} + +bool ModuleBase_ModelWidget::reset() +{ + bool aResult = resetCustom(); + if (aResult) + setValueState(Reset); + + return aResult; +} + +bool ModuleBase_ModelWidget::isInitialized(ObjectPtr theObject) const +{ + return theObject->data()->attribute(attributeID())->isInitialized(); +} + +bool ModuleBase_ModelWidget::isValueEnabled() const +{ + bool anEnabled = true; + if (myIsValueEnabled == DefinedInPreferences) { +#ifdef DEBUG_ENABLE_SKETCH_INPUT_FIELDS + bool aCanDisable = false; +#else + bool aCanDisable = true;//Config_PropManager::boolean(SKETCH_TAB_NAME, "disable_input_fields", "true"); +#endif + if (aCanDisable) + anEnabled = false; + } + else if (myIsValueEnabled == Off) + anEnabled = false; + return anEnabled; +} + +void ModuleBase_ModelWidget::processValueState() +{ + if (myState == ModifiedInPP || myState == ModifiedInViewer) + storeValue(); +} + +QString ModuleBase_ModelWidget::getValueStateError() const +{ + QString anError = ""; + + ModuleBase_ModelWidget::ValueState aState = getValueState(); + if (aState != ModuleBase_ModelWidget::Stored) { + AttributePtr anAttr = feature()->attribute(attributeID()); + if (anAttr.get()) { + QString anAttributeName = anAttr->id().c_str(); + switch (aState) { + case ModuleBase_ModelWidget::ModifiedInViewer: + anError = "Attribute \"" + anAttributeName + + "\" is locked by modification value in the viewer."; + break; + case ModuleBase_ModelWidget::Reset: + anError = "Attribute \"" + anAttributeName + "\" is not initialized."; + break; + case ModuleBase_ModelWidget::ModifiedInPP: // Apply should be enabled in this mode + default: + break; + } + } + } + return anError; +} + +QString ModuleBase_ModelWidget::getError(const bool theValueStateChecked) const +{ + QString anError; + + if (!feature().get()) + return anError; + + std::string anAttributeID = attributeID(); + AttributePtr anAttribute = feature()->attribute(anAttributeID); + if (!anAttribute.get()) + return anError; + + std::string aValidatorID; + Events_InfoMessage anErrorMsg; + + static ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators(); + if (!aValidators->validate(anAttribute, aValidatorID, anErrorMsg)) { + if (anErrorMsg.empty()) + anErrorMsg = "unknown error."; + anErrorMsg = anAttributeID + " - " + aValidatorID + ": " + anErrorMsg.messageString(); + } + + if (!anErrorMsg.empty()) { + std::string aStr = Config_Translator::translate(anErrorMsg); + std::string aCodec = Config_Translator::codec(anErrorMsg.context()); + anError = QTextCodec::codecForName(aCodec.c_str())->toUnicode(aStr.c_str()); + } + + if (anError.isEmpty() && theValueStateChecked) + anError = getValueStateError(); + + anError = translateString(anError); + return anError; +} + + +QString ModuleBase_ModelWidget::translateString(const QString& theMsg) const +{ + if (!theMsg.isEmpty()) { + std::string aContext = feature()->getKind(); + std::string aStr = Config_Translator::translate(aContext, theMsg.toStdString().c_str()); + std::string aCodec = Config_Translator::codec(aContext); + return QTextCodec::codecForName(aCodec.c_str())->toUnicode(aStr.c_str()); + } + return theMsg; +} + + +void ModuleBase_ModelWidget::enableFocusProcessing() +{ + QList aMyControls = getControls(); + foreach(QWidget* eachControl, aMyControls) { + eachControl->setFocusPolicy(Qt::StrongFocus); + eachControl->installEventFilter(this); + } +} + +void ModuleBase_ModelWidget::setHighlighted(bool isHighlighted) +{ + QList aWidgetList = getControls(); + foreach(QWidget* aWidget, aWidgetList) { + QLabel* aLabel = qobject_cast(aWidget); + // We won't set the effect to QLabels - it looks ugly + if(aLabel) continue; + // If effect is the installed on a different widget, setGraphicsEffect() will + // remove the effect from the widget and install it on this widget. + // That's why we create a new effect for each widget + ModuleBase_Tools::setShadowEffect(aWidget, isHighlighted); + } +} + +void ModuleBase_ModelWidget::setFeature(const FeaturePtr& theFeature, const bool theToStoreValue, + const bool isUpdateFlushed) +{ + /// it is possible to give this flag as parameter in storeValue/storeCustomValue + /// after debug, it may be corrected + myFlushUpdateBlocked = !isUpdateFlushed; + myFeature = theFeature; + if (theToStoreValue) { + /// it is possible that the attribute is filled before the operation is started, + /// e.g. by reentrant operation case some attributes are filled by values of + /// feature of previous operation, we should not lost them here + if (!theFeature->data()->attribute(attributeID())->isInitialized()) + storeValue(); + } + myFlushUpdateBlocked = false; +} + +bool ModuleBase_ModelWidget::focusTo() +{ +#ifdef DEBUG_WIDGET_INSTANCE + qDebug("ModuleBase_ModelWidget::focusTo"); +#endif + QList aControls = getControls(); + QList::const_iterator anIt = aControls.begin(), aLast = aControls.end(); + bool isFocusAccepted = false; + for (; anIt != aLast && !isFocusAccepted; anIt++) { + QWidget* aWidget = *anIt; + if (aWidget && aWidget->focusPolicy() != Qt::NoFocus) { + ModuleBase_Tools::setFocus(aWidget, "ModuleBase_ModelWidget::focusTo()"); + isFocusAccepted = true; + } + } + return isFocusAccepted; +} + +void ModuleBase_ModelWidget::activate() +{ +#ifdef DEBUG_WIDGET_INSTANCE + qDebug("ModuleBase_ModelWidget::activate"); +#endif + // the control value is stored to the mode by the focus in on the widget + // we need the value is initialized in order to enable the apply button in the property panel. + // It should happens in the creation mode only because all fields are filled in the edition mode + if (!isEditingMode()) { + AttributePtr anAttribute = myFeature->data()->attribute(myAttributeID); + if (anAttribute.get() != NULL && !anAttribute->isInitialized()) + initializeValueByActivate(); + } + + if (myWidgetValidator) + myWidgetValidator->activateFilters(true); + + activateCustom(); +} + +void ModuleBase_ModelWidget::deactivate() +{ +#ifdef DEBUG_WIDGET_INSTANCE + qDebug("ModuleBase_ModelWidget::deactivate"); +#endif + myIsValueStateBlocked = false; + myState = Stored; + if (myWidgetValidator) + myWidgetValidator->activateFilters(false); +} + +void ModuleBase_ModelWidget::initializeValueByActivate() +{ + if (isComputedDefault()) { + if (myFeature->compute(myAttributeID)) { + restoreValue(); + } + } + else { + storeValue(); + } +} + +QWidget* ModuleBase_ModelWidget::getControlAcceptingFocus(const bool isFirst) +{ + QWidget* aControl = 0; + + QList aControls = getControls(); + int aSize = aControls.size(); + + if (isFirst) { + for (int i = 0; i < aSize && !aControl; i++) { + if (aControls[i]->focusPolicy() != Qt::NoFocus) + aControl = aControls[i]; + } + } + else { + for (int i = aSize - 1; i >= 0 && !aControl; i--) { + if (aControls[i]->focusPolicy() != Qt::NoFocus) + aControl = aControls[i]; + } + } + return aControl; +} + +void ModuleBase_ModelWidget::setDefaultValue(const std::string& theValue) +{ + myDefaultValue = theValue; +} + +bool ModuleBase_ModelWidget::storeValue() +{ + setValueState(Stored); + + emit beforeValuesChanged(); + bool isDone = storeValueCustom(); + emit afterValuesChanged(); + + return isDone; +} +#ifdef DEBUG_VALUE_STATE +std::string getDebugInfo(const ModuleBase_ModelWidget::ValueState& theState) +{ + std::string anInfo; + switch (theState) { + case ModuleBase_ModelWidget::Stored: anInfo = "Stored "; break; + case ModuleBase_ModelWidget::ModifiedInPP: anInfo = "ModifiedInPP "; break; + case ModuleBase_ModelWidget::ModifiedInViewer: anInfo = "ModifiedInViewer"; break; + case ModuleBase_ModelWidget::Reset: anInfo = "Reset "; break; + default: break; + } + return anInfo; +} + +#endif +ModuleBase_ModelWidget::ValueState ModuleBase_ModelWidget::setValueState + (const ModuleBase_ModelWidget::ValueState& theState) +{ + ValueState aState = myState; + + if (myState != theState && !myIsValueStateBlocked) { +#ifdef DEBUG_VALUE_STATE + qDebug(QString("setValueState: previous state = %1,\t new state = %2") + .arg(getDebugInfo(myState).c_str()) + .arg(getDebugInfo(theState).c_str()).toStdString().c_str()); +#endif + myState = theState; + emit valueStateChanged(aState); + } + return aState; +} + +bool ModuleBase_ModelWidget::blockValueState(const bool theBlocked) +{ + bool isBlocked = myIsValueStateBlocked; + myIsValueStateBlocked = theBlocked; + return isBlocked; +} + +bool ModuleBase_ModelWidget::restoreValue() +{ + emit beforeValuesRestored(); + bool isDone = restoreValueCustom(); + emit afterValuesRestored(); + + return isDone; +} + +void ModuleBase_ModelWidget::updateObject(ObjectPtr theObject) +{ + if (!myFlushUpdateBlocked) { +#ifdef DEBUG_WIDGET_INSTANCE + qDebug("ModuleBase_ModelWidget::updateObject"); +#endif + ModuleBase_Tools::flushUpdated(theObject); + emit objectUpdated(); + } +} + +void ModuleBase_ModelWidget::moveObject(ObjectPtr theObj) +{ + //blockUpdateViewer(true); +#ifdef DEBUG_WIDGET_INSTANCE + qDebug("ModuleBase_ModelWidget::moveObject"); +#endif + + static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED); + ModelAPI_EventCreator::get()->sendUpdated(theObj, anEvent); + Events_Loop::loop()->flush(anEvent); + + //blockUpdateViewer(false); +} + +bool ModuleBase_ModelWidget::processEnter() +{ + return false; +} + +bool ModuleBase_ModelWidget::processDelete() +{ + // we consider that model objects eats delete key in order to + // do nothing by for example symbol delete in line edit or spin box + return true; +} + +bool ModuleBase_ModelWidget::eventFilter(QObject* theObject, QEvent *theEvent) +{ + QWidget* aWidget = qobject_cast(theObject); + if (theEvent->type() == QEvent::FocusIn) { + #ifdef _DEBUG + // The following two lines are for debugging purpose only + QFocusEvent* aFocusEvent = dynamic_cast(theEvent); + bool isWinFocus = aFocusEvent->reason() == Qt::ActiveWindowFocusReason; + #endif + if (getControls().contains(aWidget)) { + emit focusInWidget(this); + } + } + else if (theEvent->type() == QEvent::FocusOut) { + QFocusEvent* aFocusEvent = dynamic_cast(theEvent); + + Qt::FocusReason aReason = aFocusEvent->reason(); + bool aMouseOrKey = aReason == Qt::MouseFocusReason || + aReason == Qt::TabFocusReason || + aReason == Qt::BacktabFocusReason || + aReason == Qt::OtherFocusReason; // to process widget->setFocus() + if (aMouseOrKey && getControls().contains(aWidget)) { + if (getValueState() == ModifiedInPP) { + storeValue(); + } + } + } + // pass the event on to the parent class + + return QObject::eventFilter(theObject, theEvent); +} + +//************************************************************** +void ModuleBase_ModelWidget::onWidgetValuesChanged() +{ + storeValue(); +} + +//************************************************************** +void ModuleBase_ModelWidget::onWidgetValuesModified() +{ + setValueState(ModifiedInPP); +} diff --git a/src/ModuleBase/ModuleBase_OperationDescription.h b/src/ModuleBase/ModuleBase_OperationDescription.h index 7de7c3288..3fdc27b1d 100644 --- a/src/ModuleBase/ModuleBase_OperationDescription.h +++ b/src/ModuleBase/ModuleBase_OperationDescription.h @@ -1,74 +1,74 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -/* - * ModuleBase_OperationDescription.h - * - * Created on: Apr 2, 2014 - * Author: sbh - */ - -#ifndef MODULEBASE_OPERATIONDESCRIPTION_H -#define MODULEBASE_OPERATIONDESCRIPTION_H - -#include -#include - -#include -#include -#include - -#include - -//class ModuleBase_ModelWidget; - -/*! - * \class ModuleBase_OperationDescription - * \ingroup GUI - * Description of operation from XML - */ -class MODULEBASE_EXPORT ModuleBase_OperationDescription -{ - public: - /// Constructor - /// \param theId - the operation identifier - ModuleBase_OperationDescription(const QString& theId = ""); - /// Destructor - virtual ~ModuleBase_OperationDescription(); - - /// Unique name of the operation - /// \return string name of the operation. - const QString& operationId() const; - - /// Returns a short description of operation (will be - /// inserted in title of property panel) - const QString& description() const; - - /// Sets a short description of operation (will be - /// inserted in title of property panel) - void setDescription(const QString& theDescription); - - /// Returns XML representation of the operation's widget. - /// \return XML QString - const QString& xmlRepresentation() const; - - /// Sets XML representation of the operation's widget. - /// \param theXMLRepresentation - XML QString - void setXmlRepresentation(const QString& theXMLRepresentation); - - /// Returns true if there are no model widgets - /// \return the boolean value - bool hasXmlRepresentation() const; - - private: - //!< Next fields could be extracted into a subclass; - /// the operation identifier - QString myOperationId; - - /// the short description of the opertaion - QString myDescription; - - /// the xml definition - QString myXmlRepresentation; -}; - -#endif //ModuleBase_OperationDescription_H +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +/* + * ModuleBase_OperationDescription.h + * + * Created on: Apr 2, 2014 + * Author: sbh + */ + +#ifndef MODULEBASE_OPERATIONDESCRIPTION_H +#define MODULEBASE_OPERATIONDESCRIPTION_H + +#include +#include + +#include +#include +#include + +#include + +//class ModuleBase_ModelWidget; + +/*! + * \class ModuleBase_OperationDescription + * \ingroup GUI + * Description of operation from XML + */ +class MODULEBASE_EXPORT ModuleBase_OperationDescription +{ + public: + /// Constructor + /// \param theId - the operation identifier + ModuleBase_OperationDescription(const QString& theId = ""); + /// Destructor + virtual ~ModuleBase_OperationDescription(); + + /// Unique name of the operation + /// \return string name of the operation. + const QString& operationId() const; + + /// Returns a short description of operation (will be + /// inserted in title of property panel) + const QString& description() const; + + /// Sets a short description of operation (will be + /// inserted in title of property panel) + void setDescription(const QString& theDescription); + + /// Returns XML representation of the operation's widget. + /// \return XML QString + const QString& xmlRepresentation() const; + + /// Sets XML representation of the operation's widget. + /// \param theXMLRepresentation - XML QString + void setXmlRepresentation(const QString& theXMLRepresentation); + + /// Returns true if there are no model widgets + /// \return the boolean value + bool hasXmlRepresentation() const; + + private: + //!< Next fields could be extracted into a subclass; + /// the operation identifier + QString myOperationId; + + /// the short description of the opertaion + QString myDescription; + + /// the xml definition + QString myXmlRepresentation; +}; + +#endif //ModuleBase_OperationDescription_H diff --git a/src/ModuleBase/ModuleBase_WidgetConcealedObjects.cpp b/src/ModuleBase/ModuleBase_WidgetConcealedObjects.cpp index 2e7721629..0e5f4d9e6 100644 --- a/src/ModuleBase/ModuleBase_WidgetConcealedObjects.cpp +++ b/src/ModuleBase/ModuleBase_WidgetConcealedObjects.cpp @@ -1,148 +1,148 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: ModuleBase_WidgetConcealedObjects.cpp -// Created: 29 Jul 2016 -// Author: Natalia ERMOLAEVA - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include - -const int DEFAULT_NAME_COLUMN_WIDTH = 200; - -ModuleBase_WidgetConcealedObjects::ModuleBase_WidgetConcealedObjects(QWidget* theParent, - const Config_WidgetAPI* theData) -: ModuleBase_ModelWidget(theParent, theData) -{ - myBaseShapeAttribute = theData->getProperty("base_shape_attribute"); - QGridLayout* aMainLay = new QGridLayout(this); - ModuleBase_Tools::adjustMargins(aMainLay); - - myView = new QTableWidget(this); - aMainLay->addWidget(myView); - - myView->setColumnCount(2); - myView->horizontalHeader()->setVisible(false); - myView->verticalHeader()->setVisible(false); -} - -ModuleBase_WidgetConcealedObjects::~ModuleBase_WidgetConcealedObjects() -{ -} - -bool ModuleBase_WidgetConcealedObjects::storeValueCustom() -{ - if(!myFeature) - return false; - DataPtr aData = myFeature->data(); - AttributeRefListPtr anAttributeList = aData->reflist(attributeID()); - anAttributeList->clear(); - int aSize1 = anAttributeList->size(false); - for (int i = 0, aSize = myView->rowCount(); i < aSize; i++) { - QToolButton* aButton = dynamic_cast(myView->cellWidget(i, 0));; - if (aButton->isChecked()) - anAttributeList->append(myConcealedResults[i]); - } - int aSize = anAttributeList->size(false); - return true; -} - -bool ModuleBase_WidgetConcealedObjects::restoreValueCustom() -{ - FeaturePtr aBaseFeature; - ObjectPtr anObject; - if (myFeature) { - anObject = ModuleBase_Tools::getObject(myFeature->attribute(myBaseShapeAttribute)); - if (anObject.get() != NULL) - aBaseFeature = ModelAPI_Feature::feature(anObject); - } - if (myBaseFeature != aBaseFeature) { - myView->setRowCount(0); - myConcealedResults.clear(); - myBaseFeature = aBaseFeature; - if (myBaseFeature.get()) { - std::list > aResults; - ModelAPI_Tools::getConcealedResults(myBaseFeature, aResults); - std::list >::const_iterator anIt = aResults.begin(), - aLast = aResults.end(); - for (; anIt != aLast; anIt++) { - ResultPtr aResult = *anIt; - - int aRowId = myView->rowCount(); - addViewRow(aResult); - myConcealedResults[aRowId] = aResult; - } - } - } - - DataPtr aData = myFeature->data(); - AttributeRefListPtr anAttributeList = aData->reflist(attributeID()); - int aSize = anAttributeList->size(); - for (int i = 0, aSize = myView->rowCount(); i < aSize; i++) { - ResultPtr aResult = myConcealedResults[i]; - QToolButton* aButton = dynamic_cast(myView->cellWidget(i, 0)); - bool isChecked = anAttributeList->isInList(aResult); - - bool aBlocked = aButton->blockSignals(true); - aButton->setChecked(isChecked); - this->updateItemIcon(aButton); - aButton->blockSignals(aBlocked); - } - return true; -} - -QList ModuleBase_WidgetConcealedObjects::getControls() const -{ - QList result; - result << myView; - return result; -} - -void ModuleBase_WidgetConcealedObjects::addViewRow(const std::shared_ptr& theResult) -{ - int anId = myView->rowCount(); - myView->setRowCount(anId+1); - - QToolButton* aVisibilityBtn = new QToolButton(this); - connect(aVisibilityBtn, SIGNAL(toggled(bool)), this, SLOT(onItemToggled(bool))); - aVisibilityBtn->setCheckable(true); - aVisibilityBtn->setChecked(false); - updateItemIcon(aVisibilityBtn); - - myView->setCellWidget(anId, 0, aVisibilityBtn); - myView->setItem(anId, 1, new QTableWidgetItem(theResult->data()->name().c_str())); - - if (anId == 1) { - myView->setColumnWidth(0, myView->verticalHeader()->defaultSectionSize()); - myView->setColumnWidth(1, DEFAULT_NAME_COLUMN_WIDTH); - } -} - -void ModuleBase_WidgetConcealedObjects::onItemToggled(bool theState) -{ - emit valuesChanged(); - updateObject(myFeature); -} - -void ModuleBase_WidgetConcealedObjects::updateItemIcon(QToolButton* theButton) -{ - bool isChecked = theButton->isChecked(); - theButton->setIcon(isChecked ? QIcon(":icons/concealed_on.png") - : QIcon(":icons/concealed_off.png")); - theButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); -} +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: ModuleBase_WidgetConcealedObjects.cpp +// Created: 29 Jul 2016 +// Author: Natalia ERMOLAEVA + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +const int DEFAULT_NAME_COLUMN_WIDTH = 200; + +ModuleBase_WidgetConcealedObjects::ModuleBase_WidgetConcealedObjects(QWidget* theParent, + const Config_WidgetAPI* theData) +: ModuleBase_ModelWidget(theParent, theData) +{ + myBaseShapeAttribute = theData->getProperty("base_shape_attribute"); + QGridLayout* aMainLay = new QGridLayout(this); + ModuleBase_Tools::adjustMargins(aMainLay); + + myView = new QTableWidget(this); + aMainLay->addWidget(myView); + + myView->setColumnCount(2); + myView->horizontalHeader()->setVisible(false); + myView->verticalHeader()->setVisible(false); +} + +ModuleBase_WidgetConcealedObjects::~ModuleBase_WidgetConcealedObjects() +{ +} + +bool ModuleBase_WidgetConcealedObjects::storeValueCustom() +{ + if(!myFeature) + return false; + DataPtr aData = myFeature->data(); + AttributeRefListPtr anAttributeList = aData->reflist(attributeID()); + anAttributeList->clear(); + int aSize1 = anAttributeList->size(false); + for (int i = 0, aSize = myView->rowCount(); i < aSize; i++) { + QToolButton* aButton = dynamic_cast(myView->cellWidget(i, 0));; + if (aButton->isChecked()) + anAttributeList->append(myConcealedResults[i]); + } + int aSize = anAttributeList->size(false); + return true; +} + +bool ModuleBase_WidgetConcealedObjects::restoreValueCustom() +{ + FeaturePtr aBaseFeature; + ObjectPtr anObject; + if (myFeature) { + anObject = ModuleBase_Tools::getObject(myFeature->attribute(myBaseShapeAttribute)); + if (anObject.get() != NULL) + aBaseFeature = ModelAPI_Feature::feature(anObject); + } + if (myBaseFeature != aBaseFeature) { + myView->setRowCount(0); + myConcealedResults.clear(); + myBaseFeature = aBaseFeature; + if (myBaseFeature.get()) { + std::list > aResults; + ModelAPI_Tools::getConcealedResults(myBaseFeature, aResults); + std::list >::const_iterator anIt = aResults.begin(), + aLast = aResults.end(); + for (; anIt != aLast; anIt++) { + ResultPtr aResult = *anIt; + + int aRowId = myView->rowCount(); + addViewRow(aResult); + myConcealedResults[aRowId] = aResult; + } + } + } + + DataPtr aData = myFeature->data(); + AttributeRefListPtr anAttributeList = aData->reflist(attributeID()); + int aSize = anAttributeList->size(); + for (int i = 0, aSize = myView->rowCount(); i < aSize; i++) { + ResultPtr aResult = myConcealedResults[i]; + QToolButton* aButton = dynamic_cast(myView->cellWidget(i, 0)); + bool isChecked = anAttributeList->isInList(aResult); + + bool aBlocked = aButton->blockSignals(true); + aButton->setChecked(isChecked); + this->updateItemIcon(aButton); + aButton->blockSignals(aBlocked); + } + return true; +} + +QList ModuleBase_WidgetConcealedObjects::getControls() const +{ + QList result; + result << myView; + return result; +} + +void ModuleBase_WidgetConcealedObjects::addViewRow(const std::shared_ptr& theResult) +{ + int anId = myView->rowCount(); + myView->setRowCount(anId+1); + + QToolButton* aVisibilityBtn = new QToolButton(this); + connect(aVisibilityBtn, SIGNAL(toggled(bool)), this, SLOT(onItemToggled(bool))); + aVisibilityBtn->setCheckable(true); + aVisibilityBtn->setChecked(false); + updateItemIcon(aVisibilityBtn); + + myView->setCellWidget(anId, 0, aVisibilityBtn); + myView->setItem(anId, 1, new QTableWidgetItem(theResult->data()->name().c_str())); + + if (anId == 1) { + myView->setColumnWidth(0, myView->verticalHeader()->defaultSectionSize()); + myView->setColumnWidth(1, DEFAULT_NAME_COLUMN_WIDTH); + } +} + +void ModuleBase_WidgetConcealedObjects::onItemToggled(bool theState) +{ + emit valuesChanged(); + updateObject(myFeature); +} + +void ModuleBase_WidgetConcealedObjects::updateItemIcon(QToolButton* theButton) +{ + bool isChecked = theButton->isChecked(); + theButton->setIcon(isChecked ? QIcon(":icons/concealed_on.png") + : QIcon(":icons/concealed_off.png")); + theButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); +} diff --git a/src/ModuleBase/ModuleBase_WidgetConcealedObjects.h b/src/ModuleBase/ModuleBase_WidgetConcealedObjects.h index 5a42a775c..9cd8f092a 100644 --- a/src/ModuleBase/ModuleBase_WidgetConcealedObjects.h +++ b/src/ModuleBase/ModuleBase_WidgetConcealedObjects.h @@ -1,76 +1,76 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: ModuleBase_WidgetConcealedObjects.h -// Created: 29 Jul 2016 -// Author: Natalia ERMOLAEVA - -#ifndef MODULEBASE_WIDGETCONCEALEDOBJECTS_H_ -#define MODULEBASE_WIDGETCONCEALEDOBJECTS_H_ - -#include -#include - -#include -#include -#include - -class ModelAPI_Object; - -class QWidget; -class QTableWidget; -class QToolButton; - -/** -* \ingroup GUI -* Implementation of model widget for table of concealed objects. -*/ -class MODULEBASE_EXPORT ModuleBase_WidgetConcealedObjects : public ModuleBase_ModelWidget -{ - Q_OBJECT - public: - /// Constructor - /// \param theParent the parent object - /// \param theData the widget configuration. - ModuleBase_WidgetConcealedObjects(QWidget* theParent, - const Config_WidgetAPI* theData); - virtual ~ModuleBase_WidgetConcealedObjects(); - - /// Redefinition of virtual method - virtual QList getControls() const; - - /// The widget can not accept focus - virtual bool canAcceptFocus() const { return false; }; - -protected: - /// Saves the internal parameters to the given feature - /// \return True in success - virtual bool storeValueCustom(); - - /// Redefinition of virtual method - virtual bool restoreValueCustom(); - -private: - /// Creates a row in view - /// \param theResult a result for the row - void addViewRow(const std::shared_ptr& theResult); - -private slots: - /// Processes the display button click in the view. - /// \param theState a new state - void onItemToggled(bool theState); - -private: - /// Updates icon of button - /// \param theButton a button of the table - void updateItemIcon(QToolButton* theButton); - -private: - std::string myBaseShapeAttribute; ///< attribute of the base object - QTableWidget* myView; ///< table view of visibility states - - std::shared_ptr myBaseFeature; ///< backup of feature of filling the table view - /// backup of visualized in the view concealed objects, stored to avoid table rebuild by restore - std::map > myConcealedResults; -}; - -#endif /* MODULEBASE_WIDGETCONCEALEDOBJECTS_H_ */ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: ModuleBase_WidgetConcealedObjects.h +// Created: 29 Jul 2016 +// Author: Natalia ERMOLAEVA + +#ifndef MODULEBASE_WIDGETCONCEALEDOBJECTS_H_ +#define MODULEBASE_WIDGETCONCEALEDOBJECTS_H_ + +#include +#include + +#include +#include +#include + +class ModelAPI_Object; + +class QWidget; +class QTableWidget; +class QToolButton; + +/** +* \ingroup GUI +* Implementation of model widget for table of concealed objects. +*/ +class MODULEBASE_EXPORT ModuleBase_WidgetConcealedObjects : public ModuleBase_ModelWidget +{ + Q_OBJECT + public: + /// Constructor + /// \param theParent the parent object + /// \param theData the widget configuration. + ModuleBase_WidgetConcealedObjects(QWidget* theParent, + const Config_WidgetAPI* theData); + virtual ~ModuleBase_WidgetConcealedObjects(); + + /// Redefinition of virtual method + virtual QList getControls() const; + + /// The widget can not accept focus + virtual bool canAcceptFocus() const { return false; }; + +protected: + /// Saves the internal parameters to the given feature + /// \return True in success + virtual bool storeValueCustom(); + + /// Redefinition of virtual method + virtual bool restoreValueCustom(); + +private: + /// Creates a row in view + /// \param theResult a result for the row + void addViewRow(const std::shared_ptr& theResult); + +private slots: + /// Processes the display button click in the view. + /// \param theState a new state + void onItemToggled(bool theState); + +private: + /// Updates icon of button + /// \param theButton a button of the table + void updateItemIcon(QToolButton* theButton); + +private: + std::string myBaseShapeAttribute; ///< attribute of the base object + QTableWidget* myView; ///< table view of visibility states + + std::shared_ptr myBaseFeature; ///< backup of feature of filling the table view + /// backup of visualized in the view concealed objects, stored to avoid table rebuild by restore + std::map > myConcealedResults; +}; + +#endif /* MODULEBASE_WIDGETCONCEALEDOBJECTS_H_ */ diff --git a/src/ModuleBase/ModuleBase_WidgetFactory.cpp b/src/ModuleBase/ModuleBase_WidgetFactory.cpp index c0045ec1d..2812d1714 100644 --- a/src/ModuleBase/ModuleBase_WidgetFactory.cpp +++ b/src/ModuleBase/ModuleBase_WidgetFactory.cpp @@ -1,341 +1,341 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -/* - * ModuleBase_WidgetFactory.cpp - * - * Created on: Apr 3, 2014 - * Author: sbh - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _DEBUG -#include -#endif - -#include -#include - -ModuleBase_WidgetFactory::ModuleBase_WidgetFactory(const std::string& theXmlRepresentation, - ModuleBase_IWorkshop* theWorkshop) - : myWorkshop(theWorkshop) -{ - myWidgetApi = new Config_WidgetAPI(theXmlRepresentation); -} - -ModuleBase_WidgetFactory::~ModuleBase_WidgetFactory() -{ - delete myWidgetApi; -} - -void ModuleBase_WidgetFactory::createWidget(ModuleBase_PageBase* thePage, bool alignToTop) -{ - std::string aWType = myWidgetApi->widgetType(); - if (aWType == NODE_FEATURE) { - // if XML definition of the feature contains the next key, the widgets should not be created, - // but a specific panel should be made. However, to provide persistent of the panel values, - // we need to get into the panel the feature of the operation. As a result this panel should - // be created after the feature creating(create operation). The method setPanel() of this - // class is used for this. Here, we just return to avoid the widgets creation. - std::string aPanelName = myWidgetApi->getProperty(PROPERTY_PANEL_ID); - if (!aPanelName.empty()) - return; - } - - if (!myWidgetApi->toChildWidget()) - return; - - do { //Iterate over each node - std::string aWdgType = myWidgetApi->widgetType(); - // Create PageGroup TODO: extract - if (myWidgetApi->isGroupBoxWidget() || - ModuleBase_WidgetCreatorFactory::get()->hasPageWidget(aWdgType)) { - - //if current widget is groupbox (container) process it's children recursively - ModuleBase_PageBase* aPage = createPageByType(aWdgType, thePage->pageWidget()); - - createWidget(aPage); - thePage->addPageWidget(aPage); - } else { - // Create a ModelWidget - ModuleBase_ModelWidget* aWidget = createWidgetByType(aWdgType, thePage->pageWidget()); - if (aWidget) { - if (!myWidgetApi->getBooleanAttribute(ATTR_INTERNAL, false)) { - thePage->addModelWidget(aWidget); - } else { - aWidget->setVisible(false); - } - } - // Create PagedContainer TODO: extract - if (myWidgetApi->isPagedWidget()) { - //If current widget is toolbox or switch-casebox then fetch all - //it's pages recursively and setup into the widget. - if (myWidgetApi->toChildWidget()) { - do { - QString aPageName = qs(myWidgetApi->getProperty(CONTAINER_PAGE_NAME)); - QString aCaseId = qs(myWidgetApi->getProperty(_ID)); - ModuleBase_PageBase* aPage = new ModuleBase_PageWidget(aWidget); - createWidget(aPage); - if (aWdgType == WDG_SWITCH || aWdgType == WDG_TOOLBOX) { - ModuleBase_PagedContainer* aContainer = qobject_cast(aWidget); - - QString anIconPath = qs( myWidgetApi->getProperty( CONTAINER_PAGE_ICON ) ); - QPixmap anIcon = ModuleBase_IconFactory::loadPixmap( anIconPath ); - aContainer->addPage( aPage, aPageName, aCaseId, anIcon ); - } - } while (myWidgetApi->toNextWidget()); - } - } - } - } while (myWidgetApi->toNextWidget()); - - if (alignToTop) - thePage->alignToTop(); -} - -void ModuleBase_WidgetFactory::createPanel(ModuleBase_PageBase* thePage, - const FeaturePtr& theFeature) -{ - std::string aPanelName = myWidgetApi->getProperty(PROPERTY_PANEL_ID); - if (!aPanelName.empty() && ModuleBase_WidgetCreatorFactory::get()->hasPanelWidget(aPanelName)) { - QWidget* aPanel = ModuleBase_WidgetCreatorFactory::get()->createPanelByType(aPanelName, - thePage->pageWidget(), theFeature); - thePage->addWidget(aPanel); - thePage->alignToTop(); - } -} - -void ModuleBase_WidgetFactory::createWidget(ModuleBase_PageBase* thePage, - const std::string& theWidgetId) -{ - bool aFound = false; - moveToWidgetId(theWidgetId, aFound); - if (aFound) { - std::string aWdgType = myWidgetApi->widgetType(); - - // Create a ModelWidget - ModuleBase_ModelWidget* aWidget = createWidgetByType(aWdgType, thePage->pageWidget()); - if (aWidget) { - if (!myWidgetApi->getBooleanAttribute(ATTR_INTERNAL, false)) { - thePage->addModelWidget(aWidget); - } - else { - aWidget->setVisible(false); - } - } - } - thePage->alignToTop(); -} - -void ModuleBase_WidgetFactory::getAttributeTitle(const std::string& theAttributeId, - std::string& theTitle) -{ - bool aFound = false; - moveToWidgetId(theAttributeId, aFound); - if (aFound) { - theTitle = QString::fromStdString(myWidgetApi->widgetLabel()).toStdString().c_str(); - if (theTitle.empty()) - theTitle = QString::fromStdString(myWidgetApi->getProperty(CONTAINER_PAGE_NAME)).toStdString().c_str(); - } -} - -void ModuleBase_WidgetFactory::getGreedAttribute(std::string& theAttributeId) -{ - if (!theAttributeId.empty()) - return; - - if (!myWidgetApi->toChildWidget()) - return; - - do { //Iterate over each node - std::string aWdgType = myWidgetApi->widgetType(); - // Find title under PageGroup - if (myWidgetApi->isGroupBoxWidget() || - ModuleBase_WidgetCreatorFactory::get()->hasPageWidget(aWdgType)) { - getGreedAttribute(theAttributeId); - } - else { - // Find title here - std::string anAttributeId = myWidgetApi->widgetId(); - if (myWidgetApi->getBooleanAttribute(ATTR_GREED, false)) - theAttributeId = anAttributeId; - if (theAttributeId.empty() && myWidgetApi->isPagedWidget()) { - //If current widget is toolbox or switch-casebox then fetch all - //it's pages recursively and setup into the widget. - if (myWidgetApi->toChildWidget()) { - do { - getGreedAttribute(theAttributeId); - } while (theAttributeId.empty() && myWidgetApi->toNextWidget()); - } - } - } - } while (theAttributeId.empty() && myWidgetApi->toNextWidget()); -} - -void ModuleBase_WidgetFactory::moveToWidgetId(const std::string& theWidgetId, bool& theFound) -{ - if (theFound) - return; - - if (!myWidgetApi->toChildWidget()) - return; - - do { //Iterate over each node - std::string aWdgType = myWidgetApi->widgetType(); - // Find title under PageGroup - if (myWidgetApi->isGroupBoxWidget() || - ModuleBase_WidgetCreatorFactory::get()->hasPageWidget(aWdgType)) { - moveToWidgetId(theWidgetId, theFound); - } - else { - // Find title here - std::string anAttributeId = myWidgetApi->widgetId(); - theFound = anAttributeId == theWidgetId; - if (!theFound && myWidgetApi->isPagedWidget()) { - //If current widget is toolbox or switch-casebox then fetch all - //it's pages recursively and setup into the widget. - if (myWidgetApi->toChildWidget()) { - do { - moveToWidgetId(theWidgetId, theFound); - } while (!theFound && myWidgetApi->toNextWidget()); - } - } - } - } while (!theFound && myWidgetApi->toNextWidget()); -} - -ModuleBase_PageBase* ModuleBase_WidgetFactory::createPageByType(const std::string& theType, - QWidget* theParent) -{ - ModuleBase_PageBase* aResult = NULL; - - if (theType == WDG_GROUP) { - QString aGroupName = qs(myWidgetApi->getProperty(CONTAINER_PAGE_NAME)); - ModuleBase_PageGroupBox* aPage = new ModuleBase_PageGroupBox(theParent); - aPage->setTitle(aGroupName); - aResult = aPage; - } - else if (theType == WDG_OPTIONALBOX) { - ModuleBase_WidgetOptionalBox* aPage = new ModuleBase_WidgetOptionalBox(theParent, - myWidgetApi); - aResult = aPage; - } - if (!aResult) - aResult = ModuleBase_WidgetCreatorFactory::get()->createPageByType(theType, theParent, - myWidgetApi); - - ModuleBase_ModelWidget* aWidget = dynamic_cast(aResult); - if (aWidget) - myModelWidgets.append(aWidget); - - return aResult; -} - -ModuleBase_ModelWidget* ModuleBase_WidgetFactory::createWidgetByType(const std::string& theType, - QWidget* theParent) -{ - ModuleBase_ModelWidget* result = NULL; - - if (theType == WDG_INFO) { - result = new ModuleBase_WidgetLabel(theParent, myWidgetApi); - } else if (theType == WDG_DOUBLEVALUE) { - result = new ModuleBase_WidgetDoubleValue(theParent, myWidgetApi); - } else if (theType == WDG_INTEGERVALUE) { - result = new ModuleBase_WidgetIntValue(theParent, myWidgetApi); - } else if (theType == WDG_SHAPE_SELECTOR) { - result = new ModuleBase_WidgetShapeSelector(theParent, myWorkshop, myWidgetApi); - } else if (theType == WDG_FEATURE_SELECTOR) { - result = new ModuleBase_WidgetFeatureSelector(theParent, myWorkshop, myWidgetApi); - } else if (theType == WDG_BOOLVALUE) { - result = new ModuleBase_WidgetBoolValue(theParent, myWidgetApi); - //} else if (theType == WDG_DOUBLEVALUE_EDITOR) { - // result = new ModuleBase_WidgetEditor(theParent, myWidgetApi); - } else if (theType == WDG_FILE_SELECTOR) { - result = new ModuleBase_WidgetFileSelector(theParent, myWidgetApi); - } else if (theType == WDG_CHOICE) { - result = new ModuleBase_WidgetChoice(theParent, myWidgetApi); - } else if (theType == WDG_STRINGVALUE) { - std::string aPlaceHolder = myWidgetApi->getProperty( WDG_PLACE_HOLDER ); - result = new ModuleBase_WidgetLineEdit( theParent, myWidgetApi, aPlaceHolder ); - } else if (theType == WDG_EXPR_EDITOR) { - std::string aPlaceHolder = myWidgetApi->getProperty( WDG_PLACE_HOLDER ); - result = new ModuleBase_WidgetExprEditor( theParent, myWidgetApi, aPlaceHolder ); - } else if (theType == WDG_MULTISELECTOR) { - result = new ModuleBase_WidgetMultiSelector(theParent, myWorkshop, myWidgetApi); - } else if (theType == WDG_CONCEALED_OBJECTS_VIEW) { - result = new ModuleBase_WidgetConcealedObjects(theParent, myWidgetApi); - } else if (theType == WDG_TOOLBOX) { - result = new ModuleBase_WidgetToolbox(theParent, myWidgetApi); - } else if (theType == WDG_SWITCH) { - result = new ModuleBase_WidgetSwitch(theParent, myWidgetApi); - } else if (theType == WDG_TOOLBOX_BOX || theType == WDG_SWITCH_CASE || - theType == NODE_VALIDATOR) { - // Do nothing for "box" and "case" - result = NULL; - } else if (theType == WDG_ACTION) { - result = new ModuleBase_WidgetAction(theParent, myWidgetApi); - } else { - result = myWorkshop->module()->createWidgetByType(theType, theParent, myWidgetApi); - if (!result) - result = ModuleBase_WidgetCreatorFactory::get()->createWidgetByType(theType, theParent, - myWidgetApi, myWorkshop); - #ifdef _DEBUG - if (!result) { - qDebug("ModuleBase_WidgetFactory::fillWidget: find bad widget type %s", theType.c_str()); - } - #endif - } - if (result) - myModelWidgets.append(result); - return result; -} - -QString ModuleBase_WidgetFactory::qs(const std::string& theStdString) -{ - return QString::fromStdString(theStdString); -} - +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +/* + * ModuleBase_WidgetFactory.cpp + * + * Created on: Apr 3, 2014 + * Author: sbh + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _DEBUG +#include +#endif + +#include +#include + +ModuleBase_WidgetFactory::ModuleBase_WidgetFactory(const std::string& theXmlRepresentation, + ModuleBase_IWorkshop* theWorkshop) + : myWorkshop(theWorkshop) +{ + myWidgetApi = new Config_WidgetAPI(theXmlRepresentation); +} + +ModuleBase_WidgetFactory::~ModuleBase_WidgetFactory() +{ + delete myWidgetApi; +} + +void ModuleBase_WidgetFactory::createWidget(ModuleBase_PageBase* thePage, bool alignToTop) +{ + std::string aWType = myWidgetApi->widgetType(); + if (aWType == NODE_FEATURE) { + // if XML definition of the feature contains the next key, the widgets should not be created, + // but a specific panel should be made. However, to provide persistent of the panel values, + // we need to get into the panel the feature of the operation. As a result this panel should + // be created after the feature creating(create operation). The method setPanel() of this + // class is used for this. Here, we just return to avoid the widgets creation. + std::string aPanelName = myWidgetApi->getProperty(PROPERTY_PANEL_ID); + if (!aPanelName.empty()) + return; + } + + if (!myWidgetApi->toChildWidget()) + return; + + do { //Iterate over each node + std::string aWdgType = myWidgetApi->widgetType(); + // Create PageGroup TODO: extract + if (myWidgetApi->isGroupBoxWidget() || + ModuleBase_WidgetCreatorFactory::get()->hasPageWidget(aWdgType)) { + + //if current widget is groupbox (container) process it's children recursively + ModuleBase_PageBase* aPage = createPageByType(aWdgType, thePage->pageWidget()); + + createWidget(aPage); + thePage->addPageWidget(aPage); + } else { + // Create a ModelWidget + ModuleBase_ModelWidget* aWidget = createWidgetByType(aWdgType, thePage->pageWidget()); + if (aWidget) { + if (!myWidgetApi->getBooleanAttribute(ATTR_INTERNAL, false)) { + thePage->addModelWidget(aWidget); + } else { + aWidget->setVisible(false); + } + } + // Create PagedContainer TODO: extract + if (myWidgetApi->isPagedWidget()) { + //If current widget is toolbox or switch-casebox then fetch all + //it's pages recursively and setup into the widget. + if (myWidgetApi->toChildWidget()) { + do { + QString aPageName = qs(myWidgetApi->getProperty(CONTAINER_PAGE_NAME)); + QString aCaseId = qs(myWidgetApi->getProperty(_ID)); + ModuleBase_PageBase* aPage = new ModuleBase_PageWidget(aWidget); + createWidget(aPage); + if (aWdgType == WDG_SWITCH || aWdgType == WDG_TOOLBOX) { + ModuleBase_PagedContainer* aContainer = qobject_cast(aWidget); + + QString anIconPath = qs( myWidgetApi->getProperty( CONTAINER_PAGE_ICON ) ); + QPixmap anIcon = ModuleBase_IconFactory::loadPixmap( anIconPath ); + aContainer->addPage( aPage, aPageName, aCaseId, anIcon ); + } + } while (myWidgetApi->toNextWidget()); + } + } + } + } while (myWidgetApi->toNextWidget()); + + if (alignToTop) + thePage->alignToTop(); +} + +void ModuleBase_WidgetFactory::createPanel(ModuleBase_PageBase* thePage, + const FeaturePtr& theFeature) +{ + std::string aPanelName = myWidgetApi->getProperty(PROPERTY_PANEL_ID); + if (!aPanelName.empty() && ModuleBase_WidgetCreatorFactory::get()->hasPanelWidget(aPanelName)) { + QWidget* aPanel = ModuleBase_WidgetCreatorFactory::get()->createPanelByType(aPanelName, + thePage->pageWidget(), theFeature); + thePage->addWidget(aPanel); + thePage->alignToTop(); + } +} + +void ModuleBase_WidgetFactory::createWidget(ModuleBase_PageBase* thePage, + const std::string& theWidgetId) +{ + bool aFound = false; + moveToWidgetId(theWidgetId, aFound); + if (aFound) { + std::string aWdgType = myWidgetApi->widgetType(); + + // Create a ModelWidget + ModuleBase_ModelWidget* aWidget = createWidgetByType(aWdgType, thePage->pageWidget()); + if (aWidget) { + if (!myWidgetApi->getBooleanAttribute(ATTR_INTERNAL, false)) { + thePage->addModelWidget(aWidget); + } + else { + aWidget->setVisible(false); + } + } + } + thePage->alignToTop(); +} + +void ModuleBase_WidgetFactory::getAttributeTitle(const std::string& theAttributeId, + std::string& theTitle) +{ + bool aFound = false; + moveToWidgetId(theAttributeId, aFound); + if (aFound) { + theTitle = QString::fromStdString(myWidgetApi->widgetLabel()).toStdString().c_str(); + if (theTitle.empty()) + theTitle = QString::fromStdString(myWidgetApi->getProperty(CONTAINER_PAGE_NAME)).toStdString().c_str(); + } +} + +void ModuleBase_WidgetFactory::getGreedAttribute(std::string& theAttributeId) +{ + if (!theAttributeId.empty()) + return; + + if (!myWidgetApi->toChildWidget()) + return; + + do { //Iterate over each node + std::string aWdgType = myWidgetApi->widgetType(); + // Find title under PageGroup + if (myWidgetApi->isGroupBoxWidget() || + ModuleBase_WidgetCreatorFactory::get()->hasPageWidget(aWdgType)) { + getGreedAttribute(theAttributeId); + } + else { + // Find title here + std::string anAttributeId = myWidgetApi->widgetId(); + if (myWidgetApi->getBooleanAttribute(ATTR_GREED, false)) + theAttributeId = anAttributeId; + if (theAttributeId.empty() && myWidgetApi->isPagedWidget()) { + //If current widget is toolbox or switch-casebox then fetch all + //it's pages recursively and setup into the widget. + if (myWidgetApi->toChildWidget()) { + do { + getGreedAttribute(theAttributeId); + } while (theAttributeId.empty() && myWidgetApi->toNextWidget()); + } + } + } + } while (theAttributeId.empty() && myWidgetApi->toNextWidget()); +} + +void ModuleBase_WidgetFactory::moveToWidgetId(const std::string& theWidgetId, bool& theFound) +{ + if (theFound) + return; + + if (!myWidgetApi->toChildWidget()) + return; + + do { //Iterate over each node + std::string aWdgType = myWidgetApi->widgetType(); + // Find title under PageGroup + if (myWidgetApi->isGroupBoxWidget() || + ModuleBase_WidgetCreatorFactory::get()->hasPageWidget(aWdgType)) { + moveToWidgetId(theWidgetId, theFound); + } + else { + // Find title here + std::string anAttributeId = myWidgetApi->widgetId(); + theFound = anAttributeId == theWidgetId; + if (!theFound && myWidgetApi->isPagedWidget()) { + //If current widget is toolbox or switch-casebox then fetch all + //it's pages recursively and setup into the widget. + if (myWidgetApi->toChildWidget()) { + do { + moveToWidgetId(theWidgetId, theFound); + } while (!theFound && myWidgetApi->toNextWidget()); + } + } + } + } while (!theFound && myWidgetApi->toNextWidget()); +} + +ModuleBase_PageBase* ModuleBase_WidgetFactory::createPageByType(const std::string& theType, + QWidget* theParent) +{ + ModuleBase_PageBase* aResult = NULL; + + if (theType == WDG_GROUP) { + QString aGroupName = qs(myWidgetApi->getProperty(CONTAINER_PAGE_NAME)); + ModuleBase_PageGroupBox* aPage = new ModuleBase_PageGroupBox(theParent); + aPage->setTitle(aGroupName); + aResult = aPage; + } + else if (theType == WDG_OPTIONALBOX) { + ModuleBase_WidgetOptionalBox* aPage = new ModuleBase_WidgetOptionalBox(theParent, + myWidgetApi); + aResult = aPage; + } + if (!aResult) + aResult = ModuleBase_WidgetCreatorFactory::get()->createPageByType(theType, theParent, + myWidgetApi); + + ModuleBase_ModelWidget* aWidget = dynamic_cast(aResult); + if (aWidget) + myModelWidgets.append(aWidget); + + return aResult; +} + +ModuleBase_ModelWidget* ModuleBase_WidgetFactory::createWidgetByType(const std::string& theType, + QWidget* theParent) +{ + ModuleBase_ModelWidget* result = NULL; + + if (theType == WDG_INFO) { + result = new ModuleBase_WidgetLabel(theParent, myWidgetApi); + } else if (theType == WDG_DOUBLEVALUE) { + result = new ModuleBase_WidgetDoubleValue(theParent, myWidgetApi); + } else if (theType == WDG_INTEGERVALUE) { + result = new ModuleBase_WidgetIntValue(theParent, myWidgetApi); + } else if (theType == WDG_SHAPE_SELECTOR) { + result = new ModuleBase_WidgetShapeSelector(theParent, myWorkshop, myWidgetApi); + } else if (theType == WDG_FEATURE_SELECTOR) { + result = new ModuleBase_WidgetFeatureSelector(theParent, myWorkshop, myWidgetApi); + } else if (theType == WDG_BOOLVALUE) { + result = new ModuleBase_WidgetBoolValue(theParent, myWidgetApi); + //} else if (theType == WDG_DOUBLEVALUE_EDITOR) { + // result = new ModuleBase_WidgetEditor(theParent, myWidgetApi); + } else if (theType == WDG_FILE_SELECTOR) { + result = new ModuleBase_WidgetFileSelector(theParent, myWidgetApi); + } else if (theType == WDG_CHOICE) { + result = new ModuleBase_WidgetChoice(theParent, myWidgetApi); + } else if (theType == WDG_STRINGVALUE) { + std::string aPlaceHolder = myWidgetApi->getProperty( WDG_PLACE_HOLDER ); + result = new ModuleBase_WidgetLineEdit( theParent, myWidgetApi, aPlaceHolder ); + } else if (theType == WDG_EXPR_EDITOR) { + std::string aPlaceHolder = myWidgetApi->getProperty( WDG_PLACE_HOLDER ); + result = new ModuleBase_WidgetExprEditor( theParent, myWidgetApi, aPlaceHolder ); + } else if (theType == WDG_MULTISELECTOR) { + result = new ModuleBase_WidgetMultiSelector(theParent, myWorkshop, myWidgetApi); + } else if (theType == WDG_CONCEALED_OBJECTS_VIEW) { + result = new ModuleBase_WidgetConcealedObjects(theParent, myWidgetApi); + } else if (theType == WDG_TOOLBOX) { + result = new ModuleBase_WidgetToolbox(theParent, myWidgetApi); + } else if (theType == WDG_SWITCH) { + result = new ModuleBase_WidgetSwitch(theParent, myWidgetApi); + } else if (theType == WDG_TOOLBOX_BOX || theType == WDG_SWITCH_CASE || + theType == NODE_VALIDATOR) { + // Do nothing for "box" and "case" + result = NULL; + } else if (theType == WDG_ACTION) { + result = new ModuleBase_WidgetAction(theParent, myWidgetApi); + } else { + result = myWorkshop->module()->createWidgetByType(theType, theParent, myWidgetApi); + if (!result) + result = ModuleBase_WidgetCreatorFactory::get()->createWidgetByType(theType, theParent, + myWidgetApi, myWorkshop); + #ifdef _DEBUG + if (!result) { + qDebug("ModuleBase_WidgetFactory::fillWidget: find bad widget type %s", theType.c_str()); + } + #endif + } + if (result) + myModelWidgets.append(result); + return result; +} + +QString ModuleBase_WidgetFactory::qs(const std::string& theStdString) +{ + return QString::fromStdString(theStdString); +} + diff --git a/src/ModuleBase/ModuleBase_WidgetFeatureSelector.cpp b/src/ModuleBase/ModuleBase_WidgetFeatureSelector.cpp index 74da1b3af..a181d9e0c 100644 --- a/src/ModuleBase/ModuleBase_WidgetFeatureSelector.cpp +++ b/src/ModuleBase/ModuleBase_WidgetFeatureSelector.cpp @@ -1,88 +1,88 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: ModuleBase_WidgetFeatureSelector.cpp -// Created: 5 Sep 2016 -// Author: Natalia Ermolaeva - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - - -ModuleBase_WidgetFeatureSelector::ModuleBase_WidgetFeatureSelector(QWidget* theParent, - ModuleBase_IWorkshop* theWorkshop, - const Config_WidgetAPI* theData) -: ModuleBase_WidgetValidated(theParent, theWorkshop, theData) -{ - QFormLayout* aLayout = new QFormLayout(this); - ModuleBase_Tools::adjustMargins(aLayout); - - QString aLabelText = QString::fromStdString(theData->widgetLabel()); - QString aLabelIcon = QString::fromStdString(theData->widgetIcon()); - myLabel = new QLabel(aLabelText, this); - if (!aLabelIcon.isEmpty()) - myLabel->setPixmap(ModuleBase_IconFactory::loadPixmap(aLabelIcon)); - - - QString aToolTip = QString::fromStdString(theData->widgetTooltip()); - myTextLine = new QLineEdit(this); - QString anObjName = QString::fromStdString(attributeID()); - myTextLine->setObjectName(anObjName); - myTextLine->setReadOnly(true); - myTextLine->setToolTip(aToolTip); - myTextLine->installEventFilter(this); - - aLayout->addRow(myLabel, myTextLine); - myLabel->setToolTip(aToolTip); -} - -//******************************************************************** -ModuleBase_WidgetFeatureSelector::~ModuleBase_WidgetFeatureSelector() -{ -} - +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: ModuleBase_WidgetFeatureSelector.cpp +// Created: 5 Sep 2016 +// Author: Natalia Ermolaeva + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + + +ModuleBase_WidgetFeatureSelector::ModuleBase_WidgetFeatureSelector(QWidget* theParent, + ModuleBase_IWorkshop* theWorkshop, + const Config_WidgetAPI* theData) +: ModuleBase_WidgetValidated(theParent, theWorkshop, theData) +{ + QFormLayout* aLayout = new QFormLayout(this); + ModuleBase_Tools::adjustMargins(aLayout); + + QString aLabelText = QString::fromStdString(theData->widgetLabel()); + QString aLabelIcon = QString::fromStdString(theData->widgetIcon()); + myLabel = new QLabel(aLabelText, this); + if (!aLabelIcon.isEmpty()) + myLabel->setPixmap(ModuleBase_IconFactory::loadPixmap(aLabelIcon)); + + + QString aToolTip = QString::fromStdString(theData->widgetTooltip()); + myTextLine = new QLineEdit(this); + QString anObjName = QString::fromStdString(attributeID()); + myTextLine->setObjectName(anObjName); + myTextLine->setReadOnly(true); + myTextLine->setToolTip(aToolTip); + myTextLine->installEventFilter(this); + + aLayout->addRow(myLabel, myTextLine); + myLabel->setToolTip(aToolTip); +} + +//******************************************************************** +ModuleBase_WidgetFeatureSelector::~ModuleBase_WidgetFeatureSelector() +{ +} + //******************************************************************** bool ModuleBase_WidgetFeatureSelector::setSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs) { @@ -101,17 +101,17 @@ void ModuleBase_WidgetFeatureSelector::deactivate() { ModuleBase_ModelWidget::deactivate(); disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged())); - activateFilters(false); + activateFilters(false); myWorkshop->deactivateSubShapesSelection(); -} - +} + //******************************************************************** void ModuleBase_WidgetFeatureSelector::activateCustom() { connect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()), Qt::UniqueConnection); - activateFilters(true); + activateFilters(true); QIntList aShapeTypes; aShapeTypes.push_back(ModuleBase_ResultPrs::Sel_Result); @@ -122,94 +122,94 @@ void ModuleBase_WidgetFeatureSelector::activateCustom() //static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION); //ModelAPI_EventCreator::get()->sendUpdated(myFeature, anEvent); } - -//******************************************************************** -bool ModuleBase_WidgetFeatureSelector::storeValueCustom() -{ - // the value is stored on the selection changed signal processing - return true; -} - -//******************************************************************** -bool ModuleBase_WidgetFeatureSelector::setSelection(QList& theValues, - const bool theToValidate) -{ - if (theValues.empty()) { - // In order to make reselection possible, set empty object and shape should be done - setSelectionCustom(std::shared_ptr(new ModuleBase_ViewerPrs( - ObjectPtr(), GeomShapePtr(), NULL))); - return false; - } - // it removes the processed value from the parameters list - ModuleBase_ViewerPrsPtr aValue = theValues.takeFirst(); - bool isDone = false; - - if (!theToValidate || isValidSelection(aValue)) - isDone = setSelectionCustom(aValue); - - return isDone; -} - -//******************************************************************** -bool ModuleBase_WidgetFeatureSelector::restoreValueCustom() -{ - bool isBlocked = this->blockSignals(true); - updateSelectionName(); - this->blockSignals(isBlocked); - - return true; -} - -//******************************************************************** -QList ModuleBase_WidgetFeatureSelector::getControls() const -{ - QList aControls; - aControls.append(myTextLine); - return aControls; -} - -void ModuleBase_WidgetFeatureSelector::updateFocus() -{ - emit focusOutWidget(this); -} - -//******************************************************************** -void ModuleBase_WidgetFeatureSelector::updateSelectionName() -{ - DataPtr aData = myFeature->data(); - if (!aData->isValid()) - return; - - ObjectPtr anObject = ModuleBase_Tools::getObject(myFeature->attribute(attributeID())); - if (anObject.get() != NULL) { - std::string aName = anObject->data()->name(); - myTextLine->setText(QString::fromStdString(aName)); - } else { - myTextLine->clear(); - } -} - -//******************************************************************** -bool ModuleBase_WidgetFeatureSelector::isValidInFilters(const ModuleBase_ViewerPrsPtr& thePrs) -{ - bool aValid = false; - - ObjectPtr anObject = thePrs->object(); - FeaturePtr aFeature = std::dynamic_pointer_cast(anObject); - aValid = aFeature.get(); - if (!aValid) { - ResultPtr aResult = std::dynamic_pointer_cast(anObject); - aValid = aResult.get() && aResult->shape() == thePrs->shape(); - } - - return aValid; -} - -//******************************************************************** + +//******************************************************************** +bool ModuleBase_WidgetFeatureSelector::storeValueCustom() +{ + // the value is stored on the selection changed signal processing + return true; +} + +//******************************************************************** +bool ModuleBase_WidgetFeatureSelector::setSelection(QList& theValues, + const bool theToValidate) +{ + if (theValues.empty()) { + // In order to make reselection possible, set empty object and shape should be done + setSelectionCustom(std::shared_ptr(new ModuleBase_ViewerPrs( + ObjectPtr(), GeomShapePtr(), NULL))); + return false; + } + // it removes the processed value from the parameters list + ModuleBase_ViewerPrsPtr aValue = theValues.takeFirst(); + bool isDone = false; + + if (!theToValidate || isValidSelection(aValue)) + isDone = setSelectionCustom(aValue); + + return isDone; +} + +//******************************************************************** +bool ModuleBase_WidgetFeatureSelector::restoreValueCustom() +{ + bool isBlocked = this->blockSignals(true); + updateSelectionName(); + this->blockSignals(isBlocked); + + return true; +} + +//******************************************************************** +QList ModuleBase_WidgetFeatureSelector::getControls() const +{ + QList aControls; + aControls.append(myTextLine); + return aControls; +} + +void ModuleBase_WidgetFeatureSelector::updateFocus() +{ + emit focusOutWidget(this); +} + +//******************************************************************** +void ModuleBase_WidgetFeatureSelector::updateSelectionName() +{ + DataPtr aData = myFeature->data(); + if (!aData->isValid()) + return; + + ObjectPtr anObject = ModuleBase_Tools::getObject(myFeature->attribute(attributeID())); + if (anObject.get() != NULL) { + std::string aName = anObject->data()->name(); + myTextLine->setText(QString::fromStdString(aName)); + } else { + myTextLine->clear(); + } +} + +//******************************************************************** +bool ModuleBase_WidgetFeatureSelector::isValidInFilters(const ModuleBase_ViewerPrsPtr& thePrs) +{ + bool aValid = false; + + ObjectPtr anObject = thePrs->object(); + FeaturePtr aFeature = std::dynamic_pointer_cast(anObject); + aValid = aFeature.get(); + if (!aValid) { + ResultPtr aResult = std::dynamic_pointer_cast(anObject); + aValid = aResult.get() && aResult->shape() == thePrs->shape(); + } + + return aValid; +} + +//******************************************************************** void ModuleBase_WidgetFeatureSelector::onSelectionChanged() { - QList aSelected = myWorkshop->selection()->getSelected( - ModuleBase_ISelection::AllControls); + QList aSelected = myWorkshop->selection()->getSelected( + ModuleBase_ISelection::AllControls); bool isDone = setSelection(aSelected, true/*false*/); updateOnSelectionChanged(isDone); diff --git a/src/ModuleBase/ModuleBase_WidgetFeatureSelector.h b/src/ModuleBase/ModuleBase_WidgetFeatureSelector.h index 7e1538b19..3489a336a 100644 --- a/src/ModuleBase/ModuleBase_WidgetFeatureSelector.h +++ b/src/ModuleBase/ModuleBase_WidgetFeatureSelector.h @@ -1,106 +1,106 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: ModuleBase_WidgetFeatureSelector.h -// Created: 5 Sep 2016 -// Author: Natalia Ermolaeva - -#ifndef ModuleBase_WidgetFeatureSelector_H -#define ModuleBase_WidgetFeatureSelector_H - -#include "ModuleBase.h" -#include "ModuleBase_WidgetSelector.h" - -class Config_WidgetAPI; -class QWidget; -class QLabel; -class QLineEdit; - -/** -* \ingroup GUI -* Implementation of widget for feature selection. -* This type of widget can be defined in XML file with 'feature_selector' keyword. -* For example: -* \code -* -* \endcode -* It can use following parameters: -* - id - name of object attribute -* - label - content of widget's label -* - tooltip - the witget's tooltip text -*/ -class MODULEBASE_EXPORT ModuleBase_WidgetFeatureSelector : public ModuleBase_WidgetValidated -{ -Q_OBJECT - public: - - /// Constructor - /// \param theParent the parent object - /// \param theWorkshop instance of workshop interface - /// \param theData the widget configuation. The attribute of the model widget is obtained from - ModuleBase_WidgetFeatureSelector(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop, - const Config_WidgetAPI* theData); - - virtual ~ModuleBase_WidgetFeatureSelector(); - - /// Set the given wrapped value to the current widget - /// This value should be processed in the widget according to the needs - /// The method is called by the current operation to process the operation preselection. - /// It is redefined to check the value validity and if it is, fill the attribute with by value - /// \param theValues the wrapped selection values - /// \param theToValidate a flag on validation of the values - virtual bool setSelection(QList>& theValues, - const bool theToValidate); - - /// Returns list of widget controls - /// \return a control list - virtual QList getControls() const; - - /// Fills the attribute with the value of the selected owner - /// \param thePrs a selected owner - virtual bool setSelectionCustom(const std::shared_ptr& thePrs); - - /// The method called when widget is deactivated - virtual void deactivate(); - -protected: - /// The method called when widget is activated - virtual void activateCustom(); - - /// Saves the internal parameters to the given feature - /// \return True in success - virtual bool storeValueCustom(); - - virtual bool restoreValueCustom(); - - /// Computes and updates name of selected object in the widget - virtual void updateSelectionName(); - - // Update focus after the attribute value change - virtual void updateFocus(); - - /// Checks whether all active viewer filters validate the presentation - /// \param thePrs a selected presentation in the view - /// \return a boolean value - virtual bool isValidInFilters(const std::shared_ptr& thePrs); - - /// Emits model changed info, updates the current control by selection change - /// \param theDone a state whether the selection is set - virtual void updateOnSelectionChanged(const bool theDone); - -protected slots: - /// Called on selection changed event - virtual void onSelectionChanged(); - - //----------- Class members ------------- -protected: - /// Label of the widget - QLabel* myLabel; - - /// Input control of the widget - QLineEdit* myTextLine; -}; - -#endif +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: ModuleBase_WidgetFeatureSelector.h +// Created: 5 Sep 2016 +// Author: Natalia Ermolaeva + +#ifndef ModuleBase_WidgetFeatureSelector_H +#define ModuleBase_WidgetFeatureSelector_H + +#include "ModuleBase.h" +#include "ModuleBase_WidgetSelector.h" + +class Config_WidgetAPI; +class QWidget; +class QLabel; +class QLineEdit; + +/** +* \ingroup GUI +* Implementation of widget for feature selection. +* This type of widget can be defined in XML file with 'feature_selector' keyword. +* For example: +* \code +* +* \endcode +* It can use following parameters: +* - id - name of object attribute +* - label - content of widget's label +* - tooltip - the witget's tooltip text +*/ +class MODULEBASE_EXPORT ModuleBase_WidgetFeatureSelector : public ModuleBase_WidgetValidated +{ +Q_OBJECT + public: + + /// Constructor + /// \param theParent the parent object + /// \param theWorkshop instance of workshop interface + /// \param theData the widget configuation. The attribute of the model widget is obtained from + ModuleBase_WidgetFeatureSelector(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop, + const Config_WidgetAPI* theData); + + virtual ~ModuleBase_WidgetFeatureSelector(); + + /// Set the given wrapped value to the current widget + /// This value should be processed in the widget according to the needs + /// The method is called by the current operation to process the operation preselection. + /// It is redefined to check the value validity and if it is, fill the attribute with by value + /// \param theValues the wrapped selection values + /// \param theToValidate a flag on validation of the values + virtual bool setSelection(QList>& theValues, + const bool theToValidate); + + /// Returns list of widget controls + /// \return a control list + virtual QList getControls() const; + + /// Fills the attribute with the value of the selected owner + /// \param thePrs a selected owner + virtual bool setSelectionCustom(const std::shared_ptr& thePrs); + + /// The method called when widget is deactivated + virtual void deactivate(); + +protected: + /// The method called when widget is activated + virtual void activateCustom(); + + /// Saves the internal parameters to the given feature + /// \return True in success + virtual bool storeValueCustom(); + + virtual bool restoreValueCustom(); + + /// Computes and updates name of selected object in the widget + virtual void updateSelectionName(); + + // Update focus after the attribute value change + virtual void updateFocus(); + + /// Checks whether all active viewer filters validate the presentation + /// \param thePrs a selected presentation in the view + /// \return a boolean value + virtual bool isValidInFilters(const std::shared_ptr& thePrs); + + /// Emits model changed info, updates the current control by selection change + /// \param theDone a state whether the selection is set + virtual void updateOnSelectionChanged(const bool theDone); + +protected slots: + /// Called on selection changed event + virtual void onSelectionChanged(); + + //----------- Class members ------------- +protected: + /// Label of the widget + QLabel* myLabel; + + /// Input control of the widget + QLineEdit* myTextLine; +}; + +#endif diff --git a/src/ModuleBase/ModuleBase_WidgetSelector.h b/src/ModuleBase/ModuleBase_WidgetSelector.h index 11f3e474c..3a309beb0 100755 --- a/src/ModuleBase/ModuleBase_WidgetSelector.h +++ b/src/ModuleBase/ModuleBase_WidgetSelector.h @@ -1,121 +1,121 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: ModuleBase_WidgetSelector.h -// Created: 19 June 2015 -// Author: Natalia ERMOLAEVA - -#ifndef ModuleBase_WidgetSelector_H -#define ModuleBase_WidgetSelector_H - -#include "ModuleBase.h" -#include "ModuleBase_WidgetValidated.h" -#include "ModuleBase_Definitions.h" - -#include -#include -#include - -class Config_WidgetAPI; -class QWidget; -class ModuleBase_IWorkshop; -class ModuleBase_ViewerPrs; -class ModelAPI_Result; - -/** -* \ingroup GUI -* Implementation of widget for selection. -* This abstract interface is designed to be used for shape/multi shape selector widgets. -*/ -class MODULEBASE_EXPORT ModuleBase_WidgetSelector : public ModuleBase_WidgetValidated -{ -Q_OBJECT - public: - - /// Constructor - /// \param theParent the parent object - /// \param theWorkshop instance of workshop interface - /// \param theData the widget configuation. The attribute of the model widget is obtained from - ModuleBase_WidgetSelector(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop, - const Config_WidgetAPI* theData); - - virtual ~ModuleBase_WidgetSelector(); - - /// Defines if it is supposed that the widget should interact with the viewer. - virtual bool isViewerSelector() { return true; } - - /// Activate or deactivate selection and selection filters - /// \return true if the selection filter of the widget is activated in viewer context - virtual bool activateSelectionAndFilters(bool toActivate); - - /// Checks the widget validity. By default, it returns true. - /// \param thePrs a selected presentation in the view - /// \return a boolean value - virtual bool isValidSelectionCustom(const std::shared_ptr& thePrs); - - /// Fills the attribute with the value of the selected owner - /// \param thePrs a selected owner - virtual bool setSelectionCustom(const std::shared_ptr& thePrs); - - /// The methiod called when widget is deactivated - virtual void deactivate(); - - /// Return the attribute values wrapped in a list of viewer presentations - /// \return a list of viewer presentations, which contains an attribute result and - /// a shape. If the attribute do not uses the shape, it is empty - virtual QList> getAttributeSelection() const; - -protected slots: - /// Slot which is called on selection event - virtual void onSelectionChanged(); - -protected: - /// Emits model changed info, updates the current control by selection change - /// \param theDone a state whether the selection is set - virtual void updateOnSelectionChanged(const bool theDone); - - /// Update focus after the attribute value change - // NDS: has body is temporary - virtual void updateFocus() {}; - - /// Retunrs a list of possible shape types - /// \return a list of shapes - QIntList getShapeTypes() const; - - /// Retunrs a list of possible shape types - /// \return a list of shapes - virtual QIntList shapeTypes() const = 0; - - /// Computes and updates name of selected object in the widget - // NDS: has body is temporary - virtual void updateSelectionName() {}; - - /// The methiod called when widget is activated - virtual void activateCustom(); - - /// Returns true if selected shape corresponds to requested shape types. - /// If the widget type of shapes contains the faces item, the result is converted - /// to construction result and the method returns true if there is at least one face - /// in the construction. - /// \param theShape a shape - /// \param theResult a selected result - bool acceptSubShape(const GeomShapePtr& theShape, - const std::shared_ptr& theResult) const; - - /// Return an object and geom shape by the viewer presentation - /// \param thePrs a selection - /// \param theObject an output object - /// \param theShape a shape of the selection - virtual void getGeomSelection(const std::shared_ptr& thePrs, - ObjectPtr& theObject, - GeomShapePtr& theShape); - - //----------- Class members ------------- - /// Returns a name in the next form: attribute_feature_name/attribute_id - /// \param theAttribute a model attribute - /// \param theWorkshop a workshop class instance - /// \return string value - static std::string generateName(const AttributePtr& theAttribute, - ModuleBase_IWorkshop* theWorkshop); -}; - -#endif +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: ModuleBase_WidgetSelector.h +// Created: 19 June 2015 +// Author: Natalia ERMOLAEVA + +#ifndef ModuleBase_WidgetSelector_H +#define ModuleBase_WidgetSelector_H + +#include "ModuleBase.h" +#include "ModuleBase_WidgetValidated.h" +#include "ModuleBase_Definitions.h" + +#include +#include +#include + +class Config_WidgetAPI; +class QWidget; +class ModuleBase_IWorkshop; +class ModuleBase_ViewerPrs; +class ModelAPI_Result; + +/** +* \ingroup GUI +* Implementation of widget for selection. +* This abstract interface is designed to be used for shape/multi shape selector widgets. +*/ +class MODULEBASE_EXPORT ModuleBase_WidgetSelector : public ModuleBase_WidgetValidated +{ +Q_OBJECT + public: + + /// Constructor + /// \param theParent the parent object + /// \param theWorkshop instance of workshop interface + /// \param theData the widget configuation. The attribute of the model widget is obtained from + ModuleBase_WidgetSelector(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop, + const Config_WidgetAPI* theData); + + virtual ~ModuleBase_WidgetSelector(); + + /// Defines if it is supposed that the widget should interact with the viewer. + virtual bool isViewerSelector() { return true; } + + /// Activate or deactivate selection and selection filters + /// \return true if the selection filter of the widget is activated in viewer context + virtual bool activateSelectionAndFilters(bool toActivate); + + /// Checks the widget validity. By default, it returns true. + /// \param thePrs a selected presentation in the view + /// \return a boolean value + virtual bool isValidSelectionCustom(const std::shared_ptr& thePrs); + + /// Fills the attribute with the value of the selected owner + /// \param thePrs a selected owner + virtual bool setSelectionCustom(const std::shared_ptr& thePrs); + + /// The methiod called when widget is deactivated + virtual void deactivate(); + + /// Return the attribute values wrapped in a list of viewer presentations + /// \return a list of viewer presentations, which contains an attribute result and + /// a shape. If the attribute do not uses the shape, it is empty + virtual QList> getAttributeSelection() const; + +protected slots: + /// Slot which is called on selection event + virtual void onSelectionChanged(); + +protected: + /// Emits model changed info, updates the current control by selection change + /// \param theDone a state whether the selection is set + virtual void updateOnSelectionChanged(const bool theDone); + + /// Update focus after the attribute value change + // NDS: has body is temporary + virtual void updateFocus() {}; + + /// Retunrs a list of possible shape types + /// \return a list of shapes + QIntList getShapeTypes() const; + + /// Retunrs a list of possible shape types + /// \return a list of shapes + virtual QIntList shapeTypes() const = 0; + + /// Computes and updates name of selected object in the widget + // NDS: has body is temporary + virtual void updateSelectionName() {}; + + /// The methiod called when widget is activated + virtual void activateCustom(); + + /// Returns true if selected shape corresponds to requested shape types. + /// If the widget type of shapes contains the faces item, the result is converted + /// to construction result and the method returns true if there is at least one face + /// in the construction. + /// \param theShape a shape + /// \param theResult a selected result + bool acceptSubShape(const GeomShapePtr& theShape, + const std::shared_ptr& theResult) const; + + /// Return an object and geom shape by the viewer presentation + /// \param thePrs a selection + /// \param theObject an output object + /// \param theShape a shape of the selection + virtual void getGeomSelection(const std::shared_ptr& thePrs, + ObjectPtr& theObject, + GeomShapePtr& theShape); + + //----------- Class members ------------- + /// Returns a name in the next form: attribute_feature_name/attribute_id + /// \param theAttribute a model attribute + /// \param theWorkshop a workshop class instance + /// \return string value + static std::string generateName(const AttributePtr& theAttribute, + ModuleBase_IWorkshop* theWorkshop); +}; + +#endif diff --git a/src/ModuleBase/ModuleBase_WidgetValidated.cpp b/src/ModuleBase/ModuleBase_WidgetValidated.cpp index 8a3705523..daecef19f 100644 --- a/src/ModuleBase/ModuleBase_WidgetValidated.cpp +++ b/src/ModuleBase/ModuleBase_WidgetValidated.cpp @@ -1,406 +1,406 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include - -//#define DEBUG_VALID_STATE - -ModuleBase_WidgetValidated::ModuleBase_WidgetValidated(QWidget* theParent, - ModuleBase_IWorkshop* theWorkshop, - const Config_WidgetAPI* theData) -: ModuleBase_ModelWidget(theParent, theData), - myWorkshop(theWorkshop), myIsInValidate(false) -{ - myAttributeStore = new ModuleBase_WidgetSelectorStore(); -} - -ModuleBase_WidgetValidated::~ModuleBase_WidgetValidated() -{ - delete myAttributeStore; -} - -//******************************************************************** -ObjectPtr ModuleBase_WidgetValidated::findPresentedObject(const AISObjectPtr& theAIS) const -{ - return myPresentedObject; -} - -//******************************************************************** -void ModuleBase_WidgetValidated::clearValidatedCash() -{ -#ifdef DEBUG_VALID_STATE - qDebug("clearValidatedCash"); -#endif - myValidPrs.Clear(); - myInvalidPrs.Clear(); -} - -//******************************************************************** -void ModuleBase_WidgetValidated::storeAttributeValue(const AttributePtr& theAttribute) -{ - myIsInValidate = true; - myAttributeStore->storeAttributeValue(theAttribute, myWorkshop); -} - -//******************************************************************** -void ModuleBase_WidgetValidated::restoreAttributeValue(const AttributePtr& theAttribute, - const bool theValid) -{ - myIsInValidate = false; - myAttributeStore->restoreAttributeValue(theAttribute, myWorkshop); -} - -//******************************************************************** -bool ModuleBase_WidgetValidated::isValidInFilters(const ModuleBase_ViewerPrsPtr& thePrs) -{ - bool aValid = true; - Handle(SelectMgr_EntityOwner) anOwner = thePrs->owner(); - - // if an owner is null, the selection happens in the Object browser. - // creates a selection owner on the base of object shape and the object AIS object - if (anOwner.IsNull() && thePrs->owner().IsNull() && thePrs->object().get()) { - ResultPtr aResult = myWorkshop->selection()->getResult(thePrs); - GeomShapePtr aShape = aResult.get() ? aResult->shape() : GeomShapePtr(); - // some results have no shape, e.g. the parameter one. So, they should not be validated - if (aShape.get()) { - const TopoDS_Shape aTDShape = aShape->impl(); - Handle(AIS_InteractiveObject) anIO = myWorkshop->selection()->getIO(thePrs); - anOwner = new StdSelect_BRepOwner(aTDShape, anIO); - myPresentedObject = aResult; - } - else - aValid = false; // only results with a shape can be filtered - } - // checks the owner by the AIS context activated filters - if (!anOwner.IsNull()) { - // the widget validator filter should be active, but during check by preselection - // it is not yet activated, so we need to activate/deactivate it manually - bool isActivated = isFilterActivated(); - if (!isActivated) - activateFilters(true); - - Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext(); - if (!aContext.IsNull()) { - const SelectMgr_ListOfFilter& aFilters = aContext->Filters(); - SelectMgr_ListIteratorOfListOfFilter anIt(aFilters); - for (; anIt.More() && aValid; anIt.Next()) { - Handle(SelectMgr_Filter) aFilter = anIt.Value(); - aValid = aFilter->IsOk(anOwner); - } - } - if (!isActivated) - activateFilters(false); - } - - // removes created owner - if (!anOwner.IsNull() && anOwner != thePrs->owner()) { - anOwner.Nullify(); - myPresentedObject = ObjectPtr(); - } - return aValid; -} - -//******************************************************************** -AttributePtr ModuleBase_WidgetValidated::attribute() const -{ - return myFeature->attribute(attributeID()); -} - -//******************************************************************** -bool ModuleBase_WidgetValidated::isValidSelection(const ModuleBase_ViewerPrsPtr& theValue) -{ - bool aValid = false; - if (getValidState(theValue, aValid)) { - return aValid; - } - aValid = isValidSelectionCustom(theValue); - if (aValid) - aValid = isValidSelectionForAttribute(theValue, attribute()); - - storeValidState(theValue, aValid); - return aValid; -} - -//******************************************************************** -bool ModuleBase_WidgetValidated::isValidSelectionForAttribute(const ModuleBase_ViewerPrsPtr& theValue, - const AttributePtr& theAttribute) -{ - bool aValid = false; - - // stores the current values of the widget attribute - bool isFlushesActived, isAttributeSetInitializedBlocked; - - blockAttribute(theAttribute, true, isFlushesActived, isAttributeSetInitializedBlocked); - - storeAttributeValue(theAttribute); - - // saves the owner value to the widget attribute - aValid = setSelectionCustom(theValue); - if (aValid) - // checks the attribute validity - aValid = isValidAttribute(theAttribute); - - // restores the current values of the widget attribute - restoreAttributeValue(theAttribute, aValid); - - blockAttribute(theAttribute, false, isFlushesActived, isAttributeSetInitializedBlocked); - /// NDS: The following rows are commented for issue #1452 (to be removed after debug) - /// This is not correct to perform it here because it might cause update selection and - /// the selection mechanizm will be circled: use the scenario of the bug with preselected point. - // In particular case the results are deleted and called as redisplayed inside of this - // highlight-selection, to they must be flushed as soon as possible. - // Example: selection of group-vertices subshapes with shift pressend on body. Without - // these 4 lines below the application crashes because of left presentations on - // removed results still in the viewer. - /*static Events_ID aDeletedEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED); - static Events_ID aRedispEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY); - Events_Loop::loop()->flush(aDeletedEvent); - Events_Loop::loop()->flush(aRedispEvent); - */ - return aValid; -} - -//******************************************************************** -bool ModuleBase_WidgetValidated::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs) -{ - return true; -} - -//******************************************************************** -bool ModuleBase_WidgetValidated::isValidAttribute(const AttributePtr& theAttribute) const -{ - SessionPtr aMgr = ModelAPI_Session::get(); - ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); - std::string aValidatorID; - Events_InfoMessage anError; - return aFactory->validate(theAttribute, aValidatorID, anError); -} - -bool ModuleBase_WidgetValidated::isFilterActivated() const -{ - bool isActivated = false; - - Handle(SelectMgr_Filter) aSelFilter = myWorkshop->validatorFilter(); - ModuleBase_IViewer* aViewer = myWorkshop->viewer(); - - return aViewer->hasSelectionFilter(aSelFilter); -} - -bool ModuleBase_WidgetValidated::activateFilters(const bool toActivate) -{ - ModuleBase_IViewer* aViewer = myWorkshop->viewer(); - - Handle(SelectMgr_Filter) aSelFilter = myWorkshop->validatorFilter(); - bool aHasSelectionFilter = aViewer->hasSelectionFilter(aSelFilter); - - if (toActivate) - aViewer->addSelectionFilter(aSelFilter); - else { - aViewer->removeSelectionFilter(aSelFilter); - clearValidatedCash(); - } - - return aHasSelectionFilter; -} - -//******************************************************************** -void ModuleBase_WidgetValidated::blockAttribute(const AttributePtr& theAttribute, - const bool& theToBlock, - bool& isFlushesActived, - bool& isAttributeSetInitializedBlocked) -{ - Events_Loop* aLoop = Events_Loop::loop(); - DataPtr aData = myFeature->data(); - if (theToBlock) { - // blocks the flush signals to avoid the temporary objects visualization in the viewer - // they should not be shown in order to do not lose highlight by erasing them - isFlushesActived = aLoop->activateFlushes(false); - - aData->blockSendAttributeUpdated(true); - isAttributeSetInitializedBlocked = theAttribute->blockSetInitialized(true); - } - else { - aData->blockSendAttributeUpdated(false, false); - theAttribute->blockSetInitialized(isAttributeSetInitializedBlocked); - aLoop->activateFlushes(isFlushesActived); - } -} - -//******************************************************************** -void ModuleBase_WidgetValidated::storeValidState(const ModuleBase_ViewerPrsPtr& theValue, const bool theValid) -{ - GeomShapePtr aShape = theValue.get() ? theValue->shape() : GeomShapePtr(); - if (aShape.get()) { - if (theValid) { - const TopoDS_Shape& aTDShape = aShape->impl(); - bool aValidPrsContains = myValidPrs.IsBound(aTDShape) && - theValue.get()->isEqual(myValidPrs.Find(aTDShape).get()); - if (!aValidPrsContains) { - #ifdef LIST_OF_VALID_PRS - myValidPrs.append(theValue); - #else - myValidPrs.Bind(aTDShape, theValue); - #endif - // the commented code will be useful when the valid state of the presentation - // will be changable between activate/deactivate. Currently it does not happen. - //if (anInvalidPrs) - // myInvalidPrs.removeOne(theValue); - } - } - else { // !theValid - if (aShape.get()) { - const TopoDS_Shape& aTDShape = aShape->impl(); - bool anIValidPrsContains = myInvalidPrs.IsBound(aTDShape) && - theValue.get()->isEqual(myInvalidPrs.Find(aTDShape).get()); - if (!anIValidPrsContains) { - #ifdef LIST_OF_VALID_PRS - myInvalidPrs.append(theValue); - #else - myInvalidPrs.Bind(aTDShape, theValue); - #endif - //if (!aValidPrs) - // myValidPrs.removeOne(theValue); - } - } - } - } - #ifdef DEBUG_VALID_STATE - qDebug(QString("storeValidState: myValidPrs.size() = %1, myInvalidPrs.size() = %2").arg(myValidPrs.count()) - .arg(myInvalidPrs.count()).toStdString().c_str()); - #endif -} - -//******************************************************************** -bool ModuleBase_WidgetValidated::getValidState(const ModuleBase_ViewerPrsPtr& theValue, bool& theValid) -{ - if (!theValue.get()) - return false; - -#ifdef LIST_OF_VALID_PRS - bool aValidPrsContains = myValidPrs.contains(theValue); - bool anInvalidPrsContains = myInvalidPrs.contains(theValue); -#else - GeomShapePtr aShape = theValue.get() ? theValue->shape() : GeomShapePtr(); - if (!aShape.get()) - return false; - - const TopoDS_Shape& aTDShape = aShape->impl(); - bool aValidPrsContains = myValidPrs.IsBound(aTDShape) && - theValue.get()->isEqual(myValidPrs.Find(aTDShape).get()); - - bool anInvalidPrsContains = myInvalidPrs.IsBound(aTDShape) && - theValue.get()->isEqual(myInvalidPrs.Find(aTDShape).get()); - /* - bool aValidPrsContains = false, anInvalidPrsContains = false; - GeomShapePtr aShape = theValue.get() ? theValue->shape() : GeomShapePtr(); - if (aShape.get()) { - aValidPrsContains = myValidPrs.contains(aShape); - anInvalidPrsContains = myInvalidPrs.contains(aShape); - - if (aValidPrsContains) - aValidPrsContains = theValue == myValidPrs[aShape]; - else - anInvalidPrsContains = theValue == myInvalidPrs[aShape];*/ -#endif - - if (aValidPrsContains) - theValid = true; - else if (anInvalidPrsContains) - theValid = false; - - return aValidPrsContains || anInvalidPrsContains; -} - -//******************************************************************** -QList ModuleBase_WidgetValidated::getFilteredSelected() -{ - QList aSelected = myWorkshop->selection()->getSelected( - ModuleBase_ISelection::Viewer); - - QList anOBSelected = myWorkshop->selection()->getSelected( - ModuleBase_ISelection::Browser); - // filter the OB presentations - filterPresentations(anOBSelected); - if (!anOBSelected.isEmpty()) - ModuleBase_ISelection::appendSelected(anOBSelected, aSelected); - - filterCompSolids(aSelected); - - return aSelected; -} - -//******************************************************************** -void ModuleBase_WidgetValidated::filterPresentations(QList& theValues) -{ - QList aValidatedValues; - - QList::const_iterator anIt = theValues.begin(), aLast = theValues.end(); - bool isDone = false; - for (; anIt != aLast; anIt++) { - if (isValidInFilters(*anIt)) - aValidatedValues.append(*anIt); - } - if (aValidatedValues.size() != theValues.size()) { - theValues.clear(); - theValues = aValidatedValues; - } -} - -//******************************************************************** -void ModuleBase_WidgetValidated::filterCompSolids(QList& theValues) -{ - std::set aCompSolids; - QList aValidatedValues; - - // Collect compsolids. - QList::const_iterator anIt = theValues.begin(), aLast = theValues.end(); - for (; anIt != aLast; anIt++) { - const ModuleBase_ViewerPrsPtr& aViewerPrs = *anIt; - ObjectPtr anObject = aViewerPrs->object(); - ResultCompSolidPtr aResultCompSolid = std::dynamic_pointer_cast(anObject); - if(aResultCompSolid.get()) { - aCompSolids.insert(aResultCompSolid); - } - } - - // Filter sub-solids of compsolids. - anIt = theValues.begin(); - for (; anIt != aLast; anIt++) { - const ModuleBase_ViewerPrsPtr& aViewerPrs = *anIt; - ObjectPtr anObject = aViewerPrs->object(); - ResultPtr aResult = std::dynamic_pointer_cast(anObject); - ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aResult); - if(aResCompSolidPtr.get() && (aCompSolids.find(aResCompSolidPtr) != aCompSolids.end())) { - // Skip sub-solid of compsolid. - continue; - } else { - aValidatedValues.append(*anIt); - } - } - - if (aValidatedValues.size() != theValues.size()) { - theValues.clear(); - theValues = aValidatedValues; - } -} +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +//#define DEBUG_VALID_STATE + +ModuleBase_WidgetValidated::ModuleBase_WidgetValidated(QWidget* theParent, + ModuleBase_IWorkshop* theWorkshop, + const Config_WidgetAPI* theData) +: ModuleBase_ModelWidget(theParent, theData), + myWorkshop(theWorkshop), myIsInValidate(false) +{ + myAttributeStore = new ModuleBase_WidgetSelectorStore(); +} + +ModuleBase_WidgetValidated::~ModuleBase_WidgetValidated() +{ + delete myAttributeStore; +} + +//******************************************************************** +ObjectPtr ModuleBase_WidgetValidated::findPresentedObject(const AISObjectPtr& theAIS) const +{ + return myPresentedObject; +} + +//******************************************************************** +void ModuleBase_WidgetValidated::clearValidatedCash() +{ +#ifdef DEBUG_VALID_STATE + qDebug("clearValidatedCash"); +#endif + myValidPrs.Clear(); + myInvalidPrs.Clear(); +} + +//******************************************************************** +void ModuleBase_WidgetValidated::storeAttributeValue(const AttributePtr& theAttribute) +{ + myIsInValidate = true; + myAttributeStore->storeAttributeValue(theAttribute, myWorkshop); +} + +//******************************************************************** +void ModuleBase_WidgetValidated::restoreAttributeValue(const AttributePtr& theAttribute, + const bool theValid) +{ + myIsInValidate = false; + myAttributeStore->restoreAttributeValue(theAttribute, myWorkshop); +} + +//******************************************************************** +bool ModuleBase_WidgetValidated::isValidInFilters(const ModuleBase_ViewerPrsPtr& thePrs) +{ + bool aValid = true; + Handle(SelectMgr_EntityOwner) anOwner = thePrs->owner(); + + // if an owner is null, the selection happens in the Object browser. + // creates a selection owner on the base of object shape and the object AIS object + if (anOwner.IsNull() && thePrs->owner().IsNull() && thePrs->object().get()) { + ResultPtr aResult = myWorkshop->selection()->getResult(thePrs); + GeomShapePtr aShape = aResult.get() ? aResult->shape() : GeomShapePtr(); + // some results have no shape, e.g. the parameter one. So, they should not be validated + if (aShape.get()) { + const TopoDS_Shape aTDShape = aShape->impl(); + Handle(AIS_InteractiveObject) anIO = myWorkshop->selection()->getIO(thePrs); + anOwner = new StdSelect_BRepOwner(aTDShape, anIO); + myPresentedObject = aResult; + } + else + aValid = false; // only results with a shape can be filtered + } + // checks the owner by the AIS context activated filters + if (!anOwner.IsNull()) { + // the widget validator filter should be active, but during check by preselection + // it is not yet activated, so we need to activate/deactivate it manually + bool isActivated = isFilterActivated(); + if (!isActivated) + activateFilters(true); + + Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext(); + if (!aContext.IsNull()) { + const SelectMgr_ListOfFilter& aFilters = aContext->Filters(); + SelectMgr_ListIteratorOfListOfFilter anIt(aFilters); + for (; anIt.More() && aValid; anIt.Next()) { + Handle(SelectMgr_Filter) aFilter = anIt.Value(); + aValid = aFilter->IsOk(anOwner); + } + } + if (!isActivated) + activateFilters(false); + } + + // removes created owner + if (!anOwner.IsNull() && anOwner != thePrs->owner()) { + anOwner.Nullify(); + myPresentedObject = ObjectPtr(); + } + return aValid; +} + +//******************************************************************** +AttributePtr ModuleBase_WidgetValidated::attribute() const +{ + return myFeature->attribute(attributeID()); +} + +//******************************************************************** +bool ModuleBase_WidgetValidated::isValidSelection(const ModuleBase_ViewerPrsPtr& theValue) +{ + bool aValid = false; + if (getValidState(theValue, aValid)) { + return aValid; + } + aValid = isValidSelectionCustom(theValue); + if (aValid) + aValid = isValidSelectionForAttribute(theValue, attribute()); + + storeValidState(theValue, aValid); + return aValid; +} + +//******************************************************************** +bool ModuleBase_WidgetValidated::isValidSelectionForAttribute(const ModuleBase_ViewerPrsPtr& theValue, + const AttributePtr& theAttribute) +{ + bool aValid = false; + + // stores the current values of the widget attribute + bool isFlushesActived, isAttributeSetInitializedBlocked; + + blockAttribute(theAttribute, true, isFlushesActived, isAttributeSetInitializedBlocked); + + storeAttributeValue(theAttribute); + + // saves the owner value to the widget attribute + aValid = setSelectionCustom(theValue); + if (aValid) + // checks the attribute validity + aValid = isValidAttribute(theAttribute); + + // restores the current values of the widget attribute + restoreAttributeValue(theAttribute, aValid); + + blockAttribute(theAttribute, false, isFlushesActived, isAttributeSetInitializedBlocked); + /// NDS: The following rows are commented for issue #1452 (to be removed after debug) + /// This is not correct to perform it here because it might cause update selection and + /// the selection mechanizm will be circled: use the scenario of the bug with preselected point. + // In particular case the results are deleted and called as redisplayed inside of this + // highlight-selection, to they must be flushed as soon as possible. + // Example: selection of group-vertices subshapes with shift pressend on body. Without + // these 4 lines below the application crashes because of left presentations on + // removed results still in the viewer. + /*static Events_ID aDeletedEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED); + static Events_ID aRedispEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY); + Events_Loop::loop()->flush(aDeletedEvent); + Events_Loop::loop()->flush(aRedispEvent); + */ + return aValid; +} + +//******************************************************************** +bool ModuleBase_WidgetValidated::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs) +{ + return true; +} + +//******************************************************************** +bool ModuleBase_WidgetValidated::isValidAttribute(const AttributePtr& theAttribute) const +{ + SessionPtr aMgr = ModelAPI_Session::get(); + ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); + std::string aValidatorID; + Events_InfoMessage anError; + return aFactory->validate(theAttribute, aValidatorID, anError); +} + +bool ModuleBase_WidgetValidated::isFilterActivated() const +{ + bool isActivated = false; + + Handle(SelectMgr_Filter) aSelFilter = myWorkshop->validatorFilter(); + ModuleBase_IViewer* aViewer = myWorkshop->viewer(); + + return aViewer->hasSelectionFilter(aSelFilter); +} + +bool ModuleBase_WidgetValidated::activateFilters(const bool toActivate) +{ + ModuleBase_IViewer* aViewer = myWorkshop->viewer(); + + Handle(SelectMgr_Filter) aSelFilter = myWorkshop->validatorFilter(); + bool aHasSelectionFilter = aViewer->hasSelectionFilter(aSelFilter); + + if (toActivate) + aViewer->addSelectionFilter(aSelFilter); + else { + aViewer->removeSelectionFilter(aSelFilter); + clearValidatedCash(); + } + + return aHasSelectionFilter; +} + +//******************************************************************** +void ModuleBase_WidgetValidated::blockAttribute(const AttributePtr& theAttribute, + const bool& theToBlock, + bool& isFlushesActived, + bool& isAttributeSetInitializedBlocked) +{ + Events_Loop* aLoop = Events_Loop::loop(); + DataPtr aData = myFeature->data(); + if (theToBlock) { + // blocks the flush signals to avoid the temporary objects visualization in the viewer + // they should not be shown in order to do not lose highlight by erasing them + isFlushesActived = aLoop->activateFlushes(false); + + aData->blockSendAttributeUpdated(true); + isAttributeSetInitializedBlocked = theAttribute->blockSetInitialized(true); + } + else { + aData->blockSendAttributeUpdated(false, false); + theAttribute->blockSetInitialized(isAttributeSetInitializedBlocked); + aLoop->activateFlushes(isFlushesActived); + } +} + +//******************************************************************** +void ModuleBase_WidgetValidated::storeValidState(const ModuleBase_ViewerPrsPtr& theValue, const bool theValid) +{ + GeomShapePtr aShape = theValue.get() ? theValue->shape() : GeomShapePtr(); + if (aShape.get()) { + if (theValid) { + const TopoDS_Shape& aTDShape = aShape->impl(); + bool aValidPrsContains = myValidPrs.IsBound(aTDShape) && + theValue.get()->isEqual(myValidPrs.Find(aTDShape).get()); + if (!aValidPrsContains) { + #ifdef LIST_OF_VALID_PRS + myValidPrs.append(theValue); + #else + myValidPrs.Bind(aTDShape, theValue); + #endif + // the commented code will be useful when the valid state of the presentation + // will be changable between activate/deactivate. Currently it does not happen. + //if (anInvalidPrs) + // myInvalidPrs.removeOne(theValue); + } + } + else { // !theValid + if (aShape.get()) { + const TopoDS_Shape& aTDShape = aShape->impl(); + bool anIValidPrsContains = myInvalidPrs.IsBound(aTDShape) && + theValue.get()->isEqual(myInvalidPrs.Find(aTDShape).get()); + if (!anIValidPrsContains) { + #ifdef LIST_OF_VALID_PRS + myInvalidPrs.append(theValue); + #else + myInvalidPrs.Bind(aTDShape, theValue); + #endif + //if (!aValidPrs) + // myValidPrs.removeOne(theValue); + } + } + } + } + #ifdef DEBUG_VALID_STATE + qDebug(QString("storeValidState: myValidPrs.size() = %1, myInvalidPrs.size() = %2").arg(myValidPrs.count()) + .arg(myInvalidPrs.count()).toStdString().c_str()); + #endif +} + +//******************************************************************** +bool ModuleBase_WidgetValidated::getValidState(const ModuleBase_ViewerPrsPtr& theValue, bool& theValid) +{ + if (!theValue.get()) + return false; + +#ifdef LIST_OF_VALID_PRS + bool aValidPrsContains = myValidPrs.contains(theValue); + bool anInvalidPrsContains = myInvalidPrs.contains(theValue); +#else + GeomShapePtr aShape = theValue.get() ? theValue->shape() : GeomShapePtr(); + if (!aShape.get()) + return false; + + const TopoDS_Shape& aTDShape = aShape->impl(); + bool aValidPrsContains = myValidPrs.IsBound(aTDShape) && + theValue.get()->isEqual(myValidPrs.Find(aTDShape).get()); + + bool anInvalidPrsContains = myInvalidPrs.IsBound(aTDShape) && + theValue.get()->isEqual(myInvalidPrs.Find(aTDShape).get()); + /* + bool aValidPrsContains = false, anInvalidPrsContains = false; + GeomShapePtr aShape = theValue.get() ? theValue->shape() : GeomShapePtr(); + if (aShape.get()) { + aValidPrsContains = myValidPrs.contains(aShape); + anInvalidPrsContains = myInvalidPrs.contains(aShape); + + if (aValidPrsContains) + aValidPrsContains = theValue == myValidPrs[aShape]; + else + anInvalidPrsContains = theValue == myInvalidPrs[aShape];*/ +#endif + + if (aValidPrsContains) + theValid = true; + else if (anInvalidPrsContains) + theValid = false; + + return aValidPrsContains || anInvalidPrsContains; +} + +//******************************************************************** +QList ModuleBase_WidgetValidated::getFilteredSelected() +{ + QList aSelected = myWorkshop->selection()->getSelected( + ModuleBase_ISelection::Viewer); + + QList anOBSelected = myWorkshop->selection()->getSelected( + ModuleBase_ISelection::Browser); + // filter the OB presentations + filterPresentations(anOBSelected); + if (!anOBSelected.isEmpty()) + ModuleBase_ISelection::appendSelected(anOBSelected, aSelected); + + filterCompSolids(aSelected); + + return aSelected; +} + +//******************************************************************** +void ModuleBase_WidgetValidated::filterPresentations(QList& theValues) +{ + QList aValidatedValues; + + QList::const_iterator anIt = theValues.begin(), aLast = theValues.end(); + bool isDone = false; + for (; anIt != aLast; anIt++) { + if (isValidInFilters(*anIt)) + aValidatedValues.append(*anIt); + } + if (aValidatedValues.size() != theValues.size()) { + theValues.clear(); + theValues = aValidatedValues; + } +} + +//******************************************************************** +void ModuleBase_WidgetValidated::filterCompSolids(QList& theValues) +{ + std::set aCompSolids; + QList aValidatedValues; + + // Collect compsolids. + QList::const_iterator anIt = theValues.begin(), aLast = theValues.end(); + for (; anIt != aLast; anIt++) { + const ModuleBase_ViewerPrsPtr& aViewerPrs = *anIt; + ObjectPtr anObject = aViewerPrs->object(); + ResultCompSolidPtr aResultCompSolid = std::dynamic_pointer_cast(anObject); + if(aResultCompSolid.get()) { + aCompSolids.insert(aResultCompSolid); + } + } + + // Filter sub-solids of compsolids. + anIt = theValues.begin(); + for (; anIt != aLast; anIt++) { + const ModuleBase_ViewerPrsPtr& aViewerPrs = *anIt; + ObjectPtr anObject = aViewerPrs->object(); + ResultPtr aResult = std::dynamic_pointer_cast(anObject); + ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aResult); + if(aResCompSolidPtr.get() && (aCompSolids.find(aResCompSolidPtr) != aCompSolids.end())) { + // Skip sub-solid of compsolid. + continue; + } else { + aValidatedValues.append(*anIt); + } + } + + if (aValidatedValues.size() != theValues.size()) { + theValues.clear(); + theValues = aValidatedValues; + } +} diff --git a/src/ModuleBase/ModuleBase_WidgetValidated.h b/src/ModuleBase/ModuleBase_WidgetValidated.h index 31b7b59a0..427ecf169 100644 --- a/src/ModuleBase/ModuleBase_WidgetValidated.h +++ b/src/ModuleBase/ModuleBase_WidgetValidated.h @@ -1,181 +1,181 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: ModuleBase_WidgetValidated.h -// Created: 12 Mar 2015 -// Author: Natalia ERMOLAEVA - - -#ifndef MODULEBASE_WIDGETVALIDATED_H_ -#define MODULEBASE_WIDGETVALIDATED_H_ - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -class QWidget; -class ModuleBase_IWorkshop; -class ModuleBase_ISelection; -class ModuleBase_WidgetSelectorStore; -class ModelAPI_Validator; -class Config_WidgetAPI; -class Handle_SelectMgr_EntityOwner; - -//#define LIST_OF_VALID_PRS - -/** -* \ingroup GUI -* Implementation of widget with validators and filters processing. -*/ -class MODULEBASE_EXPORT ModuleBase_WidgetValidated : public ModuleBase_ModelWidget -{ - Q_OBJECT - public: - /// Constructor - /// \param theParent the parent object - /// \param theWorkshop a reference to workshop - /// \param theData the widget configuation. The attribute of the model widget is obtained from - ModuleBase_WidgetValidated(QWidget* theParent, - ModuleBase_IWorkshop* theWorkshop, - const Config_WidgetAPI* theData); - virtual ~ModuleBase_WidgetValidated(); - - /// Checks all widget validator if the owner is valid. Firstly it checks custom widget validating, - /// next, the attribute's validating. It trying on the give selection to current attribute by - /// setting the value inside and calling validators. After this, the previous attribute value is - /// restored.The valid/invalid value is cashed. - /// \param theValue a selected presentation in the view - /// \return a boolean value - virtual bool isValidSelection(const std::shared_ptr& theValue); - - //! Returns data object by AIS - ObjectPtr findPresentedObject(const AISObjectPtr& theAIS) const; - - //! Clear all validated cash in the widget - void clearValidatedCash(); - - /// Returns true if the workshop validator filter has been already activated - /// \return boolean value - bool isFilterActivated() const; - -protected: - /// Checks whether all active viewer filters validate the presentation - /// \param thePrs a selected presentation in the view - /// \return a boolean value - virtual bool isValidInFilters(const std::shared_ptr& thePrs); - - /// Checks all attribute validators returns valid. It tries on the given selection - /// to current attribute by setting the value inside and calling validators. After this, - /// the previous attribute value is restored.The valid/invalid value is cashed. - /// \param theValue a selected presentation in the view - /// \param theAttribute the attribute - /// \return a boolean value - bool isValidSelectionForAttribute(const std::shared_ptr& theValue, - const AttributePtr& theAttribute); - - /// Retunrs attribute, which should be validated. In default implementation, - /// this is an attribute of ID - /// \return an attribute - virtual AttributePtr attribute() const; - - /// Creates a backup of the current values of the attribute - /// It should be realized in the specific widget because of different - /// parameters of the current attribute - /// \param theAttribute an attribute to be stored - virtual void storeAttributeValue(const AttributePtr& theAttribute); - - /// Creates a backup of the current values of the attribute - /// It should be realized in the specific widget because of different - /// parameters of the current attribute - /// \param theAttribute an attribute to be restored - /// \param theValid a boolean flag, if restore happens for valid parameters - virtual void restoreAttributeValue(const AttributePtr& theAttribute, const bool theValid); - - /// Checks the widget validity. By default, it returns true. - /// \param thePrs a selected presentation in the view - /// \return a boolean value - virtual bool isValidSelectionCustom(const std::shared_ptr& thePrs); - - /// Fills the attribute with the value of the selected owner - /// \param thePrs a selected owner - virtual bool setSelectionCustom(const std::shared_ptr& thePrs) = 0; - - /// Returns a list of selected presentations in the viewer and object browser - /// The presentations from the object browser are filtered by the AIS context filters - /// \return a list of presentations - QList> getFilteredSelected(); - - /// It obtains selection filters from the workshop and activates them in the active viewer - /// \param toActivate a flag about activation or deactivation the filters - /// \return true if the selection filter of the widget is activated in viewer context - bool activateFilters(const bool toActivate); - - /// Block the model flush of update and intialization of attribute - /// \param theAttribute an attribute of blocking - /// \param theToBlock flag whether the model is blocked or unblocked - /// \param isFlushesActived out value if model is blocked, in value if model is unblocked - /// to be used to restore flush state when unblocked - /// \param isAttributeSetInitializedBlocked out value if model is blocked - /// in value if model is unblocked to be used to restore previous state when unblocked - virtual void blockAttribute(const AttributePtr& theAttribute, const bool& theToBlock, - bool& isFlushesActived, bool& isAttributeSetInitializedBlocked); - -private: - /// Checks the current attibute in all attribute validators - /// \param theAttribute an attribute to be validated - /// \return true if all validators return that the attribute is valid - bool isValidAttribute(const AttributePtr& theAttribute) const; - -protected: - /// Gets the validity state of the presentation in an internal map. Returns true if the valid state of value is stored - /// \param theValue a viewer presentation - /// \param theValid a valid state - bool getValidState(const std::shared_ptr& theValue, bool& theValid); - - /// Store the validity state of the presentation in an internal map - /// \param theValue a viewer presentation - /// \param theValid a valid state - void storeValidState(const std::shared_ptr& theValue, const bool theValid); - -private: - /// Applies AIS context filters to the parameter list. The not approved presentations are - /// removed from the parameters. - /// \param theValues a list of presentations. - void filterPresentations(QList>& theValues); - - /// Remove subshapes of compsolids if whole compsolid is present. - /// \param theValues a list of presentations. - void filterCompSolids(QList>& theValues); - -protected: - /// Reference to workshop - ModuleBase_IWorkshop* myWorkshop; - /// The widget is in validation mode: store is performed, restore is not - bool myIsInValidate; - -private: - ObjectPtr myPresentedObject; /// back up of the filtered object -#ifdef LIST_OF_VALID_PRS - QList> myValidPrs; /// cash of valid selection presentations - QList> myInvalidPrs; /// cash of invalid selection presentations -#else - // assume that one presentation selection presentation corresponds only one shape - NCollection_DataMap > myValidPrs; - NCollection_DataMap > myInvalidPrs; -#endif - - /// store to backup parameters of the model - ModuleBase_WidgetSelectorStore* myAttributeStore; -}; - -#endif /* MODULEBASE_WIDGETVALIDATED_H_ */ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: ModuleBase_WidgetValidated.h +// Created: 12 Mar 2015 +// Author: Natalia ERMOLAEVA + + +#ifndef MODULEBASE_WIDGETVALIDATED_H_ +#define MODULEBASE_WIDGETVALIDATED_H_ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +class QWidget; +class ModuleBase_IWorkshop; +class ModuleBase_ISelection; +class ModuleBase_WidgetSelectorStore; +class ModelAPI_Validator; +class Config_WidgetAPI; +class Handle_SelectMgr_EntityOwner; + +//#define LIST_OF_VALID_PRS + +/** +* \ingroup GUI +* Implementation of widget with validators and filters processing. +*/ +class MODULEBASE_EXPORT ModuleBase_WidgetValidated : public ModuleBase_ModelWidget +{ + Q_OBJECT + public: + /// Constructor + /// \param theParent the parent object + /// \param theWorkshop a reference to workshop + /// \param theData the widget configuation. The attribute of the model widget is obtained from + ModuleBase_WidgetValidated(QWidget* theParent, + ModuleBase_IWorkshop* theWorkshop, + const Config_WidgetAPI* theData); + virtual ~ModuleBase_WidgetValidated(); + + /// Checks all widget validator if the owner is valid. Firstly it checks custom widget validating, + /// next, the attribute's validating. It trying on the give selection to current attribute by + /// setting the value inside and calling validators. After this, the previous attribute value is + /// restored.The valid/invalid value is cashed. + /// \param theValue a selected presentation in the view + /// \return a boolean value + virtual bool isValidSelection(const std::shared_ptr& theValue); + + //! Returns data object by AIS + ObjectPtr findPresentedObject(const AISObjectPtr& theAIS) const; + + //! Clear all validated cash in the widget + void clearValidatedCash(); + + /// Returns true if the workshop validator filter has been already activated + /// \return boolean value + bool isFilterActivated() const; + +protected: + /// Checks whether all active viewer filters validate the presentation + /// \param thePrs a selected presentation in the view + /// \return a boolean value + virtual bool isValidInFilters(const std::shared_ptr& thePrs); + + /// Checks all attribute validators returns valid. It tries on the given selection + /// to current attribute by setting the value inside and calling validators. After this, + /// the previous attribute value is restored.The valid/invalid value is cashed. + /// \param theValue a selected presentation in the view + /// \param theAttribute the attribute + /// \return a boolean value + bool isValidSelectionForAttribute(const std::shared_ptr& theValue, + const AttributePtr& theAttribute); + + /// Retunrs attribute, which should be validated. In default implementation, + /// this is an attribute of ID + /// \return an attribute + virtual AttributePtr attribute() const; + + /// Creates a backup of the current values of the attribute + /// It should be realized in the specific widget because of different + /// parameters of the current attribute + /// \param theAttribute an attribute to be stored + virtual void storeAttributeValue(const AttributePtr& theAttribute); + + /// Creates a backup of the current values of the attribute + /// It should be realized in the specific widget because of different + /// parameters of the current attribute + /// \param theAttribute an attribute to be restored + /// \param theValid a boolean flag, if restore happens for valid parameters + virtual void restoreAttributeValue(const AttributePtr& theAttribute, const bool theValid); + + /// Checks the widget validity. By default, it returns true. + /// \param thePrs a selected presentation in the view + /// \return a boolean value + virtual bool isValidSelectionCustom(const std::shared_ptr& thePrs); + + /// Fills the attribute with the value of the selected owner + /// \param thePrs a selected owner + virtual bool setSelectionCustom(const std::shared_ptr& thePrs) = 0; + + /// Returns a list of selected presentations in the viewer and object browser + /// The presentations from the object browser are filtered by the AIS context filters + /// \return a list of presentations + QList> getFilteredSelected(); + + /// It obtains selection filters from the workshop and activates them in the active viewer + /// \param toActivate a flag about activation or deactivation the filters + /// \return true if the selection filter of the widget is activated in viewer context + bool activateFilters(const bool toActivate); + + /// Block the model flush of update and intialization of attribute + /// \param theAttribute an attribute of blocking + /// \param theToBlock flag whether the model is blocked or unblocked + /// \param isFlushesActived out value if model is blocked, in value if model is unblocked + /// to be used to restore flush state when unblocked + /// \param isAttributeSetInitializedBlocked out value if model is blocked + /// in value if model is unblocked to be used to restore previous state when unblocked + virtual void blockAttribute(const AttributePtr& theAttribute, const bool& theToBlock, + bool& isFlushesActived, bool& isAttributeSetInitializedBlocked); + +private: + /// Checks the current attibute in all attribute validators + /// \param theAttribute an attribute to be validated + /// \return true if all validators return that the attribute is valid + bool isValidAttribute(const AttributePtr& theAttribute) const; + +protected: + /// Gets the validity state of the presentation in an internal map. Returns true if the valid state of value is stored + /// \param theValue a viewer presentation + /// \param theValid a valid state + bool getValidState(const std::shared_ptr& theValue, bool& theValid); + + /// Store the validity state of the presentation in an internal map + /// \param theValue a viewer presentation + /// \param theValid a valid state + void storeValidState(const std::shared_ptr& theValue, const bool theValid); + +private: + /// Applies AIS context filters to the parameter list. The not approved presentations are + /// removed from the parameters. + /// \param theValues a list of presentations. + void filterPresentations(QList>& theValues); + + /// Remove subshapes of compsolids if whole compsolid is present. + /// \param theValues a list of presentations. + void filterCompSolids(QList>& theValues); + +protected: + /// Reference to workshop + ModuleBase_IWorkshop* myWorkshop; + /// The widget is in validation mode: store is performed, restore is not + bool myIsInValidate; + +private: + ObjectPtr myPresentedObject; /// back up of the filtered object +#ifdef LIST_OF_VALID_PRS + QList> myValidPrs; /// cash of valid selection presentations + QList> myInvalidPrs; /// cash of invalid selection presentations +#else + // assume that one presentation selection presentation corresponds only one shape + NCollection_DataMap > myValidPrs; + NCollection_DataMap > myInvalidPrs; +#endif + + /// store to backup parameters of the model + ModuleBase_WidgetSelectorStore* myAttributeStore; +}; + +#endif /* MODULEBASE_WIDGETVALIDATED_H_ */ diff --git a/src/PartSet/PartSet.h b/src/PartSet/PartSet.h index e39f0e728..fa6e6647c 100644 --- a/src/PartSet/PartSet.h +++ b/src/PartSet/PartSet.h @@ -1,20 +1,20 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -#ifndef PARTSET_H -#define PARTSET_H - -#if defined PARTSET_EXPORTS -#if defined WIN32 -#define PARTSET_EXPORT __declspec( dllexport ) -#else -#define PARTSET_EXPORT -#endif -#else -#if defined WIN32 -#define PARTSET_EXPORT __declspec( dllimport ) -#else -#define PARTSET_EXPORT -#endif -#endif - +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +#ifndef PARTSET_H +#define PARTSET_H + +#if defined PARTSET_EXPORTS +#if defined WIN32 +#define PARTSET_EXPORT __declspec( dllexport ) +#else +#define PARTSET_EXPORT +#endif +#else +#if defined WIN32 +#define PARTSET_EXPORT __declspec( dllimport ) +#else +#define PARTSET_EXPORT +#endif +#endif + #endif //PARTSET_H \ No newline at end of file diff --git a/src/PartSet/PartSet_SketcherMgr.cpp b/src/PartSet/PartSet_SketcherMgr.cpp index 5d607f93c..5d5a26e5b 100755 --- a/src/PartSet/PartSet_SketcherMgr.cpp +++ b/src/PartSet/PartSet_SketcherMgr.cpp @@ -1,1807 +1,1807 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: PartSet_SketcherMgr.cpp -// Created: 19 Dec 2014 -// Author: Vitaly SMETANNIKOV - -#include "PartSet_SketcherMgr.h" -#include "PartSet_SketcherReetntrantMgr.h" -#include "PartSet_Module.h" -#include "PartSet_MouseProcessor.h" -#include "PartSet_Tools.h" -#include "PartSet_WidgetSketchLabel.h" -#include "PartSet_WidgetEditor.h" -#include "PartSet_ResultSketchPrs.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -//#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -//#define DEBUG_DO_NOT_BY_ENTER -//#define DEBUG_SKETCHER_ENTITIES -//#define DEBUG_SKETCH_ENTITIES_ON_MOVE - -//#define DEBUG_CURSOR - -/// Fills attribute and result lists by the selected owner. In case if the attribute is found, -/// by the owner shape, it is put to the list. Otherwise if type of owner shape is edge, put the function -/// result as is to the list of results. -/// \param theOwner a viewer selected owner -/// \param theFeature a feature, where the attribute is searched -/// \param theSketch a current sketch -/// \param theSelectedAttribute an output list of attributes -/// \param theSelectedResults an output list of edge results -void getAttributesOrResults(const Handle(SelectMgr_EntityOwner)& theOwner, - const FeaturePtr& theFeature, const FeaturePtr& theSketch, - const ResultPtr& theResult, - std::set& aSelectedAttributes, - std::set& aSelectedResults) -{ - Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast(theOwner); - if (aBRepOwner.IsNull()) - return; - Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast( - aBRepOwner->Selectable()); - if (aBRepOwner->HasShape()) { - const TopoDS_Shape& aShape = aBRepOwner->Shape(); - TopAbs_ShapeEnum aShapeType = aShape.ShapeType(); - if (aShapeType == TopAbs_VERTEX) { - AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theFeature, - aShape, theSketch); - if (aPntAttr.get() != NULL) - aSelectedAttributes.insert(aPntAttr); - } - else if (aShapeType == TopAbs_EDGE && - aSelectedResults.find(theResult) == aSelectedResults.end()) { - aSelectedResults.insert(theResult); - } - } -} - -PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule) - : QObject(theModule), myModule(theModule), myIsDragging(false), myDragDone(false), - myIsMouseOverWindow(false), - myIsMouseOverViewProcessed(true), myPreviousUpdateViewerEnabled(true), - myIsPopupMenuActive(false) -{ - ModuleBase_IWorkshop* anIWorkshop = myModule->workshop(); - ModuleBase_IViewer* aViewer = anIWorkshop->viewer(); - - myPreviousDrawModeEnabled = true;//aViewer->isSelectionEnabled(); - - connect(aViewer, SIGNAL(mousePress(ModuleBase_IViewWindow*, QMouseEvent*)), - this, SLOT(onMousePressed(ModuleBase_IViewWindow*, QMouseEvent*))); - - connect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)), - this, SLOT(onMouseReleased(ModuleBase_IViewWindow*, QMouseEvent*))); - - connect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)), - this, SLOT(onMouseMoved(ModuleBase_IViewWindow*, QMouseEvent*))); - - connect(aViewer, SIGNAL(mouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)), - this, SLOT(onMouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*))); - - XGUI_ModuleConnector* aConnector = dynamic_cast(anIWorkshop); - XGUI_Workshop* aWorkshop = aConnector->workshop(); - connect(aWorkshop, SIGNAL(applicationStarted()), this, SLOT(onApplicationStarted())); - - myIsConstraintsShown[PartSet_Tools::Geometrical] = true; - myIsConstraintsShown[PartSet_Tools::Dimensional] = true; - myIsConstraintsShown[PartSet_Tools::Expressions] = false; -} - -PartSet_SketcherMgr::~PartSet_SketcherMgr() -{ - if (!myPlaneFilter.IsNull()) - myPlaneFilter.Nullify(); -} - -void PartSet_SketcherMgr::onEnterViewPort() -{ - // 1. if the mouse over window, update the next flag. Do not perform update visibility of - // created feature because it should be done in onMouseMove(). Some widgets watch - // the mouse move and use the cursor position to update own values. If the presentaion is - // redisplayed before this update, the feature presentation jumps from reset value to current. - myIsMouseOverWindow = true; - - #ifdef DEBUG_DO_NOT_BY_ENTER - return; - #endif - - if (canChangeCursor(getCurrentOperation())) { - QCursor* aCurrentCursor = QApplication::overrideCursor(); - if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) { - QApplication::setOverrideCursor(QCursor(Qt::CrossCursor)); -#ifdef DEBUG_CURSOR - qDebug("onEnterViewPort() : Qt::CrossCursor"); -#endif - } - } - - if (!isNestedCreateOperation(getCurrentOperation(), activeSketch())) - return; - - operationMgr()->onValidateOperation(); - - // we need change displayed state of the current operation feature - // if the feature is presentable, e.g. distance construction. It has no results, so workshop does - // not accept a signal about the result created. Nothing is shown until mouse is moved out/in view - // port. If the isDisplayed flag is true, the presentable feature is displayed as soon as the - // presentation becomes valid and redisplay happens - //ModuleBase_Operation* aOperation = getCurrentOperation(); - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (getCurrentOperation()); - if (aFOperation) { - FeaturePtr aFeature = aFOperation->feature(); - if (aFeature.get() && aFeature->data()->isValid()) { - visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature), false); - } - } -} - -void PartSet_SketcherMgr::onLeaveViewPort() -{ - myIsMouseOverViewProcessed = false; - myIsMouseOverWindow = false; - - #ifdef DEBUG_DO_NOT_BY_ENTER - return; - #endif - - if (canChangeCursor(getCurrentOperation())) { - QApplication::restoreOverrideCursor(); -#ifdef DEBUG_CURSOR - qDebug("onLeaveViewPort() : None"); -#endif - } - - if (!isNestedCreateOperation(getCurrentOperation(), activeSketch())) - return; - - // the method should be performed if the popup menu is called, - // the reset of the current widget should not happen - if (myIsPopupMenuActive) - return; - - // it is important to validate operation here only if sketch entity create operation is active - // because at this operation we reacts to the mouse leave/enter view port - operationMgr()->onValidateOperation(); - - // 2. if the mouse IS NOT over window, reset the active widget value and hide the presentation - ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); - XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); - XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); - // disable the viewer update in order to avoid visualization of redisplayed feature in viewer - // obtained after reset value - bool isEnableUpdateViewer = aDisplayer->enableUpdateViewer(false); - ModuleBase_ModelWidget* anActiveWidget = getActiveWidget(); - if (anActiveWidget) - anActiveWidget->reset(); - - // hides the presentation of the current operation feature - // the feature is to be erased here, but it is correct to call canDisplayObject because - // there can be additional check (e.g. editor widget in distance constraint) - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (getCurrentOperation()); - if (aFOperation) { - FeaturePtr aFeature = aFOperation->feature(); - visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature)); - } - // we should update viewer after the presentation are hidden in the viewer - // otherwise the reset presentation(line) appears in the viewer(by quick move from viewer to PP) - aDisplayer->enableUpdateViewer(isEnableUpdateViewer); -} - -void PartSet_SketcherMgr::onBeforeValuesChangedInPropertyPanel() -{ - if (!isNestedEditOperation(getCurrentOperation(), myModule->sketchMgr()->activeSketch()) || - myModule->sketchReentranceMgr()->isInternalEditActive()) - return; - // it is necessary to save current selection in order to restore it after the values are modifed - storeSelection(); - - ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); - XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); - XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); - myPreviousUpdateViewerEnabled = aDisplayer->enableUpdateViewer(false); -} - -void PartSet_SketcherMgr::onAfterValuesChangedInPropertyPanel() -{ - if (!isNestedEditOperation(getCurrentOperation(), myModule->sketchMgr()->activeSketch()) || - myModule->sketchReentranceMgr()->isInternalEditActive()) { - myModule->sketchReentranceMgr()->updateInternalEditActiveState(); - return; - } - // it is necessary to restore current selection in order to restore it after the values are modified - restoreSelection(); - myCurrentSelection.clear(); - - // 3. the flag to disable the update viewer should be set in order to avoid blinking in the - // viewer happens by deselect/select the modified objects. The flag should be restored after - // the selection processing. The update viewer should be also called. - ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); - XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); - XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); - aDisplayer->enableUpdateViewer(myPreviousUpdateViewerEnabled); - aDisplayer->updateViewer(); - - -} - -void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) -{ - if (myModule->sketchReentranceMgr()->processMousePressed(theWnd, theEvent)) - return; - - //get2dPoint(theWnd, theEvent, myClickedPoint); - - if (!(theEvent->buttons() & Qt::LeftButton)) - return; - - // Clear dragging mode - myIsDragging = false; - - ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); - ModuleBase_IViewer* aViewer = aWorkshop->viewer(); - if (!aViewer->canDragByMouse()) - return; - - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (getCurrentOperation()); - if (!aFOperation) - return; - - if (aFOperation->isEditOperation()) { - // If the current widget is a selector, do nothing, it processes the mouse press - ModuleBase_ModelWidget* anActiveWidget = getActiveWidget(); - if(anActiveWidget && anActiveWidget->isViewerSelector()) { - return; - } - } - - // Use only for sketch operations - if (myCurrentSketch) { - if (!PartSet_Tools::sketchPlane(myCurrentSketch)) - return; - - bool isSketcher = isSketchOperation(aFOperation); - bool isSketchOpe = isNestedSketchOperation(aFOperation); - - // Avoid non-sketch operations - if ((!isSketchOpe) && (!isSketcher)) - return; - - bool isEditing = aFOperation->isEditOperation(); - - // Ignore creation sketch operation - if ((!isSketcher) && (!isEditing)) - return; - - Handle(AIS_InteractiveContext) aContext = aViewer->AISContext(); - // Remember highlighted objects for editing - ModuleBase_ISelection* aSelect = aWorkshop->selection(); - - bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier); - storeSelection(!aHasShift); - - if (myCurrentSelection.empty()) { - if (isSketchOpe && (!isSketcher)) - // commit previous operation - if (!aFOperation->commit()) - aFOperation->abort(); - return; - } - // Init flyout point for radius rotation - FeaturePtr aFeature = myCurrentSelection.begin().key(); - - get2dPoint(theWnd, theEvent, myCurrentPoint); - if (isSketcher) { - myIsDragging = true; - myDragDone = false; - - myPreviousDrawModeEnabled = aViewer->enableDrawMode(false); - // selection should be restored before edit operation start to process the - // selected entities, e.g. selection of point(attribute on a line) should edit the point - restoreSelection(); - launchEditing(); - if (aFeature.get() != NULL) { - std::shared_ptr aSPFeature = - std::dynamic_pointer_cast(aFeature); - if (aSPFeature.get() && - (aSPFeature->getKind() == SketchPlugin_ConstraintRadius::ID() || - aSPFeature->getKind() == SketchPlugin_ConstraintAngle::ID())) { - DataPtr aData = aSPFeature->data(); - AttributePtr aAttr = aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()); - std::shared_ptr aFPAttr = - std::dynamic_pointer_cast(aAttr); - aFPAttr->setValue(myCurrentPoint.myCurX, myCurrentPoint.myCurY); - } - } - } else if (isSketchOpe && isEditing) { - // If selected another object commit current result - aFOperation->commit(); - - myIsDragging = true; - myDragDone = false; - - myPreviousDrawModeEnabled = aViewer->enableDrawMode(false); - // selection should be restored before edit operation start to process the - // selected entities, e.g. selection of point(attribute on a line) should edit the point - restoreSelection(); - launchEditing(); - if (aFeature.get() != NULL) { - std::shared_ptr aSPFeature = - std::dynamic_pointer_cast(aFeature); - if (aSPFeature.get() && - (aSPFeature->getKind() == SketchPlugin_ConstraintRadius::ID() || - aSPFeature->getKind() == SketchPlugin_ConstraintAngle::ID())) { - DataPtr aData = aSPFeature->data(); - AttributePtr aAttr = aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()); - std::shared_ptr aFPAttr = - std::dynamic_pointer_cast(aAttr); - aFPAttr->setValue(myCurrentPoint.myCurX, myCurrentPoint.myCurY); - } - } - restoreSelection(); - } - } -} - -void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) -{ - if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent)) - return; - - ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); - ModuleBase_IViewer* aViewer = aWorkshop->viewer(); - if (!aViewer->canDragByMouse()) - return; - ModuleBase_Operation* aOp = getCurrentOperation(); - if (aOp) { - if (isNestedSketchOperation(aOp)) { - // Only for sketcher operations - if (myIsDragging) { - if (myDragDone) { - myCurrentSelection.clear(); - } - } - } - } - - aWorkshop->viewer()->enableDrawMode(myPreviousDrawModeEnabled); - myIsDragging = false; - - ModuleBase_ModelWidget* anActiveWidget = getActiveWidget(); - PartSet_MouseProcessor* aProcessor = dynamic_cast(anActiveWidget); - if (aProcessor) - aProcessor->mouseReleased(theWnd, theEvent); -} - -void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) -{ -#ifdef DEBUG_SKETCH_ENTITIES_ON_MOVE - CompositeFeaturePtr aSketch = activeSketch(); - if (aSketch.get()) { - std::cout << "mouse move SKETCH FEATURES [" << aSketch->numberOfSubs() << "]:" << std::endl; - QStringList anInfo; - for (int i = 0, aNbSubs = aSketch->numberOfSubs(); i < aNbSubs; i++) { - //std::cout << getFeatureInfo(aSketch->subFeature(i), false) << std::endl; - anInfo.append(ModuleBase_Tools::objectInfo(aSketch->subFeature(i))); - } - QString anInfoStr = anInfo.join("\n"); - qDebug(QString("%1").arg(anInfo.size()).arg(anInfoStr).toStdString().c_str()); - } -#endif - - if (myModule->sketchReentranceMgr()->processMouseMoved(theWnd, theEvent)) - return; - - if (isNestedCreateOperation(getCurrentOperation(), activeSketch())) { - // 1. perform the widget mouse move functionality and display the presentation - // the mouse move should be processed in the widget, if it can in order to visualize correct - // presentation. These widgets correct the feature attribute according to the mouse position - ModuleBase_ModelWidget* anActiveWidget = myModule->activeWidget(); - PartSet_MouseProcessor* aProcessor = dynamic_cast(anActiveWidget); - if (aProcessor) - aProcessor->mouseMoved(theWnd, theEvent); - if (!myIsMouseOverViewProcessed) { - myIsMouseOverViewProcessed = true; - - // the feature is to be erased here, but it is correct to call canDisplayObject because - // there can be additional check (e.g. editor widget in distance constraint) - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (getCurrentOperation()); - if (aFOperation) { - FeaturePtr aFeature = aFOperation->feature(); - visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature)); - } - } - } - //myClickedPoint.clear(); - - if (myIsDragging) { - // 1. the current selection is saved in the mouse press method in order to restore it after moving - // 2. the enable selection in the viewer should be temporary switched off in order to ignore - // mouse press signal in the viewer(it call Select for AIS context and the dragged objects are - // deselected). This flag should be restored in the slot, processed the mouse release signal. - - ModuleBase_Operation* aCurrentOperation = getCurrentOperation(); - if (!aCurrentOperation) - return; - if (isSketchOperation(aCurrentOperation)) - return; // No edit operation activated - - Handle(V3d_View) aView = theWnd->v3dView(); - gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView); - Point aMousePnt; - get2dPoint(theWnd, theEvent, aMousePnt); - double dX = aMousePnt.myCurX - myCurrentPoint.myCurX; - double dY = aMousePnt.myCurY - myCurrentPoint.myCurY; - - ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); - XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); - XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); - // 3. the flag to disable the update viewer should be set in order to avoid blinking in the - // viewer happens by deselect/select the modified objects. The flag should be restored after - // the selection processing. The update viewer should be also called. - bool isEnableUpdateViewer = aDisplayer->enableUpdateViewer(false); - - static Events_ID aMoveEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED); - //static Events_ID aUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); - FeatureToSelectionMap::const_iterator anIt = myCurrentSelection.begin(), - aLast = myCurrentSelection.end(); - // 4. the features and attributes modification(move) - bool isModified = false; - for (; anIt != aLast; anIt++) { - FeaturePtr aFeature = anIt.key(); - - std::set anAttributes = anIt.value().first; - // Process selection by attribute: the priority to the attribute - if (!anAttributes.empty()) { - std::set::const_iterator anAttIt = anAttributes.begin(), - anAttLast = anAttributes.end(); - for (; anAttIt != anAttLast; anAttIt++) { - AttributePtr anAttr = *anAttIt; - if (anAttr.get() == NULL) - continue; - std::string aAttrId = anAttr->id(); - DataPtr aData = aFeature->data(); - if (aData->isValid()) { - std::shared_ptr aPoint = - std::dynamic_pointer_cast(aData->attribute(aAttrId)); - if (aPoint.get() != NULL) { - bool isImmutable = aPoint->setImmutable(true); - aPoint->move(dX, dY); - isModified = true; - ModelAPI_EventCreator::get()->sendUpdated(aFeature, aMoveEvent); - aPoint->setImmutable(isImmutable); - } - } - } - } else { - // Process selection by feature - std::shared_ptr aSketchFeature = - std::dynamic_pointer_cast(aFeature); - if (aSketchFeature) { - aSketchFeature->move(dX, dY); - isModified = true; - ModelAPI_EventCreator::get()->sendUpdated(aSketchFeature, aMoveEvent); - } - } - } - // the modified state of the current operation should be updated if there are features, which - // were changed here - if (isModified) { - aCurrentOperation->onValuesChanged(); - } - Events_Loop::loop()->flush(aMoveEvent); // up all move events - to be processed in the solver - //Events_Loop::loop()->flush(aUpdateEvent); // up update events - to redisplay presentations - - // 5. it is necessary to save current selection in order to restore it after the features moving - restoreSelection(); - // 6. restore the update viewer flag and call this update - aDisplayer->enableUpdateViewer(isEnableUpdateViewer); - aDisplayer->updateViewer(); - - myDragDone = true; - myCurrentPoint = aMousePnt; - } -} - -void PartSet_SketcherMgr::onMouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) -{ - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (getCurrentOperation()); - if (aFOperation && aFOperation->isEditOperation()) { - std::string aId = aFOperation->id().toStdString(); - if (isDistanceOperation(aFOperation)) - { - // Activate dimension value editing on double click - ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel(); - QList aWidgets = aPanel->modelWidgets(); - // Find corresponded widget to activate value editing - foreach (ModuleBase_ModelWidget* aWgt, aWidgets) { - if (aWgt->attributeID() == SketchPlugin_Constraint::VALUE() || - aWgt->attributeID() == SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()) { - PartSet_WidgetEditor* anEditor = dynamic_cast(aWgt); - if (anEditor) - anEditor->showPopupEditor(); - return; - } - } - } - } -} - -void PartSet_SketcherMgr::onApplicationStarted() -{ - ModuleBase_IWorkshop* anIWorkshop = myModule->workshop(); - XGUI_ModuleConnector* aConnector = dynamic_cast(anIWorkshop); - XGUI_Workshop* aWorkshop = aConnector->workshop(); - PartSet_SketcherReetntrantMgr* aReentranceMgr = myModule->sketchReentranceMgr(); - - XGUI_PropertyPanel* aPropertyPanel = aWorkshop->propertyPanel(); - if (aPropertyPanel) { - //connect(aPropertyPanel, SIGNAL(beforeWidgetActivated(ModuleBase_ModelWidget*)), - // this, SLOT(onBeforeWidgetActivated(ModuleBase_ModelWidget*))); - - connect(aPropertyPanel, SIGNAL(noMoreWidgets(const std::string&)), - aReentranceMgr, SLOT(onNoMoreWidgets(const std::string&))); - connect(aPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)), - aReentranceMgr, SLOT(onWidgetActivated())); - } - - XGUI_ViewerProxy* aViewerProxy = aWorkshop->viewer(); - connect(aViewerProxy, SIGNAL(enterViewPort()), this, SLOT(onEnterViewPort())); - connect(aViewerProxy, SIGNAL(leaveViewPort()), this, SLOT(onLeaveViewPort())); - - XGUI_ContextMenuMgr* aContextMenuMgr = aWorkshop->contextMenuMgr(); - connect(aContextMenuMgr, SIGNAL(beforeContextMenu()), this, SLOT(onBeforeContextMenu())); - connect(aContextMenuMgr, SIGNAL(afterContextMenu()), this, SLOT(onAfterContextMenu())); -} - -//void PartSet_SketcherMgr::onBeforeWidgetActivated(ModuleBase_ModelWidget* theWidget) -//{ - //if (!myClickedPoint.myIsInitialized) - // return; - - //ModuleBase_Operation* aOperation = getCurrentOperation(); - // the distance constraint feature should not use the clickedd point - // this is workaround in order to don't throw down the flyout point value, - // set by execute() method of these type of features - //if (isDistanceOperation(aOperation)) - // return; - - //PartSet_WidgetPoint2D* aPnt2dWgt = dynamic_cast(theWidget); - //if (aPnt2dWgt) { - // aPnt2dWgt->setPoint(myClickedPoint.myCurX, myClickedPoint.myCurY); - //} -//} - -void PartSet_SketcherMgr::onBeforeContextMenu() -{ - myIsPopupMenuActive = true; -} - -void PartSet_SketcherMgr::onAfterContextMenu() -{ - myIsPopupMenuActive = false; -} - -void PartSet_SketcherMgr::get2dPoint(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent, - Point& thePoint) -{ - Handle(V3d_View) aView = theWnd->v3dView(); - gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView); - double aX, anY; - PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, aX, anY); - thePoint.setValue(aX, anY); -} - -void PartSet_SketcherMgr::launchEditing() -{ - if (!myCurrentSelection.empty()) { - FeaturePtr aFeature = myCurrentSelection.begin().key(); - std::shared_ptr aSPFeature = - std::dynamic_pointer_cast(aFeature); - if (aSPFeature && (!aSPFeature->isExternal())) { - myModule->editFeature(aSPFeature); - } - } -} - -bool PartSet_SketcherMgr::sketchSolverError() -{ - bool anError = false; - CompositeFeaturePtr aSketch = activeSketch(); - if (aSketch.get()) { - AttributeStringPtr aAttributeString = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR()); - anError = !aAttributeString->value().empty(); - } - return anError; -} - -QString PartSet_SketcherMgr::getFeatureError(const FeaturePtr& theFeature) -{ - std::string anError = ""; - if (!theFeature.get() || !theFeature->data()->isValid()) - return anError.c_str(); - - CompositeFeaturePtr aSketch = activeSketch(); - if (aSketch.get() && aSketch == theFeature) { - AttributeStringPtr aAttributeString = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR()); - anError = aAttributeString->value(); - ModuleBase_Tools::translate(aSketch->getKind(), anError); - } - return anError.c_str(); -} - -void PartSet_SketcherMgr::clearClickedFlags() -{ - //myClickedPoint.clear(); - myCurrentPoint.clear(); -} - -const QStringList& PartSet_SketcherMgr::replicationsIdList() -{ - static QStringList aReplicationIds; - if (aReplicationIds.size() == 0) { - aReplicationIds << SketchPlugin_ConstraintMirror::ID().c_str(); - aReplicationIds << SketchPlugin_MultiRotation::ID().c_str(); - aReplicationIds << SketchPlugin_MultiTranslation::ID().c_str(); - } - return aReplicationIds; -} - -const QStringList& PartSet_SketcherMgr::constraintsIdList() -{ - static QStringList aConstraintIds; - if (aConstraintIds.size() == 0) { - aConstraintIds << SketchPlugin_ConstraintLength::ID().c_str(); - aConstraintIds << SketchPlugin_ConstraintDistance::ID().c_str(); - aConstraintIds << SketchPlugin_ConstraintRigid::ID().c_str(); - aConstraintIds << SketchPlugin_ConstraintRadius::ID().c_str(); - aConstraintIds << SketchPlugin_ConstraintPerpendicular::ID().c_str(); - aConstraintIds << SketchPlugin_ConstraintParallel::ID().c_str(); - aConstraintIds << SketchPlugin_ConstraintHorizontal::ID().c_str(); - aConstraintIds << SketchPlugin_ConstraintVertical::ID().c_str(); - aConstraintIds << SketchPlugin_ConstraintEqual::ID().c_str(); - aConstraintIds << SketchPlugin_ConstraintTangent::ID().c_str(); - aConstraintIds << SketchPlugin_ConstraintCoincidence::ID().c_str(); - aConstraintIds << SketchPlugin_ConstraintAngle::ID().c_str(); - aConstraintIds << SketchPlugin_ConstraintCollinear::ID().c_str(); - aConstraintIds << SketchPlugin_ConstraintMiddle::ID().c_str(); - aConstraintIds << SketchPlugin_ConstraintMirror::ID().c_str(); - aConstraintIds << SketchPlugin_MultiTranslation::ID().c_str(); - aConstraintIds << SketchPlugin_MultiRotation::ID().c_str(); - } - return aConstraintIds; -} - -void PartSet_SketcherMgr::sketchSelectionModes(QIntList& theModes) -{ - theModes.clear(); - - theModes.append(SketcherPrs_Tools::Sel_Dimension_Text); - theModes.append(SketcherPrs_Tools::Sel_Dimension_Line); - theModes.append(SketcherPrs_Tools::Sel_Constraint); - theModes.append(TopAbs_VERTEX); - theModes.append(TopAbs_EDGE); -} - -Handle(AIS_InteractiveObject) PartSet_SketcherMgr::createPresentation(const ResultPtr& theResult) -{ - Handle(AIS_InteractiveObject) aPrs; - - FeaturePtr aFeature = ModelAPI_Feature::feature(theResult); - if (aFeature.get() && aFeature->getKind() == SketchPlugin_Sketch::ID()) { - aPrs = new PartSet_ResultSketchPrs(theResult); - } - return aPrs; -} - -bool PartSet_SketcherMgr::isSketchOperation(ModuleBase_Operation* theOperation) -{ - return theOperation && theOperation->id().toStdString() == SketchPlugin_Sketch::ID(); -} - -bool PartSet_SketcherMgr::isNestedSketchOperation(ModuleBase_Operation* theOperation) const -{ - bool aNestedSketch = false; - - FeaturePtr anActiveSketch = activeSketch(); - if (anActiveSketch.get() && theOperation) { - ModuleBase_Operation* aSketchOperation = operationMgr()->findOperation( - anActiveSketch->getKind().c_str()); - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (theOperation); - if (aSketchOperation && aFOperation) { - FeaturePtr aFeature = aFOperation->feature(); - if (aFeature.get()) { - QStringList aGrantedOpIds = aSketchOperation->grantedOperationIds(); - aNestedSketch = aGrantedOpIds.contains(aFeature->getKind().c_str()); - } - } - } - return aNestedSketch; -} - -bool PartSet_SketcherMgr::isNestedCreateOperation(ModuleBase_Operation* theOperation, - const CompositeFeaturePtr& theSketch) const -{ - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (theOperation); - return aFOperation && !aFOperation->isEditOperation() && - isNestedSketchOperation(aFOperation); -} - -bool PartSet_SketcherMgr::isNestedEditOperation(ModuleBase_Operation* theOperation, - const CompositeFeaturePtr& theSketch) const -{ - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (theOperation); - return aFOperation && aFOperation->isEditOperation() && - isNestedSketchOperation(aFOperation); -} - -bool PartSet_SketcherMgr::isEntity(const std::string& theId) -{ - return (theId == SketchPlugin_Line::ID()) || - (theId == SketchPlugin_Point::ID()) || - (theId == SketchPlugin_Arc::ID()) || - (theId == SketchPlugin_Circle::ID()); -} - -bool PartSet_SketcherMgr::isDistanceOperation(ModuleBase_Operation* theOperation) -{ - std::string anId = theOperation ? theOperation->id().toStdString() : ""; - - return isDistanceKind(anId); -} - -bool PartSet_SketcherMgr::isDistanceKind(std::string& theKind) -{ - return (theKind == SketchPlugin_ConstraintLength::ID()) || - (theKind == SketchPlugin_ConstraintDistance::ID()) || - (theKind == SketchPlugin_ConstraintRadius::ID()) || - (theKind == SketchPlugin_ConstraintAngle::ID()); -} - -void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation) -{ - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (getCurrentOperation()); - if (!aFOperation) - return; - - myModule->onViewTransformed(); - - // Display all sketcher sub-Objects - myCurrentSketch = std::dynamic_pointer_cast(aFOperation->feature()); - XGUI_ModuleConnector* aConnector = dynamic_cast(myModule->workshop()); - - // Hide sketcher result - std::list aResults = myCurrentSketch->results(); - std::list::const_iterator aIt; - for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { - (*aIt)->setDisplayed(false); - } - myCurrentSketch->setDisplayed(false); - - // Remove invalid sketch entities - std::set anInvalidFeatures; - ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators(); - for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) { - FeaturePtr aFeature = myCurrentSketch->subFeature(i); - if (aFeature.get()) { - if (!aFactory->validate(aFeature)) - anInvalidFeatures.insert(aFeature); - } - } - if (!anInvalidFeatures.empty()) { - std::map > aReferences; - ModelAPI_Tools::findAllReferences(anInvalidFeatures, aReferences, false); - - std::set::const_iterator anIt = anInvalidFeatures.begin(), - aLast = anInvalidFeatures.end(); - // separate features to references to parameter features and references to others - QStringList anInvalidFeatureNames; - for (; anIt != aLast; anIt++) { - FeaturePtr aFeature = *anIt; - if (aFeature.get()) - anInvalidFeatureNames.append(aFeature->name().c_str()); - } - std::string aPrefixInfo = QString("Invalid features of the sketch will be deleted: %1.\n\n"). - arg(anInvalidFeatureNames.join(", ")).toStdString().c_str(); - std::set aFeatureRefsToDelete; - if (ModuleBase_Tools::askToDelete(anInvalidFeatures, aReferences, aConnector->desktop(), - aFeatureRefsToDelete, aPrefixInfo)) { - if (!aFeatureRefsToDelete.empty()) - anInvalidFeatures.insert(aFeatureRefsToDelete.begin(), aFeatureRefsToDelete.end()); - ModelAPI_Tools::removeFeatures(anInvalidFeatures, true); - Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); - // TODO: call the next method in the XGUI_OperationMgr::onOperationStarted(). - workshop()->errorMgr()->updateAcceptAllAction(myCurrentSketch); - } - } - - // Display sketcher objects - QStringList anInfo; - for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) { - FeaturePtr aFeature = myCurrentSketch->subFeature(i); -#ifdef DEBUG_SKETCHER_ENTITIES - anInfo.append(ModuleBase_Tools::objectInfo(aFeature)); -#endif - std::list aResults = aFeature->results(); - std::list::const_iterator aIt; - for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { - (*aIt)->setDisplayed(true); - } - aFeature->setDisplayed(true); - } -#ifdef DEBUG_SKETCHER_ENTITIES - QString anInfoStr = anInfo.join(";\t"); - qDebug(QString("startSketch: %1, %2").arg(anInfo.size()).arg(anInfoStr).toStdString().c_str()); -#endif - - if(myCirclePointFilter.IsNull()) { - myCirclePointFilter = new PartSet_CirclePointFilter(myModule->workshop()); - } - - myModule->workshop()->viewer()->addSelectionFilter(myCirclePointFilter); - - if (myPlaneFilter.IsNull()) - myPlaneFilter = new ModuleBase_ShapeInPlaneFilter(); - - myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter); - bool aHasPlane = false; - std::shared_ptr aPln; - aPln = PartSet_Tools::sketchPlane(myCurrentSketch); - myPlaneFilter->setPlane(aPln); - - Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); - // all displayed objects should be activated in current selection modes according to switched - // plane filter - if (aPln.get()) - aConnector->activateModuleSelectionModes(); -} - -void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation) -{ - myIsMouseOverWindow = false; - myIsConstraintsShown[PartSet_Tools::Geometrical] = true; - myIsConstraintsShown[PartSet_Tools::Dimensional] = true; - myIsConstraintsShown[PartSet_Tools::Expressions] = false; - - XGUI_ModuleConnector* aConnector = dynamic_cast(myModule->workshop()); - - DataPtr aData = myCurrentSketch->data(); - if (!aData->isValid()) { - XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); - // The sketch was aborted - myCurrentSketch = CompositeFeaturePtr(); - // TODO: move this outside of if-else - myModule->workshop()->viewer()->removeSelectionFilter(myCirclePointFilter); - myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter); - - // Erase all sketcher objects - QObjectPtrList aObjects = aDisplayer->displayedObjects(); - foreach (ObjectPtr aObj, aObjects) { - DataPtr aObjData = aObj->data(); - if (!aObjData->isValid()) - aObj->setDisplayed(false); - } - } - else { - // Hide all sketcher sub-Objects - for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) { - FeaturePtr aFeature = myCurrentSketch->subFeature(i); - std::list aResults = aFeature->results(); - std::list::const_iterator aIt; - for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { - (*aIt)->setDisplayed(false); - } - aFeature->setDisplayed(false); - } - // Display sketcher result - std::list aResults = myCurrentSketch->results(); - std::list::const_iterator aIt; - Events_Loop* aLoop = Events_Loop::loop(); - static Events_ID aDispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); - - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (theOperation); - for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { - if (!aFOperation->isDisplayedOnStart(*aIt)) { - (*aIt)->setDisplayed(true); - // this display event is needed because sketch already may have "displayed" state, - // but not displayed while it is still active (issue 613, abort of existing sketch) - ModelAPI_EventCreator::get()->sendUpdated(*aIt, aDispEvent); - } - } - if (!aFOperation->isDisplayedOnStart(myCurrentSketch)) - myCurrentSketch->setDisplayed(true); - - myCurrentSketch = CompositeFeaturePtr(); - - myModule->workshop()->viewer()->removeSelectionFilter(myCirclePointFilter); - myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter); - - Events_Loop::loop()->flush(aDispEvent); - } - // restore the module selection modes, which were changed on startSketch - aConnector->activateModuleSelectionModes(); -} - -void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation) -{ - if (canChangeCursor(theOperation) && myIsMouseOverWindow) { - QCursor* aCurrentCursor = QApplication::overrideCursor(); - if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) { - QApplication::setOverrideCursor(QCursor(Qt::CrossCursor)); -#ifdef DEBUG_CURSOR - qDebug("startNestedSketch() : Qt::CrossCursor"); -#endif - } - } -} - -void PartSet_SketcherMgr::stopNestedSketch(ModuleBase_Operation* theOperation) -{ - myIsMouseOverViewProcessed = true; - operationMgr()->onValidateOperation(); - // when sketch nested operation is stopped the cursor should be restored unconditionally - //if (canChangeCursor(theOperation)) { - QApplication::restoreOverrideCursor(); -#ifdef DEBUG_CURSOR - qDebug("stopNestedSketch() : None"); -#endif - //} - /// improvement to deselect automatically all eventual selected objects, when - // returning to the neutral point of the Sketcher - workshop()->selector()->clearSelection(); -} - -void PartSet_SketcherMgr::commitNestedSketch(ModuleBase_Operation* theOperation) -{ - if (isNestedCreateOperation(theOperation, activeSketch())) { - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (theOperation); - if (aFOperation) { - FeaturePtr aFeature = aFOperation->feature(); - // it is necessary to check the the feature data validity because - // some kind of features are removed by an operation commit(the macro state of a feature) - if (aFeature.get() && aFeature->data()->isValid()) { - visualizeFeature(aFeature, aFOperation->isEditOperation(), true); - } - } - } -} - -void PartSet_SketcherMgr::activatePlaneFilter(const bool& toActivate) -{ - if (toActivate) - myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter); - else - myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter); -} - -bool PartSet_SketcherMgr::operationActivatedByPreselection() -{ - bool isOperationStopped = false; - ModuleBase_Operation* anOperation = getCurrentOperation(); - if(anOperation && isNestedSketchOperation(anOperation)) { - // Set final definitions if they are necessary - //propertyPanelDefined(aOperation); - /// Commit sketcher operations automatically - /// distance operation are able to show popup editor to modify the distance value - /// after entering the value, the operation should be committed/aborted(by Esc key) - bool aCanCommitOperation = true; - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (anOperation); - if (aFOperation && PartSet_SketcherMgr::isDistanceOperation(aFOperation)) { - bool aValueAccepted = setDistanceValueByPreselection(anOperation, myModule->workshop(), - aCanCommitOperation); - if (!aValueAccepted) - return isOperationStopped; - } - - if (aCanCommitOperation) - isOperationStopped = anOperation->commit(); - else { - anOperation->abort(); - isOperationStopped = true; - } - } - return isOperationStopped; -} - -bool PartSet_SketcherMgr::canUndo() const -{ - return isNestedCreateOperation(getCurrentOperation(), activeSketch()); -} - -bool PartSet_SketcherMgr::canRedo() const -{ - return isNestedCreateOperation(getCurrentOperation(), activeSketch()); -} - -bool PartSet_SketcherMgr::canEraseObject(const ObjectPtr& theObject) const -{ - bool aCanErase = true; - // when the sketch operation is active, results of sketch sub-feature can not be hidden - if (myCurrentSketch.get()) { - return !isObjectOfSketch(theObject); - } - return aCanErase; -} - -bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const -{ - bool aCanDisplay = true; - - bool aHasActiveSketch = activeSketch().get() != NULL; - if (aHasActiveSketch) { - // 1. the sketch feature should not be displayed during the sketch active operation - // it is hidden by a sketch operation start and shown by a sketch stop, just the sketch - // nested features can be visualized - FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); - if (aFeature.get() != NULL && aFeature == activeSketch()) { - aCanDisplay = false; - } - std::shared_ptr aSketchFeature = - std::dynamic_pointer_cast(aFeature); - /// some sketch entities should be never shown, e.g. projection feature - if (aSketchFeature.get()) - aCanDisplay = aSketchFeature->canBeDisplayed(); - } - else { // there are no an active sketch - // 2. sketch sub-features should not be visualized if the sketch operation is not active - FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); - if (aFeature.get() != NULL) { - std::shared_ptr aSketchFeature = - std::dynamic_pointer_cast(aFeature); - if (aSketchFeature.get()) { - aCanDisplay = false; - } - } - } - - // 3. the method should not filter the objects, which are not related to the current operation. - // The object is filtered just if it is a current operation feature or this feature result - if (aCanDisplay) { - bool isObjectFound = false; - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (getCurrentOperation()); - if (aFOperation) { - FeaturePtr aFeature = aFOperation->feature(); - if (aFeature.get()) { - std::list aResults = aFeature->results(); - if (theObject == aFeature) - isObjectFound = true; - else { - std::list::const_iterator anIt = aResults.begin(), aLast = aResults.end(); - for (; anIt != aLast && !isObjectFound; anIt++) { - isObjectFound = *anIt == theObject; - } - } - } - } - if (isObjectFound) { - // 4. For created nested feature operation do not display the created feature if - // the mouse curstor leaves the OCC window. - // The correction cases, which ignores this condition: - // a. the property panel values modification - // b. the popup menu activated - // c. widget editor control - #ifndef DEBUG_DO_NOT_BY_ENTER - if (isNestedCreateOperation(getCurrentOperation(), activeSketch())) { - ModuleBase_ModelWidget* anActiveWidget = getActiveWidget(); - ModuleBase_WidgetEditor* anEditorWdg = anActiveWidget ? dynamic_cast(anActiveWidget) : 0; - // the active widget editor should not influence here. The presentation should be visible always - // when this widget is active. - if (!anEditorWdg && !myIsPopupMenuActive) { - // during a nested create operation, the feature is redisplayed only if the mouse over view - // of there was a value modified in the property panel after the mouse left the view - aCanDisplay = canDisplayCurrentCreatedFeature(); - } - } - #endif - } - } - - // checks the sketcher constraints visibility according to active sketch check box states - if (aCanDisplay) { - bool aProcessed = false; - FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); - if (aFeature.get()) { - bool aConstraintDisplayed = canDisplayConstraint(aFeature, PartSet_Tools::Any, aProcessed); - if (aProcessed) - aCanDisplay = aConstraintDisplayed; - } - } - - return aCanDisplay; -} - -bool PartSet_SketcherMgr::canDisplayConstraint(const FeaturePtr& theFeature, - const PartSet_Tools::ConstraintVisibleState& theState, - bool& isProcessed) const -{ - bool aSwitchedOn = true; - - const QStringList& aConstrIds = constraintsIdList(); - - std::string aKind = theFeature->getKind(); - if (aConstrIds.contains(QString(aKind.c_str()))) { - bool isTypedConstraint = false; - - switch (theState) { - case PartSet_Tools::Dimensional: { - bool isDistance = isDistanceKind(aKind); - if (isDistance) { - isProcessed = true; - aSwitchedOn = myIsConstraintsShown[theState]; - } - } - break; - case PartSet_Tools::Geometrical: { - bool isGeometrical = !isDistanceKind(aKind); - if (isGeometrical) { - isProcessed = true; - aSwitchedOn = myIsConstraintsShown[theState]; - } - } - break; - case PartSet_Tools::Any: { - isProcessed = true; - bool isDistance = isDistanceKind(aKind); - if (isDistance) - aSwitchedOn = myIsConstraintsShown[PartSet_Tools::Dimensional]; - else - aSwitchedOn = myIsConstraintsShown[PartSet_Tools::Geometrical]; - } - break; - default: - break; - } - } - return aSwitchedOn; -} - -/*void PartSet_SketcherMgr::processHiddenObject(const std::list& theObjects) -{ - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (getCurrentOperation()); - if (aFOperation && myCurrentSketch.get()) { - // find results of the current operation - // these results should not be proposed to be deleted - FeaturePtr anOperationFeature = aFOperation->feature(); - std::list anOperationResultList = anOperationFeature->results(); - std::set anOperationResults; - std::list::const_iterator aRIt = anOperationResultList.begin(), - aRLast = anOperationResultList.end(); - for (; aRIt != aRLast; aRIt++) - anOperationResults.insert(*aRIt); - - std::set anObjectsToBeDeleted; - QStringList anObjectsToBeDeletedNames; - std::list::const_iterator anIt = theObjects.begin(), aLast = theObjects.end(); - for (; anIt != aLast; anIt++) { - ObjectPtr anObject = *anIt; - bool aCanErase = true; - // when the sketch operation is active, results of sketch sub-feature can not be hidden - ResultPtr aResult = std::dynamic_pointer_cast(anObject); - // the result is found between current feature results - if (anOperationResults.find(aResult) != anOperationResults.end()) - continue; - - if (aResult.get()) { - // Display sketcher objects - for (int i = 0; i < myCurrentSketch->numberOfSubs() && aCanErase; i++) { - FeaturePtr aFeature = myCurrentSketch->subFeature(i); - std::list aResults = aFeature->results(); - std::list::const_iterator anIt; - for (anIt = aResults.begin(); anIt != aResults.end() && aCanErase; ++anIt) { - aCanErase = *anIt != aResult; - } - } - } - if (!aCanErase) { - FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); - if (aFeature.get() && anObjectsToBeDeleted.find(aFeature) == anObjectsToBeDeleted.end()) { - anObjectsToBeDeleted.insert(aFeature); - anObjectsToBeDeletedNames.append(aFeature->name().c_str()); - } - } - } - if (!anObjectsToBeDeleted.empty()) { - QString aFeatureNames = anObjectsToBeDeletedNames.join(", "); - QString aMessage = tr("The following features have incorrect presentation and \ -will be hidden: %1. Would you like to delete them?") - .arg(aFeatureNames); - int anAnswer = QMessageBox::question(qApp->activeWindow(), tr("Features hide"), - aMessage, QMessageBox::Ok | QMessageBox::Cancel, - QMessageBox::Cancel); - if (anAnswer == QMessageBox::Ok) { - QObjectPtrList anObjects; - std::set::const_iterator anIt = anObjectsToBeDeleted.begin(), - aLast = anObjectsToBeDeleted.end(); - for (; anIt != aLast; anIt++) - anObjects.append(*anIt); - SessionPtr aMgr = ModelAPI_Session::get(); - DocumentPtr aDoc = aMgr->activeDocument(); - bool aIsOp = aMgr->isOperation(); - if (!aIsOp) - aMgr->startOperation(); - workshop()->deleteFeatures(anObjects); - //static Events_ID aDeletedEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED); - //static Events_ID aRedispEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY); - //Events_Loop::loop()->flush(aDeletedEvent); - //Events_Loop::loop()->flush(aRedispEvent); - - if (!aIsOp) - aMgr->finishOperation(); - } - } - } -}*/ - -bool PartSet_SketcherMgr::canDisplayCurrentCreatedFeature() const -{ - bool aCanDisplay = myIsMouseOverWindow; - if (!aCanDisplay) { - ModuleBase_ModelWidget* anActiveWidget = getActiveWidget(); - if (anActiveWidget) - aCanDisplay = anActiveWidget->getValueState() == ModuleBase_ModelWidget::Stored; - } - return aCanDisplay; -} - -bool PartSet_SketcherMgr::canChangeCursor(ModuleBase_Operation* theOperation) const -{ - return isNestedCreateOperation(theOperation, activeSketch()) || - myModule->sketchReentranceMgr()->isInternalEditActive(); -} - -const QMap& PartSet_SketcherMgr::showConstraintStates() -{ - return myIsConstraintsShown; -} - -bool PartSet_SketcherMgr::isObjectOfSketch(const ObjectPtr& theObject) const -{ - bool isFoundObject = false; - - FeaturePtr anObjectFeature = ModelAPI_Feature::feature(theObject); - if (anObjectFeature.get()) { - int aSize = myCurrentSketch->numberOfSubs(); - for (int i = 0; i < myCurrentSketch->numberOfSubs() && !isFoundObject; i++) { - FeaturePtr aCurrentFeature = myCurrentSketch->subFeature(i); - isFoundObject = myCurrentSketch->subFeature(i) == anObjectFeature; - } - } - return isFoundObject; -} - -void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr& thePln) -{ - if (myPlaneFilter.IsNull()) - myPlaneFilter = new ModuleBase_ShapeInPlaneFilter(); - - myPlaneFilter->setPlane(thePln); -} - -bool PartSet_SketcherMgr::setDistanceValueByPreselection(ModuleBase_Operation* theOperation, - ModuleBase_IWorkshop* theWorkshop, - bool& theCanCommitOperation) -{ - bool isValueAccepted = false; - theCanCommitOperation = false; - - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (theOperation); - FeaturePtr aFeature = aFOperation->feature(); - // editor is shown only if all attribute references are filled by preseletion - bool anAllRefAttrInitialized = true; - - std::list aRefAttrs = aFeature->data()->attributes( - ModelAPI_AttributeRefAttr::typeId()); - std::list::const_iterator anIt = aRefAttrs.begin(), aLast = aRefAttrs.end(); - for (; anIt != aLast && anAllRefAttrInitialized; anIt++) { - anAllRefAttrInitialized = (*anIt)->isInitialized(); - } - if (anAllRefAttrInitialized) { - // Activate dimension value editing on double click - ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel(); - QList aWidgets = aPanel->modelWidgets(); - // Find corresponded widget to activate value editing - foreach (ModuleBase_ModelWidget* aWgt, aWidgets) { - if (aWgt->attributeID() == "ConstraintValue") { - // the featue should be displayed in order to find the AIS text position, - // the place where the editor will be shown - aFeature->setDisplayed(true); - /// the execute is necessary to perform in the feature compute for flyout position - aFeature->execute(); - - Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED)); - Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); - - PartSet_WidgetEditor* anEditor = dynamic_cast(aWgt); - if (anEditor) { - int aX = 0, anY = 0; - - XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(theWorkshop); - XGUI_Displayer* aDisplayer = aWorkshop->displayer(); - AISObjectPtr anAIS = aDisplayer->getAISObject(aFeature); - Handle(AIS_InteractiveObject) anAISIO; - if (anAIS.get() != NULL) { - anAISIO = anAIS->impl(); - } - if (anAIS.get() != NULL) { - Handle(AIS_InteractiveObject) anAISIO = anAIS->impl(); - - if (!anAISIO.IsNull()) { - Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast(anAISIO); - if (!aDim.IsNull()) { - gp_Pnt aPosition = aDim->GetTextPosition(); - - ModuleBase_IViewer* aViewer = aWorkshop->viewer(); - Handle(V3d_View) aView = aViewer->activeView(); - int aCX, aCY; - aView->Convert(aPosition.X(), aPosition.Y(), aPosition.Z(), aCX, aCY); - - QWidget* aViewPort = aViewer->activeViewPort(); - QPoint aGlPoint = aViewPort->mapToGlobal(QPoint(aCX, aCY)); - aX = aGlPoint.x(); - anY = aGlPoint.y(); - } - } - anEditor->setCursorPosition(aX, anY); - isValueAccepted = anEditor->showPopupEditor(false); - theCanCommitOperation = true; - } - } - } - } - } - return isValueAccepted; -} - -void PartSet_SketcherMgr::getSelectionOwners(const FeaturePtr& theFeature, - const FeaturePtr& theSketch, - ModuleBase_IWorkshop* theWorkshop, - const FeatureToSelectionMap& theSelection, - SelectMgr_IndexedMapOfOwner& theOwnersToSelect) -{ - if (theFeature.get() == NULL) - return; - - FeatureToSelectionMap::const_iterator anIt = theSelection.find(theFeature); - std::set aSelectedAttributes = anIt.value().first; - std::set aSelectedResults = anIt.value().second; - - ModuleBase_IViewer* aViewer = theWorkshop->viewer(); - - XGUI_ModuleConnector* aConnector = dynamic_cast(theWorkshop); - XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); - - // 1. found the feature's owners. Check the AIS objects of the constructions - AISObjectPtr aAISObj = aDisplayer->getAISObject(theFeature); - if (aAISObj.get() != NULL && aSelectedAttributes.empty() && aSelectedResults.empty()) { - Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl(); - - SelectMgr_IndexedMapOfOwner aSelectedOwners; - aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners); - for (Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++) { - Handle(SelectMgr_EntityOwner) anOwner = aSelectedOwners(i); - if (!anOwner.IsNull()) - theOwnersToSelect.Add(anOwner); - } - } - - // 2. found the feature results's owners - std::list aResults = theFeature->results(); - std::list::const_iterator aIt; - for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) - { - ResultPtr aResult = *aIt; - AISObjectPtr aAISObj = aDisplayer->getAISObject(aResult); - if (aAISObj.get() == NULL) - continue; - Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl(); - - SelectMgr_IndexedMapOfOwner aSelectedOwners; - aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners); - for ( Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++ ) { - Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast(aSelectedOwners(i)); - if ( anOwner.IsNull() || !anOwner->HasShape() ) - continue; - const TopoDS_Shape& aShape = anOwner->Shape(); - TopAbs_ShapeEnum aShapeType = aShape.ShapeType(); - if (aShapeType == TopAbs_VERTEX) { - AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theFeature, aShape, theSketch); - if (aPntAttr.get() != NULL && - aSelectedAttributes.find(aPntAttr) != aSelectedAttributes.end()) { - theOwnersToSelect.Add(anOwner); - } - } - else if (aShapeType == TopAbs_EDGE) { - bool aFound = aSelectedResults.find(aResult) != aSelectedResults.end(); - if (aSelectedResults.find(aResult) != aSelectedResults.end() && - theOwnersToSelect.FindIndex(anOwner) <= 0) - theOwnersToSelect.Add(anOwner); - } - } - } -} - -void PartSet_SketcherMgr::connectToPropertyPanel(ModuleBase_ModelWidget* theWidget, const bool isToConnect) -{ - if (isToConnect) { - connect(theWidget, SIGNAL(beforeValuesChanged()), - this, SLOT(onBeforeValuesChangedInPropertyPanel())); - connect(theWidget, SIGNAL(afterValuesChanged()), - this, SLOT(onAfterValuesChangedInPropertyPanel())); - } - else { - disconnect(theWidget, SIGNAL(beforeValuesChanged()), - this, SLOT(onBeforeValuesChangedInPropertyPanel())); - disconnect(theWidget, SIGNAL(afterValuesChanged()), - this, SLOT(onAfterValuesChangedInPropertyPanel())); - } -} - -void PartSet_SketcherMgr::widgetStateChanged(int thePreviousState) -{ - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (getCurrentOperation()); - if (aFOperation) { - if (PartSet_SketcherMgr::isSketchOperation(aFOperation) || - isNestedSketchOperation(aFOperation) && - thePreviousState == ModuleBase_ModelWidget::ModifiedInPP) { - FeaturePtr aFeature = aFOperation->feature(); - visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature)); - } - } -} - -void PartSet_SketcherMgr::customizePresentation(const ObjectPtr& theObject) -{ - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (getCurrentOperation()); - if (aFOperation && (PartSet_SketcherMgr::isSketchOperation(aFOperation) || - isNestedSketchOperation(aFOperation))) - SketcherPrs_Tools::sendExpressionShownEvent(myIsConstraintsShown[PartSet_Tools::Expressions]); - - // update entities selection priorities - FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); - if (aFeature.get() && PartSet_SketcherMgr::isEntity(aFeature->getKind())) { - // update priority for feature - updateSelectionPriority(aFeature, aFeature); - // update priority for results of the feature - std::list aResults = aFeature->results(); - std::list::const_iterator anIt = aResults.begin(), aLastIt = aResults.end(); - for (; anIt != aLastIt; anIt++) - updateSelectionPriority(*anIt, aFeature); - } -} - -ModuleBase_Operation* PartSet_SketcherMgr::getCurrentOperation() const -{ - return myModule->workshop()->currentOperation(); -} - -//************************************************************** -ModuleBase_ModelWidget* PartSet_SketcherMgr::getActiveWidget() const -{ - ModuleBase_ModelWidget* aWidget = 0; - ModuleBase_Operation* anOperation = getCurrentOperation(); - if (anOperation) { - ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel(); - if (aPanel) - aWidget = aPanel->activeWidget(); - } - return aWidget; -} - -void PartSet_SketcherMgr::visualizeFeature(const FeaturePtr& theFeature, - const bool isEditOperation, - const bool isToDisplay, - const bool isFlushRedisplay) -{ - #ifdef DEBUG_DO_NOT_BY_ENTER - return; - #endif - - if (isEditOperation || !theFeature.get()) - return; - - ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); - XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); - - // 1. change visibility of the object itself, here the presentable object is processed, - // e.g. constraints features - //FeaturePtr aFeature = aFOperation->feature(); - std::list aResults = theFeature->results(); - if (isToDisplay) - theFeature->setDisplayed(true); - else - theFeature->setDisplayed(false); - - // change visibility of the object results, e.g. non-constraint features - std::list::const_iterator aIt; - for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { - if (isToDisplay) { - (*aIt)->setDisplayed(true); - } - else { - (*aIt)->setDisplayed(false); - } - } - if (isFlushRedisplay) - Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); -} - -void PartSet_SketcherMgr::storeSelection(const bool theHighlightedOnly) -{ - if (!myCurrentSketch.get()) - return; - - ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); - ModuleBase_ISelection* aSelect = aWorkshop->selection(); - QList aStoredPrs = aSelect->getHighlighted(); - - QList aFeatureList; - if (!theHighlightedOnly) { - QList aSelected = aSelect->getSelected( - ModuleBase_ISelection::AllControls); - aStoredPrs.append(aSelected); - } - - // 1. it is necessary to save current selection in order to restore it after the features moving - myCurrentSelection.clear(); - - QList::const_iterator anIt = aStoredPrs.begin(), aLast = aStoredPrs.end(); - - CompositeFeaturePtr aSketch = activeSketch(); - for (; anIt != aLast; anIt++) { - ModuleBase_ViewerPrsPtr aPrs = *anIt; - ObjectPtr anObject = aPrs->object(); - if (!anObject.get()) - continue; - - ResultPtr aResult = std::dynamic_pointer_cast(anObject); - FeaturePtr aFeature; - if (aResult.get()) - aFeature = ModelAPI_Feature::feature(aResult); - else - aFeature = std::dynamic_pointer_cast(anObject); - - - std::set aSelectedAttributes; - std::set aSelectedResults; - if (myCurrentSelection.find(aFeature) != myCurrentSelection.end()) { - std::pair, std::set > aPair = myCurrentSelection.find(aFeature).value(); - aSelectedAttributes = aPair.first; - aSelectedResults = aPair.second; - } - - Handle(SelectMgr_EntityOwner) anOwner = aPrs->owner(); - if (aResult.get()) { - getAttributesOrResults(anOwner, aFeature, aSketch, aResult, - aSelectedAttributes, aSelectedResults); - } - else { - std::list aResults = aFeature->results(); - std::list::const_iterator aIt; - for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { - ResultPtr aResult = *aIt; - getAttributesOrResults(anOwner, aFeature, aSketch, aResult, - aSelectedAttributes, aSelectedResults); - } - } - myCurrentSelection[aFeature] = std::make_pair(aSelectedAttributes, aSelectedResults); - } - //qDebug(QString(" storeSelection: %1").arg(myCurrentSelection.size()).toStdString().c_str()); -} - -void PartSet_SketcherMgr::restoreSelection() -{ - if (!myCurrentSketch.get()) - return; - - //qDebug(QString("restoreSelection: %1").arg(myCurrentSelection.size()).toStdString().c_str()); - ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); - XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); - FeatureToSelectionMap::const_iterator aSIt = myCurrentSelection.begin(), - aSLast = myCurrentSelection.end(); - SelectMgr_IndexedMapOfOwner anOwnersToSelect; - for (; aSIt != aSLast; aSIt++) { - anOwnersToSelect.Clear(); - getSelectionOwners(aSIt.key(), myCurrentSketch, aWorkshop, myCurrentSelection, - anOwnersToSelect); - aConnector->workshop()->selector()->setSelectedOwners(anOwnersToSelect, false); - } -} - -void PartSet_SketcherMgr::onShowConstraintsToggle(int theType, bool theState) -{ - PartSet_Tools::ConstraintVisibleState aType = (PartSet_Tools::ConstraintVisibleState)theType; - - updateBySketchParameters(aType, theState); -} - -void PartSet_SketcherMgr::updateBySketchParameters( - const PartSet_Tools::ConstraintVisibleState& theType, - bool theState) -{ - if (myCurrentSketch.get() == NULL) - return; - - bool aPrevState = myIsConstraintsShown[theType]; - myIsConstraintsShown[theType] = theState; - - switch (theType) { - case PartSet_Tools::Geometrical: - case PartSet_Tools::Dimensional: { - if (aPrevState != theState) { - ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); - XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); - for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) { - FeaturePtr aSubFeature = myCurrentSketch->subFeature(i); - bool aProcessed = false; - bool aConstraintDisplayed = canDisplayConstraint(aSubFeature, theType, aProcessed); - if (aProcessed) - aSubFeature->setDisplayed(aConstraintDisplayed); - } - Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); - } - } - break; - case PartSet_Tools::Expressions: { - if (aPrevState != theState) { - /// call all sketch features redisplay, the expression state will be corrected in customize - /// of distance presentation - Events_ID anEventId = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); - PartSet_Tools::sendSubFeaturesEvent(myCurrentSketch, anEventId); - } - } - break; - } -} - -void PartSet_SketcherMgr::updateSelectionPriority(ObjectPtr theObject, - FeaturePtr theFeature) -{ - if (!theObject.get() || !theFeature.get()) - return; - - AISObjectPtr anAIS = workshop()->displayer()->getAISObject(theObject); - Handle(AIS_InteractiveObject) anAISIO; - if (anAIS.get() != NULL) { - anAISIO = anAIS->impl(); - } - - if (!anAISIO.IsNull()) { // the presentation for the object is visualized - int anAdditionalPriority = 0; - // current feature - std::shared_ptr aSPFeature = - std::dynamic_pointer_cast(theFeature); - if (aSPFeature.get() != NULL) { - // 1. Vertices - // 2. Simple segments - // 3. External objects (violet color) - // 4. Auxiliary segments (dotted) - // StdSelect_BRepSelectionTool::Load uses priority calculating: - // Standard_Integer aPriority = (thePriority == -1) ? GetStandardPriority (theShape, theType) : thePriority; - // Priority of Vertex is 8, edge(segment) is 7. - // It might be not corrected as provides the condition above. - bool isExternal = aSPFeature->isExternal(); - bool isAuxiliary = PartSet_Tools::isAuxiliarySketchEntity(aSPFeature); - // current feature - if (!isExternal && !isAuxiliary) - anAdditionalPriority = 30; - // external feature - if (isExternal) - anAdditionalPriority = 20; - // auxiliary feature - if (isAuxiliary) { - anAdditionalPriority = 10; /// auxiliary objects should have less priority that - // edges/vertices of local selection on not-sketch objects - } - Handle(ModuleBase_ResultPrs) aResult = Handle(ModuleBase_ResultPrs)::DownCast(anAISIO); - if (!aResult.IsNull()) { - aResult->setAdditionalSelectionPriority(anAdditionalPriority); - } - } - } -} - -XGUI_Workshop* PartSet_SketcherMgr::workshop() const -{ - ModuleBase_IWorkshop* anIWorkshop = myModule->workshop(); - XGUI_ModuleConnector* aConnector = dynamic_cast(anIWorkshop); - return aConnector->workshop(); -} - -XGUI_OperationMgr* PartSet_SketcherMgr::operationMgr() const -{ - return workshop()->operationMgr(); -} - +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: PartSet_SketcherMgr.cpp +// Created: 19 Dec 2014 +// Author: Vitaly SMETANNIKOV + +#include "PartSet_SketcherMgr.h" +#include "PartSet_SketcherReetntrantMgr.h" +#include "PartSet_Module.h" +#include "PartSet_MouseProcessor.h" +#include "PartSet_Tools.h" +#include "PartSet_WidgetSketchLabel.h" +#include "PartSet_WidgetEditor.h" +#include "PartSet_ResultSketchPrs.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +//#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +//#define DEBUG_DO_NOT_BY_ENTER +//#define DEBUG_SKETCHER_ENTITIES +//#define DEBUG_SKETCH_ENTITIES_ON_MOVE + +//#define DEBUG_CURSOR + +/// Fills attribute and result lists by the selected owner. In case if the attribute is found, +/// by the owner shape, it is put to the list. Otherwise if type of owner shape is edge, put the function +/// result as is to the list of results. +/// \param theOwner a viewer selected owner +/// \param theFeature a feature, where the attribute is searched +/// \param theSketch a current sketch +/// \param theSelectedAttribute an output list of attributes +/// \param theSelectedResults an output list of edge results +void getAttributesOrResults(const Handle(SelectMgr_EntityOwner)& theOwner, + const FeaturePtr& theFeature, const FeaturePtr& theSketch, + const ResultPtr& theResult, + std::set& aSelectedAttributes, + std::set& aSelectedResults) +{ + Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast(theOwner); + if (aBRepOwner.IsNull()) + return; + Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast( + aBRepOwner->Selectable()); + if (aBRepOwner->HasShape()) { + const TopoDS_Shape& aShape = aBRepOwner->Shape(); + TopAbs_ShapeEnum aShapeType = aShape.ShapeType(); + if (aShapeType == TopAbs_VERTEX) { + AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theFeature, + aShape, theSketch); + if (aPntAttr.get() != NULL) + aSelectedAttributes.insert(aPntAttr); + } + else if (aShapeType == TopAbs_EDGE && + aSelectedResults.find(theResult) == aSelectedResults.end()) { + aSelectedResults.insert(theResult); + } + } +} + +PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule) + : QObject(theModule), myModule(theModule), myIsDragging(false), myDragDone(false), + myIsMouseOverWindow(false), + myIsMouseOverViewProcessed(true), myPreviousUpdateViewerEnabled(true), + myIsPopupMenuActive(false) +{ + ModuleBase_IWorkshop* anIWorkshop = myModule->workshop(); + ModuleBase_IViewer* aViewer = anIWorkshop->viewer(); + + myPreviousDrawModeEnabled = true;//aViewer->isSelectionEnabled(); + + connect(aViewer, SIGNAL(mousePress(ModuleBase_IViewWindow*, QMouseEvent*)), + this, SLOT(onMousePressed(ModuleBase_IViewWindow*, QMouseEvent*))); + + connect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)), + this, SLOT(onMouseReleased(ModuleBase_IViewWindow*, QMouseEvent*))); + + connect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)), + this, SLOT(onMouseMoved(ModuleBase_IViewWindow*, QMouseEvent*))); + + connect(aViewer, SIGNAL(mouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)), + this, SLOT(onMouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*))); + + XGUI_ModuleConnector* aConnector = dynamic_cast(anIWorkshop); + XGUI_Workshop* aWorkshop = aConnector->workshop(); + connect(aWorkshop, SIGNAL(applicationStarted()), this, SLOT(onApplicationStarted())); + + myIsConstraintsShown[PartSet_Tools::Geometrical] = true; + myIsConstraintsShown[PartSet_Tools::Dimensional] = true; + myIsConstraintsShown[PartSet_Tools::Expressions] = false; +} + +PartSet_SketcherMgr::~PartSet_SketcherMgr() +{ + if (!myPlaneFilter.IsNull()) + myPlaneFilter.Nullify(); +} + +void PartSet_SketcherMgr::onEnterViewPort() +{ + // 1. if the mouse over window, update the next flag. Do not perform update visibility of + // created feature because it should be done in onMouseMove(). Some widgets watch + // the mouse move and use the cursor position to update own values. If the presentaion is + // redisplayed before this update, the feature presentation jumps from reset value to current. + myIsMouseOverWindow = true; + + #ifdef DEBUG_DO_NOT_BY_ENTER + return; + #endif + + if (canChangeCursor(getCurrentOperation())) { + QCursor* aCurrentCursor = QApplication::overrideCursor(); + if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) { + QApplication::setOverrideCursor(QCursor(Qt::CrossCursor)); +#ifdef DEBUG_CURSOR + qDebug("onEnterViewPort() : Qt::CrossCursor"); +#endif + } + } + + if (!isNestedCreateOperation(getCurrentOperation(), activeSketch())) + return; + + operationMgr()->onValidateOperation(); + + // we need change displayed state of the current operation feature + // if the feature is presentable, e.g. distance construction. It has no results, so workshop does + // not accept a signal about the result created. Nothing is shown until mouse is moved out/in view + // port. If the isDisplayed flag is true, the presentable feature is displayed as soon as the + // presentation becomes valid and redisplay happens + //ModuleBase_Operation* aOperation = getCurrentOperation(); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + if (aFeature.get() && aFeature->data()->isValid()) { + visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature), false); + } + } +} + +void PartSet_SketcherMgr::onLeaveViewPort() +{ + myIsMouseOverViewProcessed = false; + myIsMouseOverWindow = false; + + #ifdef DEBUG_DO_NOT_BY_ENTER + return; + #endif + + if (canChangeCursor(getCurrentOperation())) { + QApplication::restoreOverrideCursor(); +#ifdef DEBUG_CURSOR + qDebug("onLeaveViewPort() : None"); +#endif + } + + if (!isNestedCreateOperation(getCurrentOperation(), activeSketch())) + return; + + // the method should be performed if the popup menu is called, + // the reset of the current widget should not happen + if (myIsPopupMenuActive) + return; + + // it is important to validate operation here only if sketch entity create operation is active + // because at this operation we reacts to the mouse leave/enter view port + operationMgr()->onValidateOperation(); + + // 2. if the mouse IS NOT over window, reset the active widget value and hide the presentation + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); + XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); + // disable the viewer update in order to avoid visualization of redisplayed feature in viewer + // obtained after reset value + bool isEnableUpdateViewer = aDisplayer->enableUpdateViewer(false); + ModuleBase_ModelWidget* anActiveWidget = getActiveWidget(); + if (anActiveWidget) + anActiveWidget->reset(); + + // hides the presentation of the current operation feature + // the feature is to be erased here, but it is correct to call canDisplayObject because + // there can be additional check (e.g. editor widget in distance constraint) + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature)); + } + // we should update viewer after the presentation are hidden in the viewer + // otherwise the reset presentation(line) appears in the viewer(by quick move from viewer to PP) + aDisplayer->enableUpdateViewer(isEnableUpdateViewer); +} + +void PartSet_SketcherMgr::onBeforeValuesChangedInPropertyPanel() +{ + if (!isNestedEditOperation(getCurrentOperation(), myModule->sketchMgr()->activeSketch()) || + myModule->sketchReentranceMgr()->isInternalEditActive()) + return; + // it is necessary to save current selection in order to restore it after the values are modifed + storeSelection(); + + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); + XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); + myPreviousUpdateViewerEnabled = aDisplayer->enableUpdateViewer(false); +} + +void PartSet_SketcherMgr::onAfterValuesChangedInPropertyPanel() +{ + if (!isNestedEditOperation(getCurrentOperation(), myModule->sketchMgr()->activeSketch()) || + myModule->sketchReentranceMgr()->isInternalEditActive()) { + myModule->sketchReentranceMgr()->updateInternalEditActiveState(); + return; + } + // it is necessary to restore current selection in order to restore it after the values are modified + restoreSelection(); + myCurrentSelection.clear(); + + // 3. the flag to disable the update viewer should be set in order to avoid blinking in the + // viewer happens by deselect/select the modified objects. The flag should be restored after + // the selection processing. The update viewer should be also called. + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); + XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); + aDisplayer->enableUpdateViewer(myPreviousUpdateViewerEnabled); + aDisplayer->updateViewer(); + + +} + +void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) +{ + if (myModule->sketchReentranceMgr()->processMousePressed(theWnd, theEvent)) + return; + + //get2dPoint(theWnd, theEvent, myClickedPoint); + + if (!(theEvent->buttons() & Qt::LeftButton)) + return; + + // Clear dragging mode + myIsDragging = false; + + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + ModuleBase_IViewer* aViewer = aWorkshop->viewer(); + if (!aViewer->canDragByMouse()) + return; + + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (!aFOperation) + return; + + if (aFOperation->isEditOperation()) { + // If the current widget is a selector, do nothing, it processes the mouse press + ModuleBase_ModelWidget* anActiveWidget = getActiveWidget(); + if(anActiveWidget && anActiveWidget->isViewerSelector()) { + return; + } + } + + // Use only for sketch operations + if (myCurrentSketch) { + if (!PartSet_Tools::sketchPlane(myCurrentSketch)) + return; + + bool isSketcher = isSketchOperation(aFOperation); + bool isSketchOpe = isNestedSketchOperation(aFOperation); + + // Avoid non-sketch operations + if ((!isSketchOpe) && (!isSketcher)) + return; + + bool isEditing = aFOperation->isEditOperation(); + + // Ignore creation sketch operation + if ((!isSketcher) && (!isEditing)) + return; + + Handle(AIS_InteractiveContext) aContext = aViewer->AISContext(); + // Remember highlighted objects for editing + ModuleBase_ISelection* aSelect = aWorkshop->selection(); + + bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier); + storeSelection(!aHasShift); + + if (myCurrentSelection.empty()) { + if (isSketchOpe && (!isSketcher)) + // commit previous operation + if (!aFOperation->commit()) + aFOperation->abort(); + return; + } + // Init flyout point for radius rotation + FeaturePtr aFeature = myCurrentSelection.begin().key(); + + get2dPoint(theWnd, theEvent, myCurrentPoint); + if (isSketcher) { + myIsDragging = true; + myDragDone = false; + + myPreviousDrawModeEnabled = aViewer->enableDrawMode(false); + // selection should be restored before edit operation start to process the + // selected entities, e.g. selection of point(attribute on a line) should edit the point + restoreSelection(); + launchEditing(); + if (aFeature.get() != NULL) { + std::shared_ptr aSPFeature = + std::dynamic_pointer_cast(aFeature); + if (aSPFeature.get() && + (aSPFeature->getKind() == SketchPlugin_ConstraintRadius::ID() || + aSPFeature->getKind() == SketchPlugin_ConstraintAngle::ID())) { + DataPtr aData = aSPFeature->data(); + AttributePtr aAttr = aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()); + std::shared_ptr aFPAttr = + std::dynamic_pointer_cast(aAttr); + aFPAttr->setValue(myCurrentPoint.myCurX, myCurrentPoint.myCurY); + } + } + } else if (isSketchOpe && isEditing) { + // If selected another object commit current result + aFOperation->commit(); + + myIsDragging = true; + myDragDone = false; + + myPreviousDrawModeEnabled = aViewer->enableDrawMode(false); + // selection should be restored before edit operation start to process the + // selected entities, e.g. selection of point(attribute on a line) should edit the point + restoreSelection(); + launchEditing(); + if (aFeature.get() != NULL) { + std::shared_ptr aSPFeature = + std::dynamic_pointer_cast(aFeature); + if (aSPFeature.get() && + (aSPFeature->getKind() == SketchPlugin_ConstraintRadius::ID() || + aSPFeature->getKind() == SketchPlugin_ConstraintAngle::ID())) { + DataPtr aData = aSPFeature->data(); + AttributePtr aAttr = aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()); + std::shared_ptr aFPAttr = + std::dynamic_pointer_cast(aAttr); + aFPAttr->setValue(myCurrentPoint.myCurX, myCurrentPoint.myCurY); + } + } + restoreSelection(); + } + } +} + +void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) +{ + if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent)) + return; + + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + ModuleBase_IViewer* aViewer = aWorkshop->viewer(); + if (!aViewer->canDragByMouse()) + return; + ModuleBase_Operation* aOp = getCurrentOperation(); + if (aOp) { + if (isNestedSketchOperation(aOp)) { + // Only for sketcher operations + if (myIsDragging) { + if (myDragDone) { + myCurrentSelection.clear(); + } + } + } + } + + aWorkshop->viewer()->enableDrawMode(myPreviousDrawModeEnabled); + myIsDragging = false; + + ModuleBase_ModelWidget* anActiveWidget = getActiveWidget(); + PartSet_MouseProcessor* aProcessor = dynamic_cast(anActiveWidget); + if (aProcessor) + aProcessor->mouseReleased(theWnd, theEvent); +} + +void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) +{ +#ifdef DEBUG_SKETCH_ENTITIES_ON_MOVE + CompositeFeaturePtr aSketch = activeSketch(); + if (aSketch.get()) { + std::cout << "mouse move SKETCH FEATURES [" << aSketch->numberOfSubs() << "]:" << std::endl; + QStringList anInfo; + for (int i = 0, aNbSubs = aSketch->numberOfSubs(); i < aNbSubs; i++) { + //std::cout << getFeatureInfo(aSketch->subFeature(i), false) << std::endl; + anInfo.append(ModuleBase_Tools::objectInfo(aSketch->subFeature(i))); + } + QString anInfoStr = anInfo.join("\n"); + qDebug(QString("%1").arg(anInfo.size()).arg(anInfoStr).toStdString().c_str()); + } +#endif + + if (myModule->sketchReentranceMgr()->processMouseMoved(theWnd, theEvent)) + return; + + if (isNestedCreateOperation(getCurrentOperation(), activeSketch())) { + // 1. perform the widget mouse move functionality and display the presentation + // the mouse move should be processed in the widget, if it can in order to visualize correct + // presentation. These widgets correct the feature attribute according to the mouse position + ModuleBase_ModelWidget* anActiveWidget = myModule->activeWidget(); + PartSet_MouseProcessor* aProcessor = dynamic_cast(anActiveWidget); + if (aProcessor) + aProcessor->mouseMoved(theWnd, theEvent); + if (!myIsMouseOverViewProcessed) { + myIsMouseOverViewProcessed = true; + + // the feature is to be erased here, but it is correct to call canDisplayObject because + // there can be additional check (e.g. editor widget in distance constraint) + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature)); + } + } + } + //myClickedPoint.clear(); + + if (myIsDragging) { + // 1. the current selection is saved in the mouse press method in order to restore it after moving + // 2. the enable selection in the viewer should be temporary switched off in order to ignore + // mouse press signal in the viewer(it call Select for AIS context and the dragged objects are + // deselected). This flag should be restored in the slot, processed the mouse release signal. + + ModuleBase_Operation* aCurrentOperation = getCurrentOperation(); + if (!aCurrentOperation) + return; + if (isSketchOperation(aCurrentOperation)) + return; // No edit operation activated + + Handle(V3d_View) aView = theWnd->v3dView(); + gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView); + Point aMousePnt; + get2dPoint(theWnd, theEvent, aMousePnt); + double dX = aMousePnt.myCurX - myCurrentPoint.myCurX; + double dY = aMousePnt.myCurY - myCurrentPoint.myCurY; + + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); + XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); + // 3. the flag to disable the update viewer should be set in order to avoid blinking in the + // viewer happens by deselect/select the modified objects. The flag should be restored after + // the selection processing. The update viewer should be also called. + bool isEnableUpdateViewer = aDisplayer->enableUpdateViewer(false); + + static Events_ID aMoveEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED); + //static Events_ID aUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + FeatureToSelectionMap::const_iterator anIt = myCurrentSelection.begin(), + aLast = myCurrentSelection.end(); + // 4. the features and attributes modification(move) + bool isModified = false; + for (; anIt != aLast; anIt++) { + FeaturePtr aFeature = anIt.key(); + + std::set anAttributes = anIt.value().first; + // Process selection by attribute: the priority to the attribute + if (!anAttributes.empty()) { + std::set::const_iterator anAttIt = anAttributes.begin(), + anAttLast = anAttributes.end(); + for (; anAttIt != anAttLast; anAttIt++) { + AttributePtr anAttr = *anAttIt; + if (anAttr.get() == NULL) + continue; + std::string aAttrId = anAttr->id(); + DataPtr aData = aFeature->data(); + if (aData->isValid()) { + std::shared_ptr aPoint = + std::dynamic_pointer_cast(aData->attribute(aAttrId)); + if (aPoint.get() != NULL) { + bool isImmutable = aPoint->setImmutable(true); + aPoint->move(dX, dY); + isModified = true; + ModelAPI_EventCreator::get()->sendUpdated(aFeature, aMoveEvent); + aPoint->setImmutable(isImmutable); + } + } + } + } else { + // Process selection by feature + std::shared_ptr aSketchFeature = + std::dynamic_pointer_cast(aFeature); + if (aSketchFeature) { + aSketchFeature->move(dX, dY); + isModified = true; + ModelAPI_EventCreator::get()->sendUpdated(aSketchFeature, aMoveEvent); + } + } + } + // the modified state of the current operation should be updated if there are features, which + // were changed here + if (isModified) { + aCurrentOperation->onValuesChanged(); + } + Events_Loop::loop()->flush(aMoveEvent); // up all move events - to be processed in the solver + //Events_Loop::loop()->flush(aUpdateEvent); // up update events - to redisplay presentations + + // 5. it is necessary to save current selection in order to restore it after the features moving + restoreSelection(); + // 6. restore the update viewer flag and call this update + aDisplayer->enableUpdateViewer(isEnableUpdateViewer); + aDisplayer->updateViewer(); + + myDragDone = true; + myCurrentPoint = aMousePnt; + } +} + +void PartSet_SketcherMgr::onMouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) +{ + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (aFOperation && aFOperation->isEditOperation()) { + std::string aId = aFOperation->id().toStdString(); + if (isDistanceOperation(aFOperation)) + { + // Activate dimension value editing on double click + ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel(); + QList aWidgets = aPanel->modelWidgets(); + // Find corresponded widget to activate value editing + foreach (ModuleBase_ModelWidget* aWgt, aWidgets) { + if (aWgt->attributeID() == SketchPlugin_Constraint::VALUE() || + aWgt->attributeID() == SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()) { + PartSet_WidgetEditor* anEditor = dynamic_cast(aWgt); + if (anEditor) + anEditor->showPopupEditor(); + return; + } + } + } + } +} + +void PartSet_SketcherMgr::onApplicationStarted() +{ + ModuleBase_IWorkshop* anIWorkshop = myModule->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(anIWorkshop); + XGUI_Workshop* aWorkshop = aConnector->workshop(); + PartSet_SketcherReetntrantMgr* aReentranceMgr = myModule->sketchReentranceMgr(); + + XGUI_PropertyPanel* aPropertyPanel = aWorkshop->propertyPanel(); + if (aPropertyPanel) { + //connect(aPropertyPanel, SIGNAL(beforeWidgetActivated(ModuleBase_ModelWidget*)), + // this, SLOT(onBeforeWidgetActivated(ModuleBase_ModelWidget*))); + + connect(aPropertyPanel, SIGNAL(noMoreWidgets(const std::string&)), + aReentranceMgr, SLOT(onNoMoreWidgets(const std::string&))); + connect(aPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)), + aReentranceMgr, SLOT(onWidgetActivated())); + } + + XGUI_ViewerProxy* aViewerProxy = aWorkshop->viewer(); + connect(aViewerProxy, SIGNAL(enterViewPort()), this, SLOT(onEnterViewPort())); + connect(aViewerProxy, SIGNAL(leaveViewPort()), this, SLOT(onLeaveViewPort())); + + XGUI_ContextMenuMgr* aContextMenuMgr = aWorkshop->contextMenuMgr(); + connect(aContextMenuMgr, SIGNAL(beforeContextMenu()), this, SLOT(onBeforeContextMenu())); + connect(aContextMenuMgr, SIGNAL(afterContextMenu()), this, SLOT(onAfterContextMenu())); +} + +//void PartSet_SketcherMgr::onBeforeWidgetActivated(ModuleBase_ModelWidget* theWidget) +//{ + //if (!myClickedPoint.myIsInitialized) + // return; + + //ModuleBase_Operation* aOperation = getCurrentOperation(); + // the distance constraint feature should not use the clickedd point + // this is workaround in order to don't throw down the flyout point value, + // set by execute() method of these type of features + //if (isDistanceOperation(aOperation)) + // return; + + //PartSet_WidgetPoint2D* aPnt2dWgt = dynamic_cast(theWidget); + //if (aPnt2dWgt) { + // aPnt2dWgt->setPoint(myClickedPoint.myCurX, myClickedPoint.myCurY); + //} +//} + +void PartSet_SketcherMgr::onBeforeContextMenu() +{ + myIsPopupMenuActive = true; +} + +void PartSet_SketcherMgr::onAfterContextMenu() +{ + myIsPopupMenuActive = false; +} + +void PartSet_SketcherMgr::get2dPoint(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent, + Point& thePoint) +{ + Handle(V3d_View) aView = theWnd->v3dView(); + gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView); + double aX, anY; + PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, aX, anY); + thePoint.setValue(aX, anY); +} + +void PartSet_SketcherMgr::launchEditing() +{ + if (!myCurrentSelection.empty()) { + FeaturePtr aFeature = myCurrentSelection.begin().key(); + std::shared_ptr aSPFeature = + std::dynamic_pointer_cast(aFeature); + if (aSPFeature && (!aSPFeature->isExternal())) { + myModule->editFeature(aSPFeature); + } + } +} + +bool PartSet_SketcherMgr::sketchSolverError() +{ + bool anError = false; + CompositeFeaturePtr aSketch = activeSketch(); + if (aSketch.get()) { + AttributeStringPtr aAttributeString = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR()); + anError = !aAttributeString->value().empty(); + } + return anError; +} + +QString PartSet_SketcherMgr::getFeatureError(const FeaturePtr& theFeature) +{ + std::string anError = ""; + if (!theFeature.get() || !theFeature->data()->isValid()) + return anError.c_str(); + + CompositeFeaturePtr aSketch = activeSketch(); + if (aSketch.get() && aSketch == theFeature) { + AttributeStringPtr aAttributeString = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR()); + anError = aAttributeString->value(); + ModuleBase_Tools::translate(aSketch->getKind(), anError); + } + return anError.c_str(); +} + +void PartSet_SketcherMgr::clearClickedFlags() +{ + //myClickedPoint.clear(); + myCurrentPoint.clear(); +} + +const QStringList& PartSet_SketcherMgr::replicationsIdList() +{ + static QStringList aReplicationIds; + if (aReplicationIds.size() == 0) { + aReplicationIds << SketchPlugin_ConstraintMirror::ID().c_str(); + aReplicationIds << SketchPlugin_MultiRotation::ID().c_str(); + aReplicationIds << SketchPlugin_MultiTranslation::ID().c_str(); + } + return aReplicationIds; +} + +const QStringList& PartSet_SketcherMgr::constraintsIdList() +{ + static QStringList aConstraintIds; + if (aConstraintIds.size() == 0) { + aConstraintIds << SketchPlugin_ConstraintLength::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintDistance::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintRigid::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintRadius::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintPerpendicular::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintParallel::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintHorizontal::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintVertical::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintEqual::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintTangent::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintCoincidence::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintAngle::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintCollinear::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintMiddle::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintMirror::ID().c_str(); + aConstraintIds << SketchPlugin_MultiTranslation::ID().c_str(); + aConstraintIds << SketchPlugin_MultiRotation::ID().c_str(); + } + return aConstraintIds; +} + +void PartSet_SketcherMgr::sketchSelectionModes(QIntList& theModes) +{ + theModes.clear(); + + theModes.append(SketcherPrs_Tools::Sel_Dimension_Text); + theModes.append(SketcherPrs_Tools::Sel_Dimension_Line); + theModes.append(SketcherPrs_Tools::Sel_Constraint); + theModes.append(TopAbs_VERTEX); + theModes.append(TopAbs_EDGE); +} + +Handle(AIS_InteractiveObject) PartSet_SketcherMgr::createPresentation(const ResultPtr& theResult) +{ + Handle(AIS_InteractiveObject) aPrs; + + FeaturePtr aFeature = ModelAPI_Feature::feature(theResult); + if (aFeature.get() && aFeature->getKind() == SketchPlugin_Sketch::ID()) { + aPrs = new PartSet_ResultSketchPrs(theResult); + } + return aPrs; +} + +bool PartSet_SketcherMgr::isSketchOperation(ModuleBase_Operation* theOperation) +{ + return theOperation && theOperation->id().toStdString() == SketchPlugin_Sketch::ID(); +} + +bool PartSet_SketcherMgr::isNestedSketchOperation(ModuleBase_Operation* theOperation) const +{ + bool aNestedSketch = false; + + FeaturePtr anActiveSketch = activeSketch(); + if (anActiveSketch.get() && theOperation) { + ModuleBase_Operation* aSketchOperation = operationMgr()->findOperation( + anActiveSketch->getKind().c_str()); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (theOperation); + if (aSketchOperation && aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + if (aFeature.get()) { + QStringList aGrantedOpIds = aSketchOperation->grantedOperationIds(); + aNestedSketch = aGrantedOpIds.contains(aFeature->getKind().c_str()); + } + } + } + return aNestedSketch; +} + +bool PartSet_SketcherMgr::isNestedCreateOperation(ModuleBase_Operation* theOperation, + const CompositeFeaturePtr& theSketch) const +{ + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (theOperation); + return aFOperation && !aFOperation->isEditOperation() && + isNestedSketchOperation(aFOperation); +} + +bool PartSet_SketcherMgr::isNestedEditOperation(ModuleBase_Operation* theOperation, + const CompositeFeaturePtr& theSketch) const +{ + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (theOperation); + return aFOperation && aFOperation->isEditOperation() && + isNestedSketchOperation(aFOperation); +} + +bool PartSet_SketcherMgr::isEntity(const std::string& theId) +{ + return (theId == SketchPlugin_Line::ID()) || + (theId == SketchPlugin_Point::ID()) || + (theId == SketchPlugin_Arc::ID()) || + (theId == SketchPlugin_Circle::ID()); +} + +bool PartSet_SketcherMgr::isDistanceOperation(ModuleBase_Operation* theOperation) +{ + std::string anId = theOperation ? theOperation->id().toStdString() : ""; + + return isDistanceKind(anId); +} + +bool PartSet_SketcherMgr::isDistanceKind(std::string& theKind) +{ + return (theKind == SketchPlugin_ConstraintLength::ID()) || + (theKind == SketchPlugin_ConstraintDistance::ID()) || + (theKind == SketchPlugin_ConstraintRadius::ID()) || + (theKind == SketchPlugin_ConstraintAngle::ID()); +} + +void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation) +{ + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (!aFOperation) + return; + + myModule->onViewTransformed(); + + // Display all sketcher sub-Objects + myCurrentSketch = std::dynamic_pointer_cast(aFOperation->feature()); + XGUI_ModuleConnector* aConnector = dynamic_cast(myModule->workshop()); + + // Hide sketcher result + std::list aResults = myCurrentSketch->results(); + std::list::const_iterator aIt; + for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { + (*aIt)->setDisplayed(false); + } + myCurrentSketch->setDisplayed(false); + + // Remove invalid sketch entities + std::set anInvalidFeatures; + ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators(); + for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) { + FeaturePtr aFeature = myCurrentSketch->subFeature(i); + if (aFeature.get()) { + if (!aFactory->validate(aFeature)) + anInvalidFeatures.insert(aFeature); + } + } + if (!anInvalidFeatures.empty()) { + std::map > aReferences; + ModelAPI_Tools::findAllReferences(anInvalidFeatures, aReferences, false); + + std::set::const_iterator anIt = anInvalidFeatures.begin(), + aLast = anInvalidFeatures.end(); + // separate features to references to parameter features and references to others + QStringList anInvalidFeatureNames; + for (; anIt != aLast; anIt++) { + FeaturePtr aFeature = *anIt; + if (aFeature.get()) + anInvalidFeatureNames.append(aFeature->name().c_str()); + } + std::string aPrefixInfo = QString("Invalid features of the sketch will be deleted: %1.\n\n"). + arg(anInvalidFeatureNames.join(", ")).toStdString().c_str(); + std::set aFeatureRefsToDelete; + if (ModuleBase_Tools::askToDelete(anInvalidFeatures, aReferences, aConnector->desktop(), + aFeatureRefsToDelete, aPrefixInfo)) { + if (!aFeatureRefsToDelete.empty()) + anInvalidFeatures.insert(aFeatureRefsToDelete.begin(), aFeatureRefsToDelete.end()); + ModelAPI_Tools::removeFeatures(anInvalidFeatures, true); + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + // TODO: call the next method in the XGUI_OperationMgr::onOperationStarted(). + workshop()->errorMgr()->updateAcceptAllAction(myCurrentSketch); + } + } + + // Display sketcher objects + QStringList anInfo; + for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) { + FeaturePtr aFeature = myCurrentSketch->subFeature(i); +#ifdef DEBUG_SKETCHER_ENTITIES + anInfo.append(ModuleBase_Tools::objectInfo(aFeature)); +#endif + std::list aResults = aFeature->results(); + std::list::const_iterator aIt; + for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { + (*aIt)->setDisplayed(true); + } + aFeature->setDisplayed(true); + } +#ifdef DEBUG_SKETCHER_ENTITIES + QString anInfoStr = anInfo.join(";\t"); + qDebug(QString("startSketch: %1, %2").arg(anInfo.size()).arg(anInfoStr).toStdString().c_str()); +#endif + + if(myCirclePointFilter.IsNull()) { + myCirclePointFilter = new PartSet_CirclePointFilter(myModule->workshop()); + } + + myModule->workshop()->viewer()->addSelectionFilter(myCirclePointFilter); + + if (myPlaneFilter.IsNull()) + myPlaneFilter = new ModuleBase_ShapeInPlaneFilter(); + + myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter); + bool aHasPlane = false; + std::shared_ptr aPln; + aPln = PartSet_Tools::sketchPlane(myCurrentSketch); + myPlaneFilter->setPlane(aPln); + + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); + // all displayed objects should be activated in current selection modes according to switched + // plane filter + if (aPln.get()) + aConnector->activateModuleSelectionModes(); +} + +void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation) +{ + myIsMouseOverWindow = false; + myIsConstraintsShown[PartSet_Tools::Geometrical] = true; + myIsConstraintsShown[PartSet_Tools::Dimensional] = true; + myIsConstraintsShown[PartSet_Tools::Expressions] = false; + + XGUI_ModuleConnector* aConnector = dynamic_cast(myModule->workshop()); + + DataPtr aData = myCurrentSketch->data(); + if (!aData->isValid()) { + XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); + // The sketch was aborted + myCurrentSketch = CompositeFeaturePtr(); + // TODO: move this outside of if-else + myModule->workshop()->viewer()->removeSelectionFilter(myCirclePointFilter); + myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter); + + // Erase all sketcher objects + QObjectPtrList aObjects = aDisplayer->displayedObjects(); + foreach (ObjectPtr aObj, aObjects) { + DataPtr aObjData = aObj->data(); + if (!aObjData->isValid()) + aObj->setDisplayed(false); + } + } + else { + // Hide all sketcher sub-Objects + for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) { + FeaturePtr aFeature = myCurrentSketch->subFeature(i); + std::list aResults = aFeature->results(); + std::list::const_iterator aIt; + for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { + (*aIt)->setDisplayed(false); + } + aFeature->setDisplayed(false); + } + // Display sketcher result + std::list aResults = myCurrentSketch->results(); + std::list::const_iterator aIt; + Events_Loop* aLoop = Events_Loop::loop(); + static Events_ID aDispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); + + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (theOperation); + for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { + if (!aFOperation->isDisplayedOnStart(*aIt)) { + (*aIt)->setDisplayed(true); + // this display event is needed because sketch already may have "displayed" state, + // but not displayed while it is still active (issue 613, abort of existing sketch) + ModelAPI_EventCreator::get()->sendUpdated(*aIt, aDispEvent); + } + } + if (!aFOperation->isDisplayedOnStart(myCurrentSketch)) + myCurrentSketch->setDisplayed(true); + + myCurrentSketch = CompositeFeaturePtr(); + + myModule->workshop()->viewer()->removeSelectionFilter(myCirclePointFilter); + myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter); + + Events_Loop::loop()->flush(aDispEvent); + } + // restore the module selection modes, which were changed on startSketch + aConnector->activateModuleSelectionModes(); +} + +void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation) +{ + if (canChangeCursor(theOperation) && myIsMouseOverWindow) { + QCursor* aCurrentCursor = QApplication::overrideCursor(); + if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) { + QApplication::setOverrideCursor(QCursor(Qt::CrossCursor)); +#ifdef DEBUG_CURSOR + qDebug("startNestedSketch() : Qt::CrossCursor"); +#endif + } + } +} + +void PartSet_SketcherMgr::stopNestedSketch(ModuleBase_Operation* theOperation) +{ + myIsMouseOverViewProcessed = true; + operationMgr()->onValidateOperation(); + // when sketch nested operation is stopped the cursor should be restored unconditionally + //if (canChangeCursor(theOperation)) { + QApplication::restoreOverrideCursor(); +#ifdef DEBUG_CURSOR + qDebug("stopNestedSketch() : None"); +#endif + //} + /// improvement to deselect automatically all eventual selected objects, when + // returning to the neutral point of the Sketcher + workshop()->selector()->clearSelection(); +} + +void PartSet_SketcherMgr::commitNestedSketch(ModuleBase_Operation* theOperation) +{ + if (isNestedCreateOperation(theOperation, activeSketch())) { + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (theOperation); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + // it is necessary to check the the feature data validity because + // some kind of features are removed by an operation commit(the macro state of a feature) + if (aFeature.get() && aFeature->data()->isValid()) { + visualizeFeature(aFeature, aFOperation->isEditOperation(), true); + } + } + } +} + +void PartSet_SketcherMgr::activatePlaneFilter(const bool& toActivate) +{ + if (toActivate) + myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter); + else + myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter); +} + +bool PartSet_SketcherMgr::operationActivatedByPreselection() +{ + bool isOperationStopped = false; + ModuleBase_Operation* anOperation = getCurrentOperation(); + if(anOperation && isNestedSketchOperation(anOperation)) { + // Set final definitions if they are necessary + //propertyPanelDefined(aOperation); + /// Commit sketcher operations automatically + /// distance operation are able to show popup editor to modify the distance value + /// after entering the value, the operation should be committed/aborted(by Esc key) + bool aCanCommitOperation = true; + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (anOperation); + if (aFOperation && PartSet_SketcherMgr::isDistanceOperation(aFOperation)) { + bool aValueAccepted = setDistanceValueByPreselection(anOperation, myModule->workshop(), + aCanCommitOperation); + if (!aValueAccepted) + return isOperationStopped; + } + + if (aCanCommitOperation) + isOperationStopped = anOperation->commit(); + else { + anOperation->abort(); + isOperationStopped = true; + } + } + return isOperationStopped; +} + +bool PartSet_SketcherMgr::canUndo() const +{ + return isNestedCreateOperation(getCurrentOperation(), activeSketch()); +} + +bool PartSet_SketcherMgr::canRedo() const +{ + return isNestedCreateOperation(getCurrentOperation(), activeSketch()); +} + +bool PartSet_SketcherMgr::canEraseObject(const ObjectPtr& theObject) const +{ + bool aCanErase = true; + // when the sketch operation is active, results of sketch sub-feature can not be hidden + if (myCurrentSketch.get()) { + return !isObjectOfSketch(theObject); + } + return aCanErase; +} + +bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const +{ + bool aCanDisplay = true; + + bool aHasActiveSketch = activeSketch().get() != NULL; + if (aHasActiveSketch) { + // 1. the sketch feature should not be displayed during the sketch active operation + // it is hidden by a sketch operation start and shown by a sketch stop, just the sketch + // nested features can be visualized + FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); + if (aFeature.get() != NULL && aFeature == activeSketch()) { + aCanDisplay = false; + } + std::shared_ptr aSketchFeature = + std::dynamic_pointer_cast(aFeature); + /// some sketch entities should be never shown, e.g. projection feature + if (aSketchFeature.get()) + aCanDisplay = aSketchFeature->canBeDisplayed(); + } + else { // there are no an active sketch + // 2. sketch sub-features should not be visualized if the sketch operation is not active + FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); + if (aFeature.get() != NULL) { + std::shared_ptr aSketchFeature = + std::dynamic_pointer_cast(aFeature); + if (aSketchFeature.get()) { + aCanDisplay = false; + } + } + } + + // 3. the method should not filter the objects, which are not related to the current operation. + // The object is filtered just if it is a current operation feature or this feature result + if (aCanDisplay) { + bool isObjectFound = false; + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + if (aFeature.get()) { + std::list aResults = aFeature->results(); + if (theObject == aFeature) + isObjectFound = true; + else { + std::list::const_iterator anIt = aResults.begin(), aLast = aResults.end(); + for (; anIt != aLast && !isObjectFound; anIt++) { + isObjectFound = *anIt == theObject; + } + } + } + } + if (isObjectFound) { + // 4. For created nested feature operation do not display the created feature if + // the mouse curstor leaves the OCC window. + // The correction cases, which ignores this condition: + // a. the property panel values modification + // b. the popup menu activated + // c. widget editor control + #ifndef DEBUG_DO_NOT_BY_ENTER + if (isNestedCreateOperation(getCurrentOperation(), activeSketch())) { + ModuleBase_ModelWidget* anActiveWidget = getActiveWidget(); + ModuleBase_WidgetEditor* anEditorWdg = anActiveWidget ? dynamic_cast(anActiveWidget) : 0; + // the active widget editor should not influence here. The presentation should be visible always + // when this widget is active. + if (!anEditorWdg && !myIsPopupMenuActive) { + // during a nested create operation, the feature is redisplayed only if the mouse over view + // of there was a value modified in the property panel after the mouse left the view + aCanDisplay = canDisplayCurrentCreatedFeature(); + } + } + #endif + } + } + + // checks the sketcher constraints visibility according to active sketch check box states + if (aCanDisplay) { + bool aProcessed = false; + FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); + if (aFeature.get()) { + bool aConstraintDisplayed = canDisplayConstraint(aFeature, PartSet_Tools::Any, aProcessed); + if (aProcessed) + aCanDisplay = aConstraintDisplayed; + } + } + + return aCanDisplay; +} + +bool PartSet_SketcherMgr::canDisplayConstraint(const FeaturePtr& theFeature, + const PartSet_Tools::ConstraintVisibleState& theState, + bool& isProcessed) const +{ + bool aSwitchedOn = true; + + const QStringList& aConstrIds = constraintsIdList(); + + std::string aKind = theFeature->getKind(); + if (aConstrIds.contains(QString(aKind.c_str()))) { + bool isTypedConstraint = false; + + switch (theState) { + case PartSet_Tools::Dimensional: { + bool isDistance = isDistanceKind(aKind); + if (isDistance) { + isProcessed = true; + aSwitchedOn = myIsConstraintsShown[theState]; + } + } + break; + case PartSet_Tools::Geometrical: { + bool isGeometrical = !isDistanceKind(aKind); + if (isGeometrical) { + isProcessed = true; + aSwitchedOn = myIsConstraintsShown[theState]; + } + } + break; + case PartSet_Tools::Any: { + isProcessed = true; + bool isDistance = isDistanceKind(aKind); + if (isDistance) + aSwitchedOn = myIsConstraintsShown[PartSet_Tools::Dimensional]; + else + aSwitchedOn = myIsConstraintsShown[PartSet_Tools::Geometrical]; + } + break; + default: + break; + } + } + return aSwitchedOn; +} + +/*void PartSet_SketcherMgr::processHiddenObject(const std::list& theObjects) +{ + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (aFOperation && myCurrentSketch.get()) { + // find results of the current operation + // these results should not be proposed to be deleted + FeaturePtr anOperationFeature = aFOperation->feature(); + std::list anOperationResultList = anOperationFeature->results(); + std::set anOperationResults; + std::list::const_iterator aRIt = anOperationResultList.begin(), + aRLast = anOperationResultList.end(); + for (; aRIt != aRLast; aRIt++) + anOperationResults.insert(*aRIt); + + std::set anObjectsToBeDeleted; + QStringList anObjectsToBeDeletedNames; + std::list::const_iterator anIt = theObjects.begin(), aLast = theObjects.end(); + for (; anIt != aLast; anIt++) { + ObjectPtr anObject = *anIt; + bool aCanErase = true; + // when the sketch operation is active, results of sketch sub-feature can not be hidden + ResultPtr aResult = std::dynamic_pointer_cast(anObject); + // the result is found between current feature results + if (anOperationResults.find(aResult) != anOperationResults.end()) + continue; + + if (aResult.get()) { + // Display sketcher objects + for (int i = 0; i < myCurrentSketch->numberOfSubs() && aCanErase; i++) { + FeaturePtr aFeature = myCurrentSketch->subFeature(i); + std::list aResults = aFeature->results(); + std::list::const_iterator anIt; + for (anIt = aResults.begin(); anIt != aResults.end() && aCanErase; ++anIt) { + aCanErase = *anIt != aResult; + } + } + } + if (!aCanErase) { + FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); + if (aFeature.get() && anObjectsToBeDeleted.find(aFeature) == anObjectsToBeDeleted.end()) { + anObjectsToBeDeleted.insert(aFeature); + anObjectsToBeDeletedNames.append(aFeature->name().c_str()); + } + } + } + if (!anObjectsToBeDeleted.empty()) { + QString aFeatureNames = anObjectsToBeDeletedNames.join(", "); + QString aMessage = tr("The following features have incorrect presentation and \ +will be hidden: %1. Would you like to delete them?") + .arg(aFeatureNames); + int anAnswer = QMessageBox::question(qApp->activeWindow(), tr("Features hide"), + aMessage, QMessageBox::Ok | QMessageBox::Cancel, + QMessageBox::Cancel); + if (anAnswer == QMessageBox::Ok) { + QObjectPtrList anObjects; + std::set::const_iterator anIt = anObjectsToBeDeleted.begin(), + aLast = anObjectsToBeDeleted.end(); + for (; anIt != aLast; anIt++) + anObjects.append(*anIt); + SessionPtr aMgr = ModelAPI_Session::get(); + DocumentPtr aDoc = aMgr->activeDocument(); + bool aIsOp = aMgr->isOperation(); + if (!aIsOp) + aMgr->startOperation(); + workshop()->deleteFeatures(anObjects); + //static Events_ID aDeletedEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED); + //static Events_ID aRedispEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY); + //Events_Loop::loop()->flush(aDeletedEvent); + //Events_Loop::loop()->flush(aRedispEvent); + + if (!aIsOp) + aMgr->finishOperation(); + } + } + } +}*/ + +bool PartSet_SketcherMgr::canDisplayCurrentCreatedFeature() const +{ + bool aCanDisplay = myIsMouseOverWindow; + if (!aCanDisplay) { + ModuleBase_ModelWidget* anActiveWidget = getActiveWidget(); + if (anActiveWidget) + aCanDisplay = anActiveWidget->getValueState() == ModuleBase_ModelWidget::Stored; + } + return aCanDisplay; +} + +bool PartSet_SketcherMgr::canChangeCursor(ModuleBase_Operation* theOperation) const +{ + return isNestedCreateOperation(theOperation, activeSketch()) || + myModule->sketchReentranceMgr()->isInternalEditActive(); +} + +const QMap& PartSet_SketcherMgr::showConstraintStates() +{ + return myIsConstraintsShown; +} + +bool PartSet_SketcherMgr::isObjectOfSketch(const ObjectPtr& theObject) const +{ + bool isFoundObject = false; + + FeaturePtr anObjectFeature = ModelAPI_Feature::feature(theObject); + if (anObjectFeature.get()) { + int aSize = myCurrentSketch->numberOfSubs(); + for (int i = 0; i < myCurrentSketch->numberOfSubs() && !isFoundObject; i++) { + FeaturePtr aCurrentFeature = myCurrentSketch->subFeature(i); + isFoundObject = myCurrentSketch->subFeature(i) == anObjectFeature; + } + } + return isFoundObject; +} + +void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr& thePln) +{ + if (myPlaneFilter.IsNull()) + myPlaneFilter = new ModuleBase_ShapeInPlaneFilter(); + + myPlaneFilter->setPlane(thePln); +} + +bool PartSet_SketcherMgr::setDistanceValueByPreselection(ModuleBase_Operation* theOperation, + ModuleBase_IWorkshop* theWorkshop, + bool& theCanCommitOperation) +{ + bool isValueAccepted = false; + theCanCommitOperation = false; + + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (theOperation); + FeaturePtr aFeature = aFOperation->feature(); + // editor is shown only if all attribute references are filled by preseletion + bool anAllRefAttrInitialized = true; + + std::list aRefAttrs = aFeature->data()->attributes( + ModelAPI_AttributeRefAttr::typeId()); + std::list::const_iterator anIt = aRefAttrs.begin(), aLast = aRefAttrs.end(); + for (; anIt != aLast && anAllRefAttrInitialized; anIt++) { + anAllRefAttrInitialized = (*anIt)->isInitialized(); + } + if (anAllRefAttrInitialized) { + // Activate dimension value editing on double click + ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel(); + QList aWidgets = aPanel->modelWidgets(); + // Find corresponded widget to activate value editing + foreach (ModuleBase_ModelWidget* aWgt, aWidgets) { + if (aWgt->attributeID() == "ConstraintValue") { + // the featue should be displayed in order to find the AIS text position, + // the place where the editor will be shown + aFeature->setDisplayed(true); + /// the execute is necessary to perform in the feature compute for flyout position + aFeature->execute(); + + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED)); + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); + + PartSet_WidgetEditor* anEditor = dynamic_cast(aWgt); + if (anEditor) { + int aX = 0, anY = 0; + + XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(theWorkshop); + XGUI_Displayer* aDisplayer = aWorkshop->displayer(); + AISObjectPtr anAIS = aDisplayer->getAISObject(aFeature); + Handle(AIS_InteractiveObject) anAISIO; + if (anAIS.get() != NULL) { + anAISIO = anAIS->impl(); + } + if (anAIS.get() != NULL) { + Handle(AIS_InteractiveObject) anAISIO = anAIS->impl(); + + if (!anAISIO.IsNull()) { + Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast(anAISIO); + if (!aDim.IsNull()) { + gp_Pnt aPosition = aDim->GetTextPosition(); + + ModuleBase_IViewer* aViewer = aWorkshop->viewer(); + Handle(V3d_View) aView = aViewer->activeView(); + int aCX, aCY; + aView->Convert(aPosition.X(), aPosition.Y(), aPosition.Z(), aCX, aCY); + + QWidget* aViewPort = aViewer->activeViewPort(); + QPoint aGlPoint = aViewPort->mapToGlobal(QPoint(aCX, aCY)); + aX = aGlPoint.x(); + anY = aGlPoint.y(); + } + } + anEditor->setCursorPosition(aX, anY); + isValueAccepted = anEditor->showPopupEditor(false); + theCanCommitOperation = true; + } + } + } + } + } + return isValueAccepted; +} + +void PartSet_SketcherMgr::getSelectionOwners(const FeaturePtr& theFeature, + const FeaturePtr& theSketch, + ModuleBase_IWorkshop* theWorkshop, + const FeatureToSelectionMap& theSelection, + SelectMgr_IndexedMapOfOwner& theOwnersToSelect) +{ + if (theFeature.get() == NULL) + return; + + FeatureToSelectionMap::const_iterator anIt = theSelection.find(theFeature); + std::set aSelectedAttributes = anIt.value().first; + std::set aSelectedResults = anIt.value().second; + + ModuleBase_IViewer* aViewer = theWorkshop->viewer(); + + XGUI_ModuleConnector* aConnector = dynamic_cast(theWorkshop); + XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); + + // 1. found the feature's owners. Check the AIS objects of the constructions + AISObjectPtr aAISObj = aDisplayer->getAISObject(theFeature); + if (aAISObj.get() != NULL && aSelectedAttributes.empty() && aSelectedResults.empty()) { + Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl(); + + SelectMgr_IndexedMapOfOwner aSelectedOwners; + aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners); + for (Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++) { + Handle(SelectMgr_EntityOwner) anOwner = aSelectedOwners(i); + if (!anOwner.IsNull()) + theOwnersToSelect.Add(anOwner); + } + } + + // 2. found the feature results's owners + std::list aResults = theFeature->results(); + std::list::const_iterator aIt; + for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) + { + ResultPtr aResult = *aIt; + AISObjectPtr aAISObj = aDisplayer->getAISObject(aResult); + if (aAISObj.get() == NULL) + continue; + Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl(); + + SelectMgr_IndexedMapOfOwner aSelectedOwners; + aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners); + for ( Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++ ) { + Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast(aSelectedOwners(i)); + if ( anOwner.IsNull() || !anOwner->HasShape() ) + continue; + const TopoDS_Shape& aShape = anOwner->Shape(); + TopAbs_ShapeEnum aShapeType = aShape.ShapeType(); + if (aShapeType == TopAbs_VERTEX) { + AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theFeature, aShape, theSketch); + if (aPntAttr.get() != NULL && + aSelectedAttributes.find(aPntAttr) != aSelectedAttributes.end()) { + theOwnersToSelect.Add(anOwner); + } + } + else if (aShapeType == TopAbs_EDGE) { + bool aFound = aSelectedResults.find(aResult) != aSelectedResults.end(); + if (aSelectedResults.find(aResult) != aSelectedResults.end() && + theOwnersToSelect.FindIndex(anOwner) <= 0) + theOwnersToSelect.Add(anOwner); + } + } + } +} + +void PartSet_SketcherMgr::connectToPropertyPanel(ModuleBase_ModelWidget* theWidget, const bool isToConnect) +{ + if (isToConnect) { + connect(theWidget, SIGNAL(beforeValuesChanged()), + this, SLOT(onBeforeValuesChangedInPropertyPanel())); + connect(theWidget, SIGNAL(afterValuesChanged()), + this, SLOT(onAfterValuesChangedInPropertyPanel())); + } + else { + disconnect(theWidget, SIGNAL(beforeValuesChanged()), + this, SLOT(onBeforeValuesChangedInPropertyPanel())); + disconnect(theWidget, SIGNAL(afterValuesChanged()), + this, SLOT(onAfterValuesChangedInPropertyPanel())); + } +} + +void PartSet_SketcherMgr::widgetStateChanged(int thePreviousState) +{ + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (aFOperation) { + if (PartSet_SketcherMgr::isSketchOperation(aFOperation) || + isNestedSketchOperation(aFOperation) && + thePreviousState == ModuleBase_ModelWidget::ModifiedInPP) { + FeaturePtr aFeature = aFOperation->feature(); + visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature)); + } + } +} + +void PartSet_SketcherMgr::customizePresentation(const ObjectPtr& theObject) +{ + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (aFOperation && (PartSet_SketcherMgr::isSketchOperation(aFOperation) || + isNestedSketchOperation(aFOperation))) + SketcherPrs_Tools::sendExpressionShownEvent(myIsConstraintsShown[PartSet_Tools::Expressions]); + + // update entities selection priorities + FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); + if (aFeature.get() && PartSet_SketcherMgr::isEntity(aFeature->getKind())) { + // update priority for feature + updateSelectionPriority(aFeature, aFeature); + // update priority for results of the feature + std::list aResults = aFeature->results(); + std::list::const_iterator anIt = aResults.begin(), aLastIt = aResults.end(); + for (; anIt != aLastIt; anIt++) + updateSelectionPriority(*anIt, aFeature); + } +} + +ModuleBase_Operation* PartSet_SketcherMgr::getCurrentOperation() const +{ + return myModule->workshop()->currentOperation(); +} + +//************************************************************** +ModuleBase_ModelWidget* PartSet_SketcherMgr::getActiveWidget() const +{ + ModuleBase_ModelWidget* aWidget = 0; + ModuleBase_Operation* anOperation = getCurrentOperation(); + if (anOperation) { + ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel(); + if (aPanel) + aWidget = aPanel->activeWidget(); + } + return aWidget; +} + +void PartSet_SketcherMgr::visualizeFeature(const FeaturePtr& theFeature, + const bool isEditOperation, + const bool isToDisplay, + const bool isFlushRedisplay) +{ + #ifdef DEBUG_DO_NOT_BY_ENTER + return; + #endif + + if (isEditOperation || !theFeature.get()) + return; + + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); + + // 1. change visibility of the object itself, here the presentable object is processed, + // e.g. constraints features + //FeaturePtr aFeature = aFOperation->feature(); + std::list aResults = theFeature->results(); + if (isToDisplay) + theFeature->setDisplayed(true); + else + theFeature->setDisplayed(false); + + // change visibility of the object results, e.g. non-constraint features + std::list::const_iterator aIt; + for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { + if (isToDisplay) { + (*aIt)->setDisplayed(true); + } + else { + (*aIt)->setDisplayed(false); + } + } + if (isFlushRedisplay) + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); +} + +void PartSet_SketcherMgr::storeSelection(const bool theHighlightedOnly) +{ + if (!myCurrentSketch.get()) + return; + + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + ModuleBase_ISelection* aSelect = aWorkshop->selection(); + QList aStoredPrs = aSelect->getHighlighted(); + + QList aFeatureList; + if (!theHighlightedOnly) { + QList aSelected = aSelect->getSelected( + ModuleBase_ISelection::AllControls); + aStoredPrs.append(aSelected); + } + + // 1. it is necessary to save current selection in order to restore it after the features moving + myCurrentSelection.clear(); + + QList::const_iterator anIt = aStoredPrs.begin(), aLast = aStoredPrs.end(); + + CompositeFeaturePtr aSketch = activeSketch(); + for (; anIt != aLast; anIt++) { + ModuleBase_ViewerPrsPtr aPrs = *anIt; + ObjectPtr anObject = aPrs->object(); + if (!anObject.get()) + continue; + + ResultPtr aResult = std::dynamic_pointer_cast(anObject); + FeaturePtr aFeature; + if (aResult.get()) + aFeature = ModelAPI_Feature::feature(aResult); + else + aFeature = std::dynamic_pointer_cast(anObject); + + + std::set aSelectedAttributes; + std::set aSelectedResults; + if (myCurrentSelection.find(aFeature) != myCurrentSelection.end()) { + std::pair, std::set > aPair = myCurrentSelection.find(aFeature).value(); + aSelectedAttributes = aPair.first; + aSelectedResults = aPair.second; + } + + Handle(SelectMgr_EntityOwner) anOwner = aPrs->owner(); + if (aResult.get()) { + getAttributesOrResults(anOwner, aFeature, aSketch, aResult, + aSelectedAttributes, aSelectedResults); + } + else { + std::list aResults = aFeature->results(); + std::list::const_iterator aIt; + for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { + ResultPtr aResult = *aIt; + getAttributesOrResults(anOwner, aFeature, aSketch, aResult, + aSelectedAttributes, aSelectedResults); + } + } + myCurrentSelection[aFeature] = std::make_pair(aSelectedAttributes, aSelectedResults); + } + //qDebug(QString(" storeSelection: %1").arg(myCurrentSelection.size()).toStdString().c_str()); +} + +void PartSet_SketcherMgr::restoreSelection() +{ + if (!myCurrentSketch.get()) + return; + + //qDebug(QString("restoreSelection: %1").arg(myCurrentSelection.size()).toStdString().c_str()); + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); + FeatureToSelectionMap::const_iterator aSIt = myCurrentSelection.begin(), + aSLast = myCurrentSelection.end(); + SelectMgr_IndexedMapOfOwner anOwnersToSelect; + for (; aSIt != aSLast; aSIt++) { + anOwnersToSelect.Clear(); + getSelectionOwners(aSIt.key(), myCurrentSketch, aWorkshop, myCurrentSelection, + anOwnersToSelect); + aConnector->workshop()->selector()->setSelectedOwners(anOwnersToSelect, false); + } +} + +void PartSet_SketcherMgr::onShowConstraintsToggle(int theType, bool theState) +{ + PartSet_Tools::ConstraintVisibleState aType = (PartSet_Tools::ConstraintVisibleState)theType; + + updateBySketchParameters(aType, theState); +} + +void PartSet_SketcherMgr::updateBySketchParameters( + const PartSet_Tools::ConstraintVisibleState& theType, + bool theState) +{ + if (myCurrentSketch.get() == NULL) + return; + + bool aPrevState = myIsConstraintsShown[theType]; + myIsConstraintsShown[theType] = theState; + + switch (theType) { + case PartSet_Tools::Geometrical: + case PartSet_Tools::Dimensional: { + if (aPrevState != theState) { + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); + for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) { + FeaturePtr aSubFeature = myCurrentSketch->subFeature(i); + bool aProcessed = false; + bool aConstraintDisplayed = canDisplayConstraint(aSubFeature, theType, aProcessed); + if (aProcessed) + aSubFeature->setDisplayed(aConstraintDisplayed); + } + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); + } + } + break; + case PartSet_Tools::Expressions: { + if (aPrevState != theState) { + /// call all sketch features redisplay, the expression state will be corrected in customize + /// of distance presentation + Events_ID anEventId = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); + PartSet_Tools::sendSubFeaturesEvent(myCurrentSketch, anEventId); + } + } + break; + } +} + +void PartSet_SketcherMgr::updateSelectionPriority(ObjectPtr theObject, + FeaturePtr theFeature) +{ + if (!theObject.get() || !theFeature.get()) + return; + + AISObjectPtr anAIS = workshop()->displayer()->getAISObject(theObject); + Handle(AIS_InteractiveObject) anAISIO; + if (anAIS.get() != NULL) { + anAISIO = anAIS->impl(); + } + + if (!anAISIO.IsNull()) { // the presentation for the object is visualized + int anAdditionalPriority = 0; + // current feature + std::shared_ptr aSPFeature = + std::dynamic_pointer_cast(theFeature); + if (aSPFeature.get() != NULL) { + // 1. Vertices + // 2. Simple segments + // 3. External objects (violet color) + // 4. Auxiliary segments (dotted) + // StdSelect_BRepSelectionTool::Load uses priority calculating: + // Standard_Integer aPriority = (thePriority == -1) ? GetStandardPriority (theShape, theType) : thePriority; + // Priority of Vertex is 8, edge(segment) is 7. + // It might be not corrected as provides the condition above. + bool isExternal = aSPFeature->isExternal(); + bool isAuxiliary = PartSet_Tools::isAuxiliarySketchEntity(aSPFeature); + // current feature + if (!isExternal && !isAuxiliary) + anAdditionalPriority = 30; + // external feature + if (isExternal) + anAdditionalPriority = 20; + // auxiliary feature + if (isAuxiliary) { + anAdditionalPriority = 10; /// auxiliary objects should have less priority that + // edges/vertices of local selection on not-sketch objects + } + Handle(ModuleBase_ResultPrs) aResult = Handle(ModuleBase_ResultPrs)::DownCast(anAISIO); + if (!aResult.IsNull()) { + aResult->setAdditionalSelectionPriority(anAdditionalPriority); + } + } + } +} + +XGUI_Workshop* PartSet_SketcherMgr::workshop() const +{ + ModuleBase_IWorkshop* anIWorkshop = myModule->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(anIWorkshop); + return aConnector->workshop(); +} + +XGUI_OperationMgr* PartSet_SketcherMgr::operationMgr() const +{ + return workshop()->operationMgr(); +} + diff --git a/src/PartSet/PartSet_SketcherReetntrantMgr.cpp b/src/PartSet/PartSet_SketcherReetntrantMgr.cpp index 4cfcf167d..5bc007456 100755 --- a/src/PartSet/PartSet_SketcherReetntrantMgr.cpp +++ b/src/PartSet/PartSet_SketcherReetntrantMgr.cpp @@ -161,7 +161,7 @@ bool PartSet_SketcherReetntrantMgr::processMouseMoved(ModuleBase_IViewWindow* th /// before restarting of operation we need to clear selection, as it may take part in /// new feature creation, e.g. tangent arc. But it is not necessary as it was processed /// by mouse release when the operation was restarted. - workshop()->selector()->clearSelection(); + workshop()->selector()->clearSelection(); myPreviousFeature = aFOperation->feature(); restartOperation(); diff --git a/src/XGUI/XGUI_OperationMgr.cpp b/src/XGUI/XGUI_OperationMgr.cpp index 4db8401dc..9eed33074 100644 --- a/src/XGUI/XGUI_OperationMgr.cpp +++ b/src/XGUI/XGUI_OperationMgr.cpp @@ -1,745 +1,745 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> - -// File: XGUI_OperationMgr.cpp -// Created: 20 Apr 2014 -// Author: Natalia ERMOLAEVA - -#include "XGUI_OperationMgr.h" -#include "XGUI_ModuleConnector.h" -#include "XGUI_Workshop.h" -#include "XGUI_ErrorMgr.h" -#include "XGUI_Tools.h" -#include "XGUI_ObjectsBrowser.h" -#include "XGUI_ContextMenuMgr.h" - -#include -#include -#include "ModuleBase_Operation.h" -#include "ModuleBase_IWorkshop.h" -#include "ModuleBase_IModule.h" -#include -#include "ModuleBase_OperationDescription.h" -#include "ModuleBase_OperationFeature.h" -#include "ModuleBase_Tools.h" - -#include "ModelAPI_CompositeFeature.h" -#include "ModelAPI_Session.h" - -#include -#include -#include - -#include -#include -#include - -//#define DEBUG_CURRENT_FEATURE - -/// Processes "Delete" key event of application. This key is used by several application actions. -/// There is a logical order of the actions processing. So the key can not be set for actions -/// as a shortcut. The class listens the key event and call operation manager processor. -class XGUI_ShortCutListener : public QObject -{ -public: - /// Constructor - /// \param theParent the parent to be deleted when the parent is deleted - /// \param theOperationMgr the class to perform deletion - XGUI_ShortCutListener(QObject* theParent, XGUI_OperationMgr* theOperationMgr) - : QObject(theParent), myOperationMgr(theOperationMgr) - { - qApp->installEventFilter(this); - } - ~XGUI_ShortCutListener() {} - - /// Switch on short cut listener - void setActive(const bool theIsActive) { myIsActive = theIsActive; } - - /// Redefinition of virtual function to process Delete key release - virtual bool eventFilter(QObject *theObject, QEvent *theEvent) - { - bool isAccepted = false; - if (myIsActive && theEvent->type() == QEvent::KeyRelease) { - QKeyEvent* aKeyEvent = dynamic_cast(theEvent); - if(aKeyEvent) { - switch (aKeyEvent->key()) { - case Qt::Key_Delete: { - isAccepted = myOperationMgr->onProcessDelete(theObject); - } - } - } - } - if (!isAccepted) - isAccepted = QObject::eventFilter(theObject, theEvent); - return isAccepted; - } - -private: - XGUI_OperationMgr* myOperationMgr; /// processor for key event - bool myIsActive; /// boolean state whether the event filter perform own signal processing -}; - -XGUI_OperationMgr::XGUI_OperationMgr(QObject* theParent, - ModuleBase_IWorkshop* theWorkshop) -: QObject(theParent), myWorkshop(theWorkshop) -{ - /// we need to install filter to the application in order to react to 'Delete' key button - /// this key can not be a short cut for a corresponded action because we need to set - /// the actions priority - myShortCutListener = new XGUI_ShortCutListener(theParent, this); -} - -XGUI_OperationMgr::~XGUI_OperationMgr() -{ -} - -void XGUI_OperationMgr::activate() -{ - myShortCutListener->setActive(true); -} - -void XGUI_OperationMgr::deactivate() -{ - myShortCutListener->setActive(false); -} - -ModuleBase_Operation* XGUI_OperationMgr::currentOperation() const -{ - return myOperations.count() > 0 ? myOperations.last() : 0; -} - -bool XGUI_OperationMgr::isCurrentOperation(ModuleBase_Operation* theOperation) -{ - if(!hasOperation()) - return false; - return currentOperation() == theOperation; -} - -bool XGUI_OperationMgr::hasOperation() const -{ - return !myOperations.isEmpty() && (myOperations.last() != NULL); -} - -bool XGUI_OperationMgr::hasOperation(const QString& theId) const -{ - foreach(ModuleBase_Operation* aOp, myOperations) { - if (aOp->id() == theId) - return true; - } - return false; -} - -ModuleBase_Operation* XGUI_OperationMgr::findOperation(const QString& theId) const -{ - QList::const_iterator anIt = myOperations.end(); - while (anIt != myOperations.begin()) { - --anIt; - ModuleBase_Operation* anOperation = *anIt; - if (anOperation->id() == theId) - return anOperation; - } - return 0; -} - - -int XGUI_OperationMgr::operationsCount() const -{ - return myOperations.count(); -} - -QStringList XGUI_OperationMgr::operationList() const -{ - QStringList result; - foreach(ModuleBase_Operation* eachOperation, myOperations) { - ModuleBase_OperationFeature* aFOperation = dynamic_cast(eachOperation); - if (aFOperation) { - FeaturePtr aFeature = aFOperation->feature(); - if(aFeature) { - result << QString::fromStdString(aFeature->getKind()); - } - } - } - return result; -} - -ModuleBase_Operation* XGUI_OperationMgr::previousOperation(ModuleBase_Operation* theOperation) const -{ - int idx = myOperations.lastIndexOf(theOperation); - if(idx == -1 || idx == 0) { - return NULL; - } - return myOperations.at(idx - 1); -} - -bool XGUI_OperationMgr::eventFilter(QObject *theObject, QEvent *theEvent) -{ - bool isAccepted = false; - if (theEvent->type() == QEvent::KeyRelease) { - QKeyEvent* aKeyEvent = dynamic_cast(theEvent); - if(aKeyEvent) - isAccepted = onKeyReleased(theObject, aKeyEvent); - } - if (!isAccepted) - isAccepted = QObject::eventFilter(theObject, theEvent); - - return isAccepted; -} - -bool XGUI_OperationMgr::startOperation(ModuleBase_Operation* theOperation) -{ - if (hasOperation()) - currentOperation()->postpone(); - myOperations.append(theOperation); - - connect(theOperation, SIGNAL(beforeStarted()), SLOT(onBeforeOperationStarted())); - connect(theOperation, SIGNAL(beforeAborted()), SLOT(onBeforeOperationAborted())); - connect(theOperation, SIGNAL(beforeCommitted()), SLOT(onBeforeOperationCommitted())); - - connect(theOperation, SIGNAL(started()), SLOT(onOperationStarted())); - connect(theOperation, SIGNAL(aborted()), SLOT(onOperationAborted())); - connect(theOperation, SIGNAL(committed()), SLOT(onOperationCommitted())); - - connect(theOperation, SIGNAL(stopped()), SLOT(onOperationStopped())); - connect(theOperation, SIGNAL(resumed()), SLOT(onOperationResumed())); - - bool isStarted = theOperation->start(); - if (isStarted) - onValidateOperation(); - return isStarted; -} - -bool XGUI_OperationMgr::abortAllOperations() -{ - bool aResult = true; - if(!hasOperation()) - return aResult; - - if (operationsCount() == 1) { - ModuleBase_Operation* aCurrentOperation = currentOperation(); - if (canStopOperation(aCurrentOperation)) { - abortOperation(aCurrentOperation); - } - else - aResult = false; - } - else { - aResult = QMessageBox::question(qApp->activeWindow(), - tr("Abort operation"), - tr("All active operations will be aborted."), - QMessageBox::Ok | QMessageBox::Cancel, - QMessageBox::Cancel) == QMessageBox::Ok; - while(aResult && hasOperation()) { - abortOperation(currentOperation()); - } - } - return aResult; -} - -bool XGUI_OperationMgr::commitAllOperations() -{ - bool isCompositeCommitted = false, anOperationProcessed = false; - while (hasOperation()) { - ModuleBase_Operation* anOperation = currentOperation(); - if (XGUI_Tools::workshop(myWorkshop)->errorMgr()->isApplyEnabled()) { - anOperationProcessed = onCommitOperation(); - } else { - abortOperation(anOperation); - anOperationProcessed = true; - } - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (anOperation); - if (aFOperation) { - FeaturePtr aFeature = aFOperation->feature(); - CompositeFeaturePtr aComposite = - std::dynamic_pointer_cast(aFeature); - isCompositeCommitted = aComposite.get(); - if (isCompositeCommitted) - break; - } - // not processed[committed] operation might be used in composite feature, - // so the while will be stopped by the previous check. - // this code is not necessary, but logically should be done when the processing will not - // be done for not composite feature by some reasons - if (!anOperationProcessed) - break; - } - return true; -} - -void XGUI_OperationMgr::onValidateOperation() -{ - if (!hasOperation()) - return; - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (currentOperation()); - if(aFOperation && aFOperation->feature().get()) - XGUI_Tools::workshop(myWorkshop)->errorMgr()->updateActions(aFOperation->feature()); -} - -void XGUI_OperationMgr::updateApplyOfOperations(ModuleBase_Operation* theOperation) -{ - XGUI_ErrorMgr* anErrorMgr = XGUI_Tools::workshop(myWorkshop)->errorMgr(); - if (theOperation) { - ModuleBase_OperationFeature* aFOperation = dynamic_cast(theOperation); - if (aFOperation) - anErrorMgr->updateAcceptAllAction(aFOperation->feature()); - } - else { - foreach(ModuleBase_Operation* anOperation, myOperations) { - if (anOperation) - updateApplyOfOperations(anOperation); - } - } - // Apply button of the current operation should also be updated - onValidateOperation(); -} - -bool XGUI_OperationMgr::canStopOperation(ModuleBase_Operation* theOperation) -{ - //in case of nested (sketch) operation no confirmation needed - if (isGrantedOperation(theOperation->id())) - return true; - if (theOperation && theOperation->isModified()) { - QString aMessage = tr("%1 operation will be aborted.").arg(theOperation->id()); - int anAnswer = QMessageBox::question(qApp->activeWindow(), - tr("Abort operation"), - aMessage, - QMessageBox::Ok | QMessageBox::Cancel, - QMessageBox::Cancel); - return anAnswer == QMessageBox::Ok; - } - return true; -} - -bool XGUI_OperationMgr::commitOperation() -{ - //if (hasOperation() && currentOperation()->isValid()) { - // onCommitOperation(); - // return true; - //} - //return false; - return onCommitOperation(); -} - -void XGUI_OperationMgr::resumeOperation(ModuleBase_Operation* theOperation) -{ - theOperation->resume(); -} - -bool XGUI_OperationMgr::isGrantedOperation(const QString& theId) -{ - bool isGranted = false; - - QListIterator anIt(myOperations); - anIt.toBack(); - ModuleBase_Operation* aPreviousOperation = 0; - while (anIt.hasPrevious() && !isGranted) { - ModuleBase_Operation* anOp = anIt.previous(); - if (anOp) - isGranted = anOp->isGranted(theId); - } - return isGranted; -} - -void XGUI_OperationMgr::setCurrentFeature(const FeaturePtr& theFeature) -{ - SessionPtr aMgr = ModelAPI_Session::get(); - DocumentPtr aDoc = aMgr->activeDocument(); - bool aIsOp = aMgr->isOperation(); - if (!aIsOp) - aMgr->startOperation(QString("Set current feature: %1").arg(theFeature->getKind().c_str()).toStdString()); - aDoc->setCurrentFeature(theFeature, false); - if (!aIsOp) - aMgr->finishOperation(); -} - -bool XGUI_OperationMgr::canStartOperation(const QString& theId) -{ - bool aCanStart = true; - ModuleBase_Operation* aCurrentOp = currentOperation(); - if (aCurrentOp) { - bool aGranted = aCurrentOp->isGranted(theId); - // the started operation is granted for the current one, - // e.g. current - Sketch, started - Line - if (aGranted) { - aCanStart = true; - } - else { - if (!isGrantedOperation(theId)) { - // the operation is not granted in the current list of operations - // e.g. Edit Parameter when Sketch, Line in Sketch is active. - aCanStart = abortAllOperations(); - } - else if (canStopOperation(aCurrentOp)) { - // the started operation is granted in the parrent operation, - // e.g. current - Line in Sketch, started Circle - stopOperation(aCurrentOp); - } else { - aCanStart = false; - } - } - } - return aCanStart; -} - -void XGUI_OperationMgr::stopOperation(ModuleBase_Operation* theOperation) -{ - if (XGUI_Tools::workshop(myWorkshop)->errorMgr()->isApplyEnabled() && theOperation->isModified()) - theOperation->commit(); - else - abortOperation(theOperation); -} - -void XGUI_OperationMgr::abortOperation(ModuleBase_Operation* theOperation) -{ - ModuleBase_Operation* aCurrentOperation = currentOperation(); - if (theOperation == aCurrentOperation) - theOperation->abort(); - else { - // it is possible to trigger upper operation(e.g. sketch, current is sketch line) - // all operation from the current to triggered should also be aborted - // operations over the parameter one are not aborted(e.g. extrusion cut, sketch abort) - while(hasOperation()) { - ModuleBase_Operation* aCurrentOperation = currentOperation(); - aCurrentOperation->abort(); - if(theOperation == aCurrentOperation) - break; - } - } -} - -bool XGUI_OperationMgr::onCommitOperation() -{ - bool isCommitted = false; - ModuleBase_Operation* anOperation = currentOperation(); - if (anOperation && myWorkshop->module()->canCommitOperation()) - isCommitted = anOperation->commit(); - return isCommitted; -} - -void XGUI_OperationMgr::onAbortOperation() -{ - ModuleBase_Operation* aCurrentOperation = currentOperation(); - if (aCurrentOperation && canStopOperation(aCurrentOperation)) { - abortOperation(aCurrentOperation); - } -} - -void XGUI_OperationMgr::onBeforeOperationStarted() -{ - ModuleBase_Operation* aCurrentOperation = dynamic_cast(sender()); - if (!aCurrentOperation) - return; - - /// Set current feature and remeber old current feature - ModuleBase_OperationFeature* aFOperation = dynamic_cast(aCurrentOperation); - if (aFOperation) { - SessionPtr aMgr = ModelAPI_Session::get(); - DocumentPtr aDoc = aMgr->activeDocument(); - // the parameter of current feature should be false, we should use all feature, not only visible - // in order to correctly save the previous feature of the nested operation, where the - // features can be not visible in the tree. The problem case is Edit sketch entitity(line) - // in the Sketch, created in ExtrusionCut operation. The entity disappears by commit. - // When sketch entity operation started, the sketch should be cashed here as the current. - // Otherwise(the flag is true), the ExtrusionCut is cashed, when commit happens, the sketch - // is disabled, sketch entity is disabled as extrusion cut is created earliest then sketch. - // As a result the sketch disappears from the viewer. However after commit it is displayed back. - aFOperation->setPreviousCurrentFeature(aDoc->currentFeature(false)); - -#ifdef DEBUG_CURRENT_FEATURE - FeaturePtr aFeature = aFOperation->feature(); - QString aKind = aFeature ? aFeature->getKind().c_str() : ""; - qDebug(QString("onBeforeOperationStarted(), edit operation = %1, feature = %2") - .arg(aFOperation->isEditOperation()) - .arg(ModuleBase_Tools::objectInfo(aFeature)).toStdString().c_str()); - - qDebug(QString("\tdocument->currentFeature(false) = %1").arg( - ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str()); -#endif - - if (aFOperation->isEditOperation()) {// it should be performed by the feature edit only - // in create operation, the current feature is changed by addFeature() - aDoc->setCurrentFeature(aFOperation->feature(), false); - // this is the only place where flushes must be called after setCurrentFeature for the current - // moment: after this the opertion is not finished, so, the ObjectBrowser state may be corrupted - // (issue #1457) - static Events_Loop* aLoop = Events_Loop::loop(); - static Events_ID aCreateEvent = aLoop->eventByName(EVENT_OBJECT_CREATED); - aLoop->flush(aCreateEvent); - static Events_ID aDeleteEvent = aLoop->eventByName(EVENT_OBJECT_DELETED); - aLoop->flush(aDeleteEvent); - } - -#ifdef DEBUG_CURRENT_FEATURE - qDebug("\tdocument->setCurrentFeature"); - qDebug(QString("\tdocument->currentFeature(false) = %1").arg( - ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str()); -#endif - } -} - -void XGUI_OperationMgr::onOperationStarted() -{ - ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); - updateApplyOfOperations(aSenderOperation); - XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop); - aWorkshop->operationStarted(aSenderOperation); -} - -void XGUI_OperationMgr::onBeforeOperationAborted() -{ - onBeforeOperationCommitted(); -} - -void XGUI_OperationMgr::onOperationAborted() -{ - ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); - emit operationAborted(aSenderOperation); -} - -void XGUI_OperationMgr::onBeforeOperationCommitted() -{ - ModuleBase_Operation* aCurrentOperation = dynamic_cast(sender()); - if (!aCurrentOperation) - return; - - /// Restore the previous current feature - ModuleBase_OperationFeature* aFOperation = dynamic_cast(aCurrentOperation); - if (aFOperation) { -#ifdef DEBUG_CURRENT_FEATURE - QString aKind = aFOperation->feature()->getKind().c_str(); - qDebug(QString("onBeforeOperationCommitted(), edit operation = %1, feature = %2") - .arg(aFOperation->isEditOperation()) - .arg(ModuleBase_Tools::objectInfo(aFOperation->feature())).toStdString().c_str()); - - qDebug(QString("\tdocument->currentFeature(false) = %1").arg( - ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str()); -#endif - - if (aFOperation->isEditOperation()) { - /// Restore the previous current feature - setCurrentFeature(aFOperation->previousCurrentFeature()); - } - else { // create operation - // the Top created feature should stays the current. In nested operations, like Line in the Sketch or - // Sketch in ExtrusionCut, a previous feature should be restored on commit. It is performed here - // in order to perform it in the current transaction without opening a new one. - if (myOperations.front() != aFOperation) - setCurrentFeature(aFOperation->previousCurrentFeature()); - } -#ifdef DEBUG_CURRENT_FEATURE - qDebug("\tdocument->setCurrentFeature"); - qDebug(QString("\tdocument->currentFeature(false) = %1").arg( - ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str()); -#endif - ModuleBase_IModule* aModule = myWorkshop->module(); - if (aModule) - aModule->beforeOperationStopped(aFOperation); - } -} - -void XGUI_OperationMgr::onOperationCommitted() -{ - // apply state for all features from the stack of operations should be updated - updateApplyOfOperations(); - - ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); - emit operationCommitted(aSenderOperation); -} - -void XGUI_OperationMgr::onOperationResumed() -{ - ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); - emit operationResumed(aSenderOperation); -} - -void XGUI_OperationMgr::onOperationStopped() -{ - ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); - ModuleBase_Operation* aCurrentOperation = currentOperation(); - if (!aSenderOperation || !aCurrentOperation || aSenderOperation != aCurrentOperation) - return; - - myOperations.removeAll(aCurrentOperation); - aCurrentOperation->deleteLater(); - - emit operationStopped(aCurrentOperation); - - // get last operation which can be resumed - ModuleBase_Operation* aResultOp = 0; - QListIterator anIt(myOperations); - anIt.toBack(); - while (anIt.hasPrevious()) { - ModuleBase_Operation* anOp = anIt.previous(); - if (anOp) { - aResultOp = anOp; - break; - } - } - if (aResultOp) { - bool isModified = aCurrentOperation->isModified(); - aResultOp->setIsModified(aResultOp->isModified() || isModified); - resumeOperation(aResultOp); - onValidateOperation(); - } -} - -bool XGUI_OperationMgr::onKeyReleased(QObject *theObject, QKeyEvent* theEvent) -{ - // Let the manager decide what to do with the given key combination. - ModuleBase_Operation* anOperation = currentOperation(); - bool isAccepted = false; - switch (theEvent->key()) { - case Qt::Key_Return: - case Qt::Key_Enter: { - isAccepted = onProcessEnter(theObject); - } - break; - case Qt::Key_N: - case Qt::Key_P: { - bool noModifiers = (theEvent->modifiers() == Qt::NoModifier); - if (noModifiers) { - ModuleBase_IViewer* aViewer = myWorkshop->viewer(); - Handle(AIS_InteractiveContext) aContext = aViewer->AISContext(); - if (!aContext.IsNull()) { - Handle(V3d_View) aView = aViewer->activeView(); - if ((theEvent->key() == Qt::Key_N)) - aContext->HilightNextDetected(aView); - else if ((theEvent->key() == Qt::Key_P)) - aContext->HilightPreviousDetected(aView); - } - } - } - break; - break; - default: - isAccepted = false; - break; - } - //if(anOperation) { - // anOperation->keyReleased(theEvent->key()); - //} - return isAccepted; -} - -bool XGUI_OperationMgr::onProcessEnter(QObject* theObject) -{ - bool isAccepted = false; - ModuleBase_Operation* aOperation = currentOperation(); - // to avoid enter processing when operation has not been started yet - if (!aOperation) - return isAccepted; - ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); - // only property panel enter is processed in order to do not process enter in application dialogs - bool isPPChild = isChildObject(theObject, aPanel); - if (!isPPChild) - return isAccepted; - - ModuleBase_ModelWidget* anActiveWgt = aPanel->activeWidget(); - bool isAborted = false; - if (!anActiveWgt) { - QWidget* aFocusWidget = aPanel->focusWidget(); - QToolButton* aCancelBtn = dynamic_cast(aPanel)->findButton(PROP_PANEL_CANCEL); - if (aFocusWidget && aCancelBtn && aFocusWidget == aCancelBtn) { - abortOperation(aOperation); - isAccepted = true; - isAborted = true; - } - } - if (!isAborted) { - isAccepted = anActiveWgt && anActiveWgt->processEnter(); - if (!isAccepted) { - isAccepted = myWorkshop->module()->processEnter(anActiveWgt ? anActiveWgt->attributeID() : ""); - if (!isAccepted) { - /// functionality is similar to Apply click - ModuleBase_OperationFeature* aFOperation = dynamic_cast(currentOperation()); - if (!aFOperation || myWorkshop->module()->getFeatureError(aFOperation->feature()).isEmpty()) { - // key released is emitted to apply the current value to the model if it was modified in PP - emit keyEnterReleased(); - commitOperation(); - isAccepted = true; - } - else - isAccepted = false; - } - } - } - return isAccepted; -} - -bool editorControl(QObject* theObject) -{ - QLineEdit* aLineEdit = dynamic_cast(theObject); - return aLineEdit; -} - -bool XGUI_OperationMgr::onProcessDelete(QObject* theObject) -{ - bool isAccepted = false; - ModuleBase_Operation* aOperation = currentOperation(); - ModuleBase_ModelWidget* anActiveWgt = 0; - // firstly the widget should process Delete action - ModuleBase_IPropertyPanel* aPanel; - bool isPPChildObject = false; - if (aOperation) { - aPanel = aOperation->propertyPanel(); - if (aPanel) { - isPPChildObject = isChildObject(theObject, aPanel); - // process delete in active widget only if delete sender is child of property panel - // it is necessary for the case when OB is shown, user perform selection and click Delete - if (isPPChildObject) { - anActiveWgt = aPanel->activeWidget(); - if (anActiveWgt) { - isAccepted = anActiveWgt->processDelete(); - } - } - } - } - if (!isAccepted) { - // after widget, object browser and viewer should process delete - /// other widgets such as line edit controls should not lead to - /// processing delete by workshop - XGUI_ObjectsBrowser* aBrowser = XGUI_Tools::workshop(myWorkshop)->objectBrowser(); - QWidget* aViewPort = myWorkshop->viewer()->activeViewPort(); - bool isToDeleteObject = false; - XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop); - XGUI_ContextMenuMgr* aContextMenuMgr = aWorkshop->contextMenuMgr(); - if (theObject == aBrowser->treeView()) { - aContextMenuMgr->updateObjectBrowserMenu(); - isToDeleteObject = aContextMenuMgr->action("DELETE_CMD")->isEnabled(); - } - else if (isChildObject(theObject, aViewPort)) { - aContextMenuMgr->updateViewerMenu(); - isToDeleteObject = aContextMenuMgr->action("DELETE_CMD")->isEnabled(); - } - else if (isPPChildObject) { - // property panel child object is processed to process delete performed on Apply button of PP - isToDeleteObject = true; - } - else if (editorControl(theObject)) { - isToDeleteObject = false; /// Line Edit of Rename operation in ObjectBrowser - isAccepted = true; - } - - if (isToDeleteObject) { - aWorkshop->deleteObjects(); - isAccepted = true; - } - } - - return isAccepted; -} - -bool XGUI_OperationMgr::isChildObject(const QObject* theObject, const QObject* theParent) -{ - bool isPPChild = false; - if (theParent && theObject) { - QObject* aParent = (QObject*)theObject; - while (aParent ) { - isPPChild = aParent == theParent; - if (isPPChild) - break; - aParent = aParent->parent(); - } - } - return isPPChild; -} +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: XGUI_OperationMgr.cpp +// Created: 20 Apr 2014 +// Author: Natalia ERMOLAEVA + +#include "XGUI_OperationMgr.h" +#include "XGUI_ModuleConnector.h" +#include "XGUI_Workshop.h" +#include "XGUI_ErrorMgr.h" +#include "XGUI_Tools.h" +#include "XGUI_ObjectsBrowser.h" +#include "XGUI_ContextMenuMgr.h" + +#include +#include +#include "ModuleBase_Operation.h" +#include "ModuleBase_IWorkshop.h" +#include "ModuleBase_IModule.h" +#include +#include "ModuleBase_OperationDescription.h" +#include "ModuleBase_OperationFeature.h" +#include "ModuleBase_Tools.h" + +#include "ModelAPI_CompositeFeature.h" +#include "ModelAPI_Session.h" + +#include +#include +#include + +#include +#include +#include + +//#define DEBUG_CURRENT_FEATURE + +/// Processes "Delete" key event of application. This key is used by several application actions. +/// There is a logical order of the actions processing. So the key can not be set for actions +/// as a shortcut. The class listens the key event and call operation manager processor. +class XGUI_ShortCutListener : public QObject +{ +public: + /// Constructor + /// \param theParent the parent to be deleted when the parent is deleted + /// \param theOperationMgr the class to perform deletion + XGUI_ShortCutListener(QObject* theParent, XGUI_OperationMgr* theOperationMgr) + : QObject(theParent), myOperationMgr(theOperationMgr) + { + qApp->installEventFilter(this); + } + ~XGUI_ShortCutListener() {} + + /// Switch on short cut listener + void setActive(const bool theIsActive) { myIsActive = theIsActive; } + + /// Redefinition of virtual function to process Delete key release + virtual bool eventFilter(QObject *theObject, QEvent *theEvent) + { + bool isAccepted = false; + if (myIsActive && theEvent->type() == QEvent::KeyRelease) { + QKeyEvent* aKeyEvent = dynamic_cast(theEvent); + if(aKeyEvent) { + switch (aKeyEvent->key()) { + case Qt::Key_Delete: { + isAccepted = myOperationMgr->onProcessDelete(theObject); + } + } + } + } + if (!isAccepted) + isAccepted = QObject::eventFilter(theObject, theEvent); + return isAccepted; + } + +private: + XGUI_OperationMgr* myOperationMgr; /// processor for key event + bool myIsActive; /// boolean state whether the event filter perform own signal processing +}; + +XGUI_OperationMgr::XGUI_OperationMgr(QObject* theParent, + ModuleBase_IWorkshop* theWorkshop) +: QObject(theParent), myWorkshop(theWorkshop) +{ + /// we need to install filter to the application in order to react to 'Delete' key button + /// this key can not be a short cut for a corresponded action because we need to set + /// the actions priority + myShortCutListener = new XGUI_ShortCutListener(theParent, this); +} + +XGUI_OperationMgr::~XGUI_OperationMgr() +{ +} + +void XGUI_OperationMgr::activate() +{ + myShortCutListener->setActive(true); +} + +void XGUI_OperationMgr::deactivate() +{ + myShortCutListener->setActive(false); +} + +ModuleBase_Operation* XGUI_OperationMgr::currentOperation() const +{ + return myOperations.count() > 0 ? myOperations.last() : 0; +} + +bool XGUI_OperationMgr::isCurrentOperation(ModuleBase_Operation* theOperation) +{ + if(!hasOperation()) + return false; + return currentOperation() == theOperation; +} + +bool XGUI_OperationMgr::hasOperation() const +{ + return !myOperations.isEmpty() && (myOperations.last() != NULL); +} + +bool XGUI_OperationMgr::hasOperation(const QString& theId) const +{ + foreach(ModuleBase_Operation* aOp, myOperations) { + if (aOp->id() == theId) + return true; + } + return false; +} + +ModuleBase_Operation* XGUI_OperationMgr::findOperation(const QString& theId) const +{ + QList::const_iterator anIt = myOperations.end(); + while (anIt != myOperations.begin()) { + --anIt; + ModuleBase_Operation* anOperation = *anIt; + if (anOperation->id() == theId) + return anOperation; + } + return 0; +} + + +int XGUI_OperationMgr::operationsCount() const +{ + return myOperations.count(); +} + +QStringList XGUI_OperationMgr::operationList() const +{ + QStringList result; + foreach(ModuleBase_Operation* eachOperation, myOperations) { + ModuleBase_OperationFeature* aFOperation = dynamic_cast(eachOperation); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + if(aFeature) { + result << QString::fromStdString(aFeature->getKind()); + } + } + } + return result; +} + +ModuleBase_Operation* XGUI_OperationMgr::previousOperation(ModuleBase_Operation* theOperation) const +{ + int idx = myOperations.lastIndexOf(theOperation); + if(idx == -1 || idx == 0) { + return NULL; + } + return myOperations.at(idx - 1); +} + +bool XGUI_OperationMgr::eventFilter(QObject *theObject, QEvent *theEvent) +{ + bool isAccepted = false; + if (theEvent->type() == QEvent::KeyRelease) { + QKeyEvent* aKeyEvent = dynamic_cast(theEvent); + if(aKeyEvent) + isAccepted = onKeyReleased(theObject, aKeyEvent); + } + if (!isAccepted) + isAccepted = QObject::eventFilter(theObject, theEvent); + + return isAccepted; +} + +bool XGUI_OperationMgr::startOperation(ModuleBase_Operation* theOperation) +{ + if (hasOperation()) + currentOperation()->postpone(); + myOperations.append(theOperation); + + connect(theOperation, SIGNAL(beforeStarted()), SLOT(onBeforeOperationStarted())); + connect(theOperation, SIGNAL(beforeAborted()), SLOT(onBeforeOperationAborted())); + connect(theOperation, SIGNAL(beforeCommitted()), SLOT(onBeforeOperationCommitted())); + + connect(theOperation, SIGNAL(started()), SLOT(onOperationStarted())); + connect(theOperation, SIGNAL(aborted()), SLOT(onOperationAborted())); + connect(theOperation, SIGNAL(committed()), SLOT(onOperationCommitted())); + + connect(theOperation, SIGNAL(stopped()), SLOT(onOperationStopped())); + connect(theOperation, SIGNAL(resumed()), SLOT(onOperationResumed())); + + bool isStarted = theOperation->start(); + if (isStarted) + onValidateOperation(); + return isStarted; +} + +bool XGUI_OperationMgr::abortAllOperations() +{ + bool aResult = true; + if(!hasOperation()) + return aResult; + + if (operationsCount() == 1) { + ModuleBase_Operation* aCurrentOperation = currentOperation(); + if (canStopOperation(aCurrentOperation)) { + abortOperation(aCurrentOperation); + } + else + aResult = false; + } + else { + aResult = QMessageBox::question(qApp->activeWindow(), + tr("Abort operation"), + tr("All active operations will be aborted."), + QMessageBox::Ok | QMessageBox::Cancel, + QMessageBox::Cancel) == QMessageBox::Ok; + while(aResult && hasOperation()) { + abortOperation(currentOperation()); + } + } + return aResult; +} + +bool XGUI_OperationMgr::commitAllOperations() +{ + bool isCompositeCommitted = false, anOperationProcessed = false; + while (hasOperation()) { + ModuleBase_Operation* anOperation = currentOperation(); + if (XGUI_Tools::workshop(myWorkshop)->errorMgr()->isApplyEnabled()) { + anOperationProcessed = onCommitOperation(); + } else { + abortOperation(anOperation); + anOperationProcessed = true; + } + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (anOperation); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + CompositeFeaturePtr aComposite = + std::dynamic_pointer_cast(aFeature); + isCompositeCommitted = aComposite.get(); + if (isCompositeCommitted) + break; + } + // not processed[committed] operation might be used in composite feature, + // so the while will be stopped by the previous check. + // this code is not necessary, but logically should be done when the processing will not + // be done for not composite feature by some reasons + if (!anOperationProcessed) + break; + } + return true; +} + +void XGUI_OperationMgr::onValidateOperation() +{ + if (!hasOperation()) + return; + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (currentOperation()); + if(aFOperation && aFOperation->feature().get()) + XGUI_Tools::workshop(myWorkshop)->errorMgr()->updateActions(aFOperation->feature()); +} + +void XGUI_OperationMgr::updateApplyOfOperations(ModuleBase_Operation* theOperation) +{ + XGUI_ErrorMgr* anErrorMgr = XGUI_Tools::workshop(myWorkshop)->errorMgr(); + if (theOperation) { + ModuleBase_OperationFeature* aFOperation = dynamic_cast(theOperation); + if (aFOperation) + anErrorMgr->updateAcceptAllAction(aFOperation->feature()); + } + else { + foreach(ModuleBase_Operation* anOperation, myOperations) { + if (anOperation) + updateApplyOfOperations(anOperation); + } + } + // Apply button of the current operation should also be updated + onValidateOperation(); +} + +bool XGUI_OperationMgr::canStopOperation(ModuleBase_Operation* theOperation) +{ + //in case of nested (sketch) operation no confirmation needed + if (isGrantedOperation(theOperation->id())) + return true; + if (theOperation && theOperation->isModified()) { + QString aMessage = tr("%1 operation will be aborted.").arg(theOperation->id()); + int anAnswer = QMessageBox::question(qApp->activeWindow(), + tr("Abort operation"), + aMessage, + QMessageBox::Ok | QMessageBox::Cancel, + QMessageBox::Cancel); + return anAnswer == QMessageBox::Ok; + } + return true; +} + +bool XGUI_OperationMgr::commitOperation() +{ + //if (hasOperation() && currentOperation()->isValid()) { + // onCommitOperation(); + // return true; + //} + //return false; + return onCommitOperation(); +} + +void XGUI_OperationMgr::resumeOperation(ModuleBase_Operation* theOperation) +{ + theOperation->resume(); +} + +bool XGUI_OperationMgr::isGrantedOperation(const QString& theId) +{ + bool isGranted = false; + + QListIterator anIt(myOperations); + anIt.toBack(); + ModuleBase_Operation* aPreviousOperation = 0; + while (anIt.hasPrevious() && !isGranted) { + ModuleBase_Operation* anOp = anIt.previous(); + if (anOp) + isGranted = anOp->isGranted(theId); + } + return isGranted; +} + +void XGUI_OperationMgr::setCurrentFeature(const FeaturePtr& theFeature) +{ + SessionPtr aMgr = ModelAPI_Session::get(); + DocumentPtr aDoc = aMgr->activeDocument(); + bool aIsOp = aMgr->isOperation(); + if (!aIsOp) + aMgr->startOperation(QString("Set current feature: %1").arg(theFeature->getKind().c_str()).toStdString()); + aDoc->setCurrentFeature(theFeature, false); + if (!aIsOp) + aMgr->finishOperation(); +} + +bool XGUI_OperationMgr::canStartOperation(const QString& theId) +{ + bool aCanStart = true; + ModuleBase_Operation* aCurrentOp = currentOperation(); + if (aCurrentOp) { + bool aGranted = aCurrentOp->isGranted(theId); + // the started operation is granted for the current one, + // e.g. current - Sketch, started - Line + if (aGranted) { + aCanStart = true; + } + else { + if (!isGrantedOperation(theId)) { + // the operation is not granted in the current list of operations + // e.g. Edit Parameter when Sketch, Line in Sketch is active. + aCanStart = abortAllOperations(); + } + else if (canStopOperation(aCurrentOp)) { + // the started operation is granted in the parrent operation, + // e.g. current - Line in Sketch, started Circle + stopOperation(aCurrentOp); + } else { + aCanStart = false; + } + } + } + return aCanStart; +} + +void XGUI_OperationMgr::stopOperation(ModuleBase_Operation* theOperation) +{ + if (XGUI_Tools::workshop(myWorkshop)->errorMgr()->isApplyEnabled() && theOperation->isModified()) + theOperation->commit(); + else + abortOperation(theOperation); +} + +void XGUI_OperationMgr::abortOperation(ModuleBase_Operation* theOperation) +{ + ModuleBase_Operation* aCurrentOperation = currentOperation(); + if (theOperation == aCurrentOperation) + theOperation->abort(); + else { + // it is possible to trigger upper operation(e.g. sketch, current is sketch line) + // all operation from the current to triggered should also be aborted + // operations over the parameter one are not aborted(e.g. extrusion cut, sketch abort) + while(hasOperation()) { + ModuleBase_Operation* aCurrentOperation = currentOperation(); + aCurrentOperation->abort(); + if(theOperation == aCurrentOperation) + break; + } + } +} + +bool XGUI_OperationMgr::onCommitOperation() +{ + bool isCommitted = false; + ModuleBase_Operation* anOperation = currentOperation(); + if (anOperation && myWorkshop->module()->canCommitOperation()) + isCommitted = anOperation->commit(); + return isCommitted; +} + +void XGUI_OperationMgr::onAbortOperation() +{ + ModuleBase_Operation* aCurrentOperation = currentOperation(); + if (aCurrentOperation && canStopOperation(aCurrentOperation)) { + abortOperation(aCurrentOperation); + } +} + +void XGUI_OperationMgr::onBeforeOperationStarted() +{ + ModuleBase_Operation* aCurrentOperation = dynamic_cast(sender()); + if (!aCurrentOperation) + return; + + /// Set current feature and remeber old current feature + ModuleBase_OperationFeature* aFOperation = dynamic_cast(aCurrentOperation); + if (aFOperation) { + SessionPtr aMgr = ModelAPI_Session::get(); + DocumentPtr aDoc = aMgr->activeDocument(); + // the parameter of current feature should be false, we should use all feature, not only visible + // in order to correctly save the previous feature of the nested operation, where the + // features can be not visible in the tree. The problem case is Edit sketch entitity(line) + // in the Sketch, created in ExtrusionCut operation. The entity disappears by commit. + // When sketch entity operation started, the sketch should be cashed here as the current. + // Otherwise(the flag is true), the ExtrusionCut is cashed, when commit happens, the sketch + // is disabled, sketch entity is disabled as extrusion cut is created earliest then sketch. + // As a result the sketch disappears from the viewer. However after commit it is displayed back. + aFOperation->setPreviousCurrentFeature(aDoc->currentFeature(false)); + +#ifdef DEBUG_CURRENT_FEATURE + FeaturePtr aFeature = aFOperation->feature(); + QString aKind = aFeature ? aFeature->getKind().c_str() : ""; + qDebug(QString("onBeforeOperationStarted(), edit operation = %1, feature = %2") + .arg(aFOperation->isEditOperation()) + .arg(ModuleBase_Tools::objectInfo(aFeature)).toStdString().c_str()); + + qDebug(QString("\tdocument->currentFeature(false) = %1").arg( + ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str()); +#endif + + if (aFOperation->isEditOperation()) {// it should be performed by the feature edit only + // in create operation, the current feature is changed by addFeature() + aDoc->setCurrentFeature(aFOperation->feature(), false); + // this is the only place where flushes must be called after setCurrentFeature for the current + // moment: after this the opertion is not finished, so, the ObjectBrowser state may be corrupted + // (issue #1457) + static Events_Loop* aLoop = Events_Loop::loop(); + static Events_ID aCreateEvent = aLoop->eventByName(EVENT_OBJECT_CREATED); + aLoop->flush(aCreateEvent); + static Events_ID aDeleteEvent = aLoop->eventByName(EVENT_OBJECT_DELETED); + aLoop->flush(aDeleteEvent); + } + +#ifdef DEBUG_CURRENT_FEATURE + qDebug("\tdocument->setCurrentFeature"); + qDebug(QString("\tdocument->currentFeature(false) = %1").arg( + ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str()); +#endif + } +} + +void XGUI_OperationMgr::onOperationStarted() +{ + ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); + updateApplyOfOperations(aSenderOperation); + XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop); + aWorkshop->operationStarted(aSenderOperation); +} + +void XGUI_OperationMgr::onBeforeOperationAborted() +{ + onBeforeOperationCommitted(); +} + +void XGUI_OperationMgr::onOperationAborted() +{ + ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); + emit operationAborted(aSenderOperation); +} + +void XGUI_OperationMgr::onBeforeOperationCommitted() +{ + ModuleBase_Operation* aCurrentOperation = dynamic_cast(sender()); + if (!aCurrentOperation) + return; + + /// Restore the previous current feature + ModuleBase_OperationFeature* aFOperation = dynamic_cast(aCurrentOperation); + if (aFOperation) { +#ifdef DEBUG_CURRENT_FEATURE + QString aKind = aFOperation->feature()->getKind().c_str(); + qDebug(QString("onBeforeOperationCommitted(), edit operation = %1, feature = %2") + .arg(aFOperation->isEditOperation()) + .arg(ModuleBase_Tools::objectInfo(aFOperation->feature())).toStdString().c_str()); + + qDebug(QString("\tdocument->currentFeature(false) = %1").arg( + ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str()); +#endif + + if (aFOperation->isEditOperation()) { + /// Restore the previous current feature + setCurrentFeature(aFOperation->previousCurrentFeature()); + } + else { // create operation + // the Top created feature should stays the current. In nested operations, like Line in the Sketch or + // Sketch in ExtrusionCut, a previous feature should be restored on commit. It is performed here + // in order to perform it in the current transaction without opening a new one. + if (myOperations.front() != aFOperation) + setCurrentFeature(aFOperation->previousCurrentFeature()); + } +#ifdef DEBUG_CURRENT_FEATURE + qDebug("\tdocument->setCurrentFeature"); + qDebug(QString("\tdocument->currentFeature(false) = %1").arg( + ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str()); +#endif + ModuleBase_IModule* aModule = myWorkshop->module(); + if (aModule) + aModule->beforeOperationStopped(aFOperation); + } +} + +void XGUI_OperationMgr::onOperationCommitted() +{ + // apply state for all features from the stack of operations should be updated + updateApplyOfOperations(); + + ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); + emit operationCommitted(aSenderOperation); +} + +void XGUI_OperationMgr::onOperationResumed() +{ + ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); + emit operationResumed(aSenderOperation); +} + +void XGUI_OperationMgr::onOperationStopped() +{ + ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); + ModuleBase_Operation* aCurrentOperation = currentOperation(); + if (!aSenderOperation || !aCurrentOperation || aSenderOperation != aCurrentOperation) + return; + + myOperations.removeAll(aCurrentOperation); + aCurrentOperation->deleteLater(); + + emit operationStopped(aCurrentOperation); + + // get last operation which can be resumed + ModuleBase_Operation* aResultOp = 0; + QListIterator anIt(myOperations); + anIt.toBack(); + while (anIt.hasPrevious()) { + ModuleBase_Operation* anOp = anIt.previous(); + if (anOp) { + aResultOp = anOp; + break; + } + } + if (aResultOp) { + bool isModified = aCurrentOperation->isModified(); + aResultOp->setIsModified(aResultOp->isModified() || isModified); + resumeOperation(aResultOp); + onValidateOperation(); + } +} + +bool XGUI_OperationMgr::onKeyReleased(QObject *theObject, QKeyEvent* theEvent) +{ + // Let the manager decide what to do with the given key combination. + ModuleBase_Operation* anOperation = currentOperation(); + bool isAccepted = false; + switch (theEvent->key()) { + case Qt::Key_Return: + case Qt::Key_Enter: { + isAccepted = onProcessEnter(theObject); + } + break; + case Qt::Key_N: + case Qt::Key_P: { + bool noModifiers = (theEvent->modifiers() == Qt::NoModifier); + if (noModifiers) { + ModuleBase_IViewer* aViewer = myWorkshop->viewer(); + Handle(AIS_InteractiveContext) aContext = aViewer->AISContext(); + if (!aContext.IsNull()) { + Handle(V3d_View) aView = aViewer->activeView(); + if ((theEvent->key() == Qt::Key_N)) + aContext->HilightNextDetected(aView); + else if ((theEvent->key() == Qt::Key_P)) + aContext->HilightPreviousDetected(aView); + } + } + } + break; + break; + default: + isAccepted = false; + break; + } + //if(anOperation) { + // anOperation->keyReleased(theEvent->key()); + //} + return isAccepted; +} + +bool XGUI_OperationMgr::onProcessEnter(QObject* theObject) +{ + bool isAccepted = false; + ModuleBase_Operation* aOperation = currentOperation(); + // to avoid enter processing when operation has not been started yet + if (!aOperation) + return isAccepted; + ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); + // only property panel enter is processed in order to do not process enter in application dialogs + bool isPPChild = isChildObject(theObject, aPanel); + if (!isPPChild) + return isAccepted; + + ModuleBase_ModelWidget* anActiveWgt = aPanel->activeWidget(); + bool isAborted = false; + if (!anActiveWgt) { + QWidget* aFocusWidget = aPanel->focusWidget(); + QToolButton* aCancelBtn = dynamic_cast(aPanel)->findButton(PROP_PANEL_CANCEL); + if (aFocusWidget && aCancelBtn && aFocusWidget == aCancelBtn) { + abortOperation(aOperation); + isAccepted = true; + isAborted = true; + } + } + if (!isAborted) { + isAccepted = anActiveWgt && anActiveWgt->processEnter(); + if (!isAccepted) { + isAccepted = myWorkshop->module()->processEnter(anActiveWgt ? anActiveWgt->attributeID() : ""); + if (!isAccepted) { + /// functionality is similar to Apply click + ModuleBase_OperationFeature* aFOperation = dynamic_cast(currentOperation()); + if (!aFOperation || myWorkshop->module()->getFeatureError(aFOperation->feature()).isEmpty()) { + // key released is emitted to apply the current value to the model if it was modified in PP + emit keyEnterReleased(); + commitOperation(); + isAccepted = true; + } + else + isAccepted = false; + } + } + } + return isAccepted; +} + +bool editorControl(QObject* theObject) +{ + QLineEdit* aLineEdit = dynamic_cast(theObject); + return aLineEdit; +} + +bool XGUI_OperationMgr::onProcessDelete(QObject* theObject) +{ + bool isAccepted = false; + ModuleBase_Operation* aOperation = currentOperation(); + ModuleBase_ModelWidget* anActiveWgt = 0; + // firstly the widget should process Delete action + ModuleBase_IPropertyPanel* aPanel; + bool isPPChildObject = false; + if (aOperation) { + aPanel = aOperation->propertyPanel(); + if (aPanel) { + isPPChildObject = isChildObject(theObject, aPanel); + // process delete in active widget only if delete sender is child of property panel + // it is necessary for the case when OB is shown, user perform selection and click Delete + if (isPPChildObject) { + anActiveWgt = aPanel->activeWidget(); + if (anActiveWgt) { + isAccepted = anActiveWgt->processDelete(); + } + } + } + } + if (!isAccepted) { + // after widget, object browser and viewer should process delete + /// other widgets such as line edit controls should not lead to + /// processing delete by workshop + XGUI_ObjectsBrowser* aBrowser = XGUI_Tools::workshop(myWorkshop)->objectBrowser(); + QWidget* aViewPort = myWorkshop->viewer()->activeViewPort(); + bool isToDeleteObject = false; + XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop); + XGUI_ContextMenuMgr* aContextMenuMgr = aWorkshop->contextMenuMgr(); + if (theObject == aBrowser->treeView()) { + aContextMenuMgr->updateObjectBrowserMenu(); + isToDeleteObject = aContextMenuMgr->action("DELETE_CMD")->isEnabled(); + } + else if (isChildObject(theObject, aViewPort)) { + aContextMenuMgr->updateViewerMenu(); + isToDeleteObject = aContextMenuMgr->action("DELETE_CMD")->isEnabled(); + } + else if (isPPChildObject) { + // property panel child object is processed to process delete performed on Apply button of PP + isToDeleteObject = true; + } + else if (editorControl(theObject)) { + isToDeleteObject = false; /// Line Edit of Rename operation in ObjectBrowser + isAccepted = true; + } + + if (isToDeleteObject) { + aWorkshop->deleteObjects(); + isAccepted = true; + } + } + + return isAccepted; +} + +bool XGUI_OperationMgr::isChildObject(const QObject* theObject, const QObject* theParent) +{ + bool isPPChild = false; + if (theParent && theObject) { + QObject* aParent = (QObject*)theObject; + while (aParent ) { + isPPChild = aParent == theParent; + if (isPPChild) + break; + aParent = aParent->parent(); + } + } + return isPPChild; +} -- 2.39.2