From: nds Date: Mon, 5 Sep 2016 13:20:55 +0000 (+0300) Subject: Feature selector widget for recover feature. X-Git-Tag: V_2.5.0~60 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=8634847ac05ce637193ec2f5234c3c8996762f94;p=modules%2Fshaper.git Feature selector widget for recover feature. --- diff --git a/src/Config/Config_Keywords.h b/src/Config/Config_Keywords.h index adb9ae00c..3b8de4693 100644 --- a/src/Config/Config_Keywords.h +++ b/src/Config/Config_Keywords.h @@ -1,128 +1,129 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -/* - * Config_Keywords.h - * - * Created on: Apr 2, 2014 - * Author: sbh - */ - -#ifndef CONFIG_KEYWORDS_H_ -#define CONFIG_KEYWORDS_H_ - -/* - * Hardcoded xml entities of plugin-*.xml - */ -const static char* NODE_WORKBENCH = "workbench"; -const static char* NODE_GROUP = "group"; -const static char* NODE_FEATURE = "feature"; -const static char* NODE_SOURCE = "source"; -const static char* NODE_VALIDATOR = "validator"; -const static char* NODE_SELFILTER = "selection_filter"; -const static char* NODE_XMLPARENT = "libxml_parent"; - -// Property panels -const static char* PROPERTY_PANEL_ID = "property_panel_id"; - -// Widgets -const static char* WDG_INFO = "label"; -const static char* WDG_DOUBLEVALUE = "doublevalue"; -const static char* WDG_INTEGERVALUE = "integervalue"; -const static char* WDG_BOOLVALUE = "boolvalue"; -const static char* WDG_STRINGVALUE = "stringvalue"; -const static char* WDG_MULTISELECTOR = "multi_selector"; -const static char* WDG_SHAPE_SELECTOR = "shape_selector"; -const static char* WDG_CONCEALED_OBJECTS_VIEW = "concealed_objects_view"; -const static char* WDG_CHOICE = "choice"; -const static char* WDG_DOUBLEVALUE_EDITOR = "doublevalue_editor"; -const static char* WDG_FILE_SELECTOR= "file_selector"; -const static char* WDG_EXPR_EDITOR = "expr_editor"; -const static char* WDG_PLACE_HOLDER = "placeholder"; -const static char* WDG_ACTION = "action"; - -// Containers -const static char* WDG_GROUP = "groupbox"; -const static char* WDG_OPTIONALBOX = "optionalbox"; -const static char* WDG_TOOLBOX = "toolbox"; -const static char* WDG_TOOLBOX_BOX = "box"; -const static char* WDG_SWITCH = "switch"; -const static char* WDG_SWITCH_CASE = "case"; -// Common properties (xml attributes of nodes) -const static char* _ID = "id"; -// NODE_WORKBENCH properties -const static char* WORKBENCH_DOC = "document"; -// NODE_SOURCE properties -const static char* SOURCE_FILE = "path"; -// NODE_FEATURE properties -const static char* FEATURE_TOOLTIP = "tooltip"; -const static char* FEATURE_ICON = "icon"; -const static char* FEATURE_TEXT = "title"; -const static char* FEATURE_KEYSEQUENCE = "keysequence"; -const static char* FEATURE_NESTED = "nested"; -const static char* FEATURE_WHEN_NESTED = "when_nested"; -const static char* FEATURE_WHEN_NESTED_ACCEPT = "accept"; -const static char* FEATURE_WHEN_NESTED_ABORT = "abort"; -const static char* FEATURE_DOC = WORKBENCH_DOC; -const static char* FEATURE_MODAL = "modal"; -const static char* FEATURE_AUTO_PREVIEW = "auto_preview"; -// NODE_VALIDATOR properties, NODE_SELFILTER properties -const static char* _PARAMETERS = "parameters"; - -// Widget (attribute) properties -const static char* ATTR_TOOLTIP = FEATURE_TOOLTIP; -const static char* ATTR_ICON = FEATURE_ICON; -const static char* ATTR_LABEL = "label"; -const static char* ATTR_STYLE_SHEET = "styleSheet"; -const static char* ATTR_DEFAULT = "default"; -const static char* ATTR_INTERNAL = "internal"; -const static char* ATTR_OBLIGATORY = "obligatory"; -const static char* ATTR_CONCEALMENT = "concealment"; -const static char* ATTR_USE_RESET = "use_reset"; -const static char* ATTR_GREED = "greed"; - -// WDG_INFO properties -const static char* INFO_WDG_TEXT = FEATURE_TEXT; -const static char* INFO_WDG_TOOLTIP = FEATURE_TOOLTIP; -// WDG_DOUBLEVALUE properties: -const static char* DOUBLE_WDG_MIN = "min"; -const static char* DOUBLE_WDG_MAX = "max"; -const static char* DOUBLE_WDG_STEP = "step"; -const static char* DOUBLE_WDG_DEFAULT_COMPUTED = "computed"; -const static char* DOUBLE_WDG_ACCEPT_EXPRESSIONS = "accept_expressions"; -const static char* DOUBLE_WDG_ENABLE_VALUE = "enable_value"; - -const static char* DOUBLE_WDG_ENABLE_VALUE_BY_PREFERENCES = "enable_by_preferences"; - -// WDG_TOOLBOX/WDG_SWITCH properties -const static char* CONTAINER_PAGE_NAME = "title"; -const static char* CONTAINER_PAGE_ICON = "icon"; - -/* - * Hardcoded xml entities of plugins.xml - */ - -const static char* PLUGIN_FILE = "plugins.xml"; -const static char* NODE_PLUGIN = "plugin"; -const static char* NODE_PLUGINS = "plugins"; - -const static char* PLUGINS_MODULE = "module"; -const static char* PLUGIN_CONFIG = "configuration"; -const static char* PLUGIN_LIBRARY = "library"; -const static char* PLUGIN_SCRIPT = "script"; -const static char* PLUGIN_DEPENDENCY = "dependency"; - -/* - * Hardcoded xml entities of dataModel.xml - */ -const static char* DATAMODEL_FILE = "dataModel.xml"; -const static char* NODE_FOLDER = "folder"; -const static char* FOLDER_NAME = "name"; -const static char* GROUP_TYPE = "group_type"; -const static char* ROOT_DOCUMENT = "root_document"; -const static char* SUB_DOCUMENT = "sub_document"; -const static char* NODE_ICON = "icon"; -const static char* SHOW_EMPTY = "show_empty"; -const static char* LINK_ITEM = "from_result"; -const static char* FOLDER_FEATURES = "folder_features"; - -#endif /* CONFIG_KEYWORDS_H_ */ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +/* + * Config_Keywords.h + * + * Created on: Apr 2, 2014 + * Author: sbh + */ + +#ifndef CONFIG_KEYWORDS_H_ +#define CONFIG_KEYWORDS_H_ + +/* + * Hardcoded xml entities of plugin-*.xml + */ +const static char* NODE_WORKBENCH = "workbench"; +const static char* NODE_GROUP = "group"; +const static char* NODE_FEATURE = "feature"; +const static char* NODE_SOURCE = "source"; +const static char* NODE_VALIDATOR = "validator"; +const static char* NODE_SELFILTER = "selection_filter"; +const static char* NODE_XMLPARENT = "libxml_parent"; + +// Property panels +const static char* PROPERTY_PANEL_ID = "property_panel_id"; + +// Widgets +const static char* WDG_INFO = "label"; +const static char* WDG_DOUBLEVALUE = "doublevalue"; +const static char* WDG_INTEGERVALUE = "integervalue"; +const static char* WDG_BOOLVALUE = "boolvalue"; +const static char* WDG_STRINGVALUE = "stringvalue"; +const static char* WDG_MULTISELECTOR = "multi_selector"; +const static char* WDG_SHAPE_SELECTOR = "shape_selector"; +const static char* WDG_FEATURE_SELECTOR = "feature_selector"; +const static char* WDG_CONCEALED_OBJECTS_VIEW = "concealed_objects_view"; +const static char* WDG_CHOICE = "choice"; +const static char* WDG_DOUBLEVALUE_EDITOR = "doublevalue_editor"; +const static char* WDG_FILE_SELECTOR= "file_selector"; +const static char* WDG_EXPR_EDITOR = "expr_editor"; +const static char* WDG_PLACE_HOLDER = "placeholder"; +const static char* WDG_ACTION = "action"; + +// Containers +const static char* WDG_GROUP = "groupbox"; +const static char* WDG_OPTIONALBOX = "optionalbox"; +const static char* WDG_TOOLBOX = "toolbox"; +const static char* WDG_TOOLBOX_BOX = "box"; +const static char* WDG_SWITCH = "switch"; +const static char* WDG_SWITCH_CASE = "case"; +// Common properties (xml attributes of nodes) +const static char* _ID = "id"; +// NODE_WORKBENCH properties +const static char* WORKBENCH_DOC = "document"; +// NODE_SOURCE properties +const static char* SOURCE_FILE = "path"; +// NODE_FEATURE properties +const static char* FEATURE_TOOLTIP = "tooltip"; +const static char* FEATURE_ICON = "icon"; +const static char* FEATURE_TEXT = "title"; +const static char* FEATURE_KEYSEQUENCE = "keysequence"; +const static char* FEATURE_NESTED = "nested"; +const static char* FEATURE_WHEN_NESTED = "when_nested"; +const static char* FEATURE_WHEN_NESTED_ACCEPT = "accept"; +const static char* FEATURE_WHEN_NESTED_ABORT = "abort"; +const static char* FEATURE_DOC = WORKBENCH_DOC; +const static char* FEATURE_MODAL = "modal"; +const static char* FEATURE_AUTO_PREVIEW = "auto_preview"; +// NODE_VALIDATOR properties, NODE_SELFILTER properties +const static char* _PARAMETERS = "parameters"; + +// Widget (attribute) properties +const static char* ATTR_TOOLTIP = FEATURE_TOOLTIP; +const static char* ATTR_ICON = FEATURE_ICON; +const static char* ATTR_LABEL = "label"; +const static char* ATTR_STYLE_SHEET = "styleSheet"; +const static char* ATTR_DEFAULT = "default"; +const static char* ATTR_INTERNAL = "internal"; +const static char* ATTR_OBLIGATORY = "obligatory"; +const static char* ATTR_CONCEALMENT = "concealment"; +const static char* ATTR_USE_RESET = "use_reset"; +const static char* ATTR_GREED = "greed"; + +// WDG_INFO properties +const static char* INFO_WDG_TEXT = FEATURE_TEXT; +const static char* INFO_WDG_TOOLTIP = FEATURE_TOOLTIP; +// WDG_DOUBLEVALUE properties: +const static char* DOUBLE_WDG_MIN = "min"; +const static char* DOUBLE_WDG_MAX = "max"; +const static char* DOUBLE_WDG_STEP = "step"; +const static char* DOUBLE_WDG_DEFAULT_COMPUTED = "computed"; +const static char* DOUBLE_WDG_ACCEPT_EXPRESSIONS = "accept_expressions"; +const static char* DOUBLE_WDG_ENABLE_VALUE = "enable_value"; + +const static char* DOUBLE_WDG_ENABLE_VALUE_BY_PREFERENCES = "enable_by_preferences"; + +// WDG_TOOLBOX/WDG_SWITCH properties +const static char* CONTAINER_PAGE_NAME = "title"; +const static char* CONTAINER_PAGE_ICON = "icon"; + +/* + * Hardcoded xml entities of plugins.xml + */ + +const static char* PLUGIN_FILE = "plugins.xml"; +const static char* NODE_PLUGIN = "plugin"; +const static char* NODE_PLUGINS = "plugins"; + +const static char* PLUGINS_MODULE = "module"; +const static char* PLUGIN_CONFIG = "configuration"; +const static char* PLUGIN_LIBRARY = "library"; +const static char* PLUGIN_SCRIPT = "script"; +const static char* PLUGIN_DEPENDENCY = "dependency"; + +/* + * Hardcoded xml entities of dataModel.xml + */ +const static char* DATAMODEL_FILE = "dataModel.xml"; +const static char* NODE_FOLDER = "folder"; +const static char* FOLDER_NAME = "name"; +const static char* GROUP_TYPE = "group_type"; +const static char* ROOT_DOCUMENT = "root_document"; +const static char* SUB_DOCUMENT = "sub_document"; +const static char* NODE_ICON = "icon"; +const static char* SHOW_EMPTY = "show_empty"; +const static char* LINK_ITEM = "from_result"; +const static char* FOLDER_FEATURES = "folder_features"; + +#endif /* CONFIG_KEYWORDS_H_ */ diff --git a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index 0daaa1ec1..8d05e895f 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -1,109 +1,111 @@ -// 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); - - // 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 c77f516b6..18b4be1ac 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp @@ -1,784 +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 - -#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 = abs(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; -} +// 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 = abs(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); + + int 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 ce3fe042e..64262768a 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.h @@ -1,205 +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); -}; - -#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_ValidatorUnionArguments +/// \ingroup Validators +/// \brief Validator for the "Union" 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/FeaturesPlugin/recover_widget.xml b/src/FeaturesPlugin/recover_widget.xml index 51582a8b7..b2c6e8091 100644 --- a/src/FeaturesPlugin/recover_widget.xml +++ b/src/FeaturesPlugin/recover_widget.xml @@ -1,13 +1,13 @@ - - - - - - - + + + + + + + + + diff --git a/src/ModelAPI/ModelAPI_Tools.cpp b/src/ModelAPI/ModelAPI_Tools.cpp index 74a33d366..4e094e611 100755 --- a/src/ModelAPI/ModelAPI_Tools.cpp +++ b/src/ModelAPI/ModelAPI_Tools.cpp @@ -1,653 +1,681 @@ -// 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 - -#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; -} - -static std::map > myColorMap; - -void appendValues(std::vector& theRGB, const int theRed, const int theGreen, const int theBlue) -{ - theRGB.push_back(theRed); - theRGB.push_back(theGreen); - theRGB.push_back(theBlue); -} - -bool containsValues(std::map >& theColorMap, std::vector& theValues) -{ - std::map >::const_iterator anIt = theColorMap.begin(), aLast = theColorMap.end(); - bool isFound = false; - for (; anIt != aLast && !isFound; anIt++) { - std::vector aValues = anIt->second; - isFound = aValues[0] == theValues[0] && - aValues[1] == theValues[1] && - aValues[2] == theValues[2]; - } - return isFound; -} - -std::vector HSVtoRGB(int theH, int theS, int theV) -{ - std::vector aRGB; - if (theH < 0 || theH > 360 || - theS < 0 || theS > 100 || - theV < 0 || theV > 100) - return aRGB; - - int aHi = (int)theH/60; - - double aV = theV; - double aVmin = (100 - theS)*theV/100; - - double anA = (theV - aVmin)* (theH % 60) / 60; - - double aVinc = aVmin + anA; - double aVdec = theV - anA; - - double aPercentToValue = 255./100; - int aV_int = (int)(aV*aPercentToValue); - int aVinc_int = (int)(aVinc*aPercentToValue); - int aVmin_int = (int)(aVmin*aPercentToValue); - int aVdec_int = (int)(aVdec*aPercentToValue); - - switch(aHi) { - case 0: appendValues(aRGB, aV_int, aVinc_int, aVmin_int); break; - case 1: appendValues(aRGB, aVdec_int, aV_int, aVmin_int); break; - case 2: appendValues(aRGB, aVmin_int, aV_int, aVinc_int); break; - case 3: appendValues(aRGB, aVmin_int, aVdec_int, aV_int); break; - case 4: appendValues(aRGB, aVinc_int, aVmin_int, aV_int); break; - case 5: appendValues(aRGB, aV_int, aVmin_int, aVdec_int); break; - default: break; - } - return aRGB; -} - - -void fillColorMap() -{ - if (!myColorMap.empty()) - return; - - int i = 0; - for (int s = 100; s > 0; s = s - 50) - { - for (int v = 100; v >= 40; v = v - 20) - { - for (int h = 0; h < 359 ; h = h + 60) - { - std::vector aColor = HSVtoRGB(h, s, v); - if (containsValues(myColorMap, aColor)) - continue; - myColorMap[i] = aColor; - i++; - } - } - } -} - -void findRandomColor(std::vector& theValues) -{ - theValues.clear(); - if (myColorMap.empty()) { - fillColorMap(); - } - - size_t aSize = myColorMap.size(); - int anIndex = rand() % aSize; - if (myColorMap.find(anIndex) != myColorMap.end()) { - theValues = myColorMap.at(anIndex); - } -} - -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); - } - } -} - -} // 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; +} + +static std::map > myColorMap; + +void appendValues(std::vector& theRGB, const int theRed, const int theGreen, const int theBlue) +{ + theRGB.push_back(theRed); + theRGB.push_back(theGreen); + theRGB.push_back(theBlue); +} + +bool containsValues(std::map >& theColorMap, std::vector& theValues) +{ + std::map >::const_iterator anIt = theColorMap.begin(), aLast = theColorMap.end(); + bool isFound = false; + for (; anIt != aLast && !isFound; anIt++) { + std::vector aValues = anIt->second; + isFound = aValues[0] == theValues[0] && + aValues[1] == theValues[1] && + aValues[2] == theValues[2]; + } + return isFound; +} + +std::vector HSVtoRGB(int theH, int theS, int theV) +{ + std::vector aRGB; + if (theH < 0 || theH > 360 || + theS < 0 || theS > 100 || + theV < 0 || theV > 100) + return aRGB; + + int aHi = (int)theH/60; + + double aV = theV; + double aVmin = (100 - theS)*theV/100; + + double anA = (theV - aVmin)* (theH % 60) / 60; + + double aVinc = aVmin + anA; + double aVdec = theV - anA; + + double aPercentToValue = 255./100; + int aV_int = (int)(aV*aPercentToValue); + int aVinc_int = (int)(aVinc*aPercentToValue); + int aVmin_int = (int)(aVmin*aPercentToValue); + int aVdec_int = (int)(aVdec*aPercentToValue); + + switch(aHi) { + case 0: appendValues(aRGB, aV_int, aVinc_int, aVmin_int); break; + case 1: appendValues(aRGB, aVdec_int, aV_int, aVmin_int); break; + case 2: appendValues(aRGB, aVmin_int, aV_int, aVinc_int); break; + case 3: appendValues(aRGB, aVmin_int, aVdec_int, aV_int); break; + case 4: appendValues(aRGB, aVinc_int, aVmin_int, aV_int); break; + case 5: appendValues(aRGB, aV_int, aVmin_int, aVdec_int); break; + default: break; + } + return aRGB; +} + + +void fillColorMap() +{ + if (!myColorMap.empty()) + return; + + int i = 0; + for (int s = 100; s > 0; s = s - 50) + { + for (int v = 100; v >= 40; v = v - 20) + { + for (int h = 0; h < 359 ; h = h + 60) + { + std::vector aColor = HSVtoRGB(h, s, v); + if (containsValues(myColorMap, aColor)) + continue; + myColorMap[i] = aColor; + i++; + } + } + } +} + +void findRandomColor(std::vector& theValues) +{ + theValues.clear(); + if (myColorMap.empty()) { + fillColorMap(); + } + + size_t aSize = myColorMap.size(); + int anIndex = rand() % aSize; + if (myColorMap.find(anIndex) != myColorMap.end()) { + theValues = myColorMap.at(anIndex); + } +} + +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 14f028823..3133d3794 100755 --- a/src/ModelAPI/ModelAPI_Tools.h +++ b/src/ModelAPI/ModelAPI_Tools.h @@ -1,160 +1,167 @@ -// 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()); - -/*! - * Returns the values of the next random color. The values are in range [0, 255] - * \param theValues a container of component of RGB value: red, green, blue - */ -MODELAPI_EXPORT void findRandomColor(std::vector& theValues); - -/*! - * 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); -} - -#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()); + +/*! + * Returns the values of the next random color. The values are in range [0, 255] + * \param theValues a container of component of RGB value: red, green, blue + */ +MODELAPI_EXPORT void findRandomColor(std::vector& theValues); + +/*! + * 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/ModuleBase/CMakeLists.txt b/src/ModuleBase/CMakeLists.txt index 4e444009e..7ff157483 100644 --- a/src/ModuleBase/CMakeLists.txt +++ b/src/ModuleBase/CMakeLists.txt @@ -49,6 +49,7 @@ SET(PROJECT_HEADERS ModuleBase_WidgetEditor.h ModuleBase_WidgetExprEditor.h ModuleBase_WidgetFactory.h + ModuleBase_WidgetFeatureSelector.h ModuleBase_WidgetFileSelector.h ModuleBase_WidgetIntValue.h ModuleBase_WidgetLabel.h @@ -109,6 +110,7 @@ SET(PROJECT_SOURCES ModuleBase_WidgetEditor.cpp ModuleBase_WidgetExprEditor.cpp ModuleBase_WidgetFactory.cpp + ModuleBase_WidgetFeatureSelector.cpp ModuleBase_WidgetFileSelector.cpp ModuleBase_WidgetIntValue.cpp ModuleBase_WidgetLabel.cpp diff --git a/src/ModuleBase/ModuleBase_FilterValidated.cpp b/src/ModuleBase/ModuleBase_FilterValidated.cpp index 097eb60cb..b9238538c 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_ModelWidget.cpp b/src/ModuleBase/ModuleBase_ModelWidget.cpp index f961d0f95..ed373b038 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 +// 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) { + +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 = true;//Config_PropManager::boolean(SKETCH_TAB_NAME, "disable_input_fields", "true"); #else bool aCanDisable = 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); -} + 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_WidgetConcealedObjects.cpp b/src/ModuleBase/ModuleBase_WidgetConcealedObjects.cpp index fd5c23cef..aff8f49eb 100644 --- a/src/ModuleBase/ModuleBase_WidgetConcealedObjects.cpp +++ b/src/ModuleBase/ModuleBase_WidgetConcealedObjects.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -73,28 +74,16 @@ bool ModuleBase_WidgetConcealedObjects::restoreValueCustom() myConcealedResults.clear(); myBaseFeature = aBaseFeature; if (myBaseFeature.get()) { - std::list > > > aRefs; - myBaseFeature->data()->referencesToObjects(aRefs); - std::list > >::const_iterator - anIt = aRefs.begin(), aLast = aRefs.end(); - std::set alreadyThere; // to avoid duplications + std::list > aResults; + ModelAPI_Tools::getConcealedResults(myBaseFeature, aResults); + std::list >::const_iterator anIt = aResults.begin(), + aLast = aResults.end(); for (; anIt != aLast; anIt++) { - if (!ModelAPI_Session::get()->validators()-> - isConcealed(myBaseFeature->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; - int aRowId = myView->rowCount(); - addViewRow(aResult); - myConcealedResults[aRowId] = aResult; - } - } + ResultPtr aResult = *anIt; + + int aRowId = myView->rowCount(); + addViewRow(aResult); + myConcealedResults[aRowId] = aResult; } } } diff --git a/src/ModuleBase/ModuleBase_WidgetFactory.cpp b/src/ModuleBase/ModuleBase_WidgetFactory.cpp index 8af4cbb32..c0045ec1d 100644 --- a/src/ModuleBase/ModuleBase_WidgetFactory.cpp +++ b/src/ModuleBase/ModuleBase_WidgetFactory.cpp @@ -1,338 +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 - -#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_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 new file mode 100644 index 000000000..9396183d3 --- /dev/null +++ b/src/ModuleBase/ModuleBase_WidgetFeatureSelector.cpp @@ -0,0 +1,235 @@ +// 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) +{ + ModuleBase_ISelection* aSelection = myWorkshop->selection(); + ObjectPtr anObject = ModelAPI_Feature::feature(thePrs->object()); + GeomShapePtr aShape; + + FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); + // the last flag is to be depending on hasObject is called before. To be corrected later + return ModuleBase_Tools::setObject(attribute(), aFeature, aShape, + myWorkshop, myIsInValidate, true); +} + +//******************************************************************** +void ModuleBase_WidgetFeatureSelector::deactivate() +{ + ModuleBase_ModelWidget::deactivate(); + disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged())); + activateFilters(false); + myWorkshop->deactivateSubShapesSelection(); +} + +//******************************************************************** +void ModuleBase_WidgetFeatureSelector::activateCustom() +{ + connect(myWorkshop, SIGNAL(selectionChanged()), this, + SLOT(onSelectionChanged()), Qt::UniqueConnection); + + activateFilters(true); + + QIntList aShapeTypes; + aShapeTypes.push_back(ModuleBase_ResultPrs::Sel_Result); + myWorkshop->activateSubShapesSelection(aShapeTypes); + + // Restore selection in the viewer by the attribute selection list + // it should be postponed to have current widget as active to validate restored selection + //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)); + } +} + +//******************************************************************** +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); + + bool isDone = setSelection(aSelected, true/*false*/); + updateOnSelectionChanged(isDone); +} + +//******************************************************************** +void ModuleBase_WidgetFeatureSelector::updateOnSelectionChanged(const bool theDone) +{ + // "false" flag should be used here, it connects to the #26658 OCC bug, when the user click in + // the same place repeatedly without mouse moved. In the case validation by filters is not + // perfromed, so an invalid object is selected. E.g. distance constraint, selection of a point. + // the 3rd click in the same point allow using this point. + emit valuesChanged(); + // the updateObject method should be called to flush the updated sigal. The workshop listens it, + // calls validators for the feature and, as a result, updates the Apply button state. + updateObject(myFeature); + + // we need to forget about previous validation result as the current selection can influence on it + clearValidatedCash(); + + if (theDone) + updateFocus(); +} + + diff --git a/src/ModuleBase/ModuleBase_WidgetFeatureSelector.h b/src/ModuleBase/ModuleBase_WidgetFeatureSelector.h new file mode 100644 index 000000000..7e1538b19 --- /dev/null +++ b/src/ModuleBase/ModuleBase_WidgetFeatureSelector.h @@ -0,0 +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 diff --git a/src/ModuleBase/ModuleBase_WidgetSelector.h b/src/ModuleBase/ModuleBase_WidgetSelector.h index 3a309beb0..11f3e474c 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 daecef19f..8a3705523 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 cb826704b..31b7b59a0 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 - 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_SketcherMgr.cpp b/src/PartSet/PartSet_SketcherMgr.cpp index abe3a586f..bb9c18df2 100755 --- a/src/PartSet/PartSet_SketcherMgr.cpp +++ b/src/PartSet/PartSet_SketcherMgr.cpp @@ -1,1802 +1,1802 @@ -// 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(); - - if (isSketcher) { - myIsDragging = true; - get2dPoint(theWnd, theEvent, myCurrentPoint); - 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()) { - 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; - get2dPoint(theWnd, theEvent, myCurrentPoint); - 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(); - 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); - double aX, aY; - PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, aX, aY); - double dX = aX - myCurrentPoint.myCurX; - double dY = aY - 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.setValue(aX, aY); - } -} - -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(); - } - 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()) { - ResultPtr aResult = std::dynamic_pointer_cast(theObject); - 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; - } - } - } - } - 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(); + + if (isSketcher) { + myIsDragging = true; + get2dPoint(theWnd, theEvent, myCurrentPoint); + 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()) { + 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; + get2dPoint(theWnd, theEvent, myCurrentPoint); + 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(); + 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); + double aX, aY; + PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, aX, aY); + double dX = aX - myCurrentPoint.myCurX; + double dY = aY - 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.setValue(aX, aY); + } +} + +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(); + } + 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()) { + ResultPtr aResult = std::dynamic_pointer_cast(theObject); + 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; + } + } + } + } + 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(); +} +