From: mpv Date: Mon, 8 Dec 2014 16:43:02 +0000 (+0300) Subject: Merge remote-tracking branch 'origin/Dev_0.6' X-Git-Tag: V_0.6.0^0 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=a7f44a41bdf29e7bd978ff3b8c8bd514d1223be7;hp=d29ed3f3f7c0e119d2917b2d4120aa7b473220f4;p=modules%2Fshaper.git Merge remote-tracking branch 'origin/Dev_0.6' --- diff --git a/build_Salome740_deb.bat b/build_Salome740_deb.bat deleted file mode 100644 index 77a58f1ed..000000000 --- a/build_Salome740_deb.bat +++ /dev/null @@ -1,19 +0,0 @@ -@ECHO OFF - -REM Find absolute path to ROOT_DIR -@SET PARENT_DIR=%~dp0.. -@SET ROOT_DIR= -pushd %PARENT_DIR% -@SET ROOT_DIR=%CD% -popd - -@SET SRC_DIR=%ROOT_DIR%\sources -@SET OCC_LIB_PREFIX=d - -call %SRC_DIR%\env_Salome.bat d -mkdir %ROOT_DIR%\build -cd %ROOT_DIR%\build - -cmake %SRC_DIR% -G "Visual Studio 10" -DPYTHON_EXECUTABLE=%PYTHONHOME%\python_d.exe -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX:PATH=%ROOT_DIR%\install - -start "" %MSVC_EXE% NewGEOM.sln diff --git a/build_Salome740_rel.bat b/build_Salome740_rel.bat deleted file mode 100644 index 26fbe1521..000000000 --- a/build_Salome740_rel.bat +++ /dev/null @@ -1,18 +0,0 @@ -@ECHO OFF - -REM Find absolute path to ROOT_DIR -@SET PARENT_DIR=%~dp0.. -@SET ROOT_DIR= -pushd %PARENT_DIR% -@SET ROOT_DIR=%CD% -popd - -@SET SRC_DIR=%ROOT_DIR%\sources - -call %SRC_DIR%\env_Salome.bat -mkdir %ROOT_DIR%\build -cd %ROOT_DIR%\build - -cmake %SRC_DIR% -G "Visual Studio 10" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX:PATH=%ROOT_DIR%\install - -start "" %MSVC_EXE% NewGEOM.sln diff --git a/build_Salome_deb.bat b/build_Salome_deb.bat new file mode 100644 index 000000000..77a58f1ed --- /dev/null +++ b/build_Salome_deb.bat @@ -0,0 +1,19 @@ +@ECHO OFF + +REM Find absolute path to ROOT_DIR +@SET PARENT_DIR=%~dp0.. +@SET ROOT_DIR= +pushd %PARENT_DIR% +@SET ROOT_DIR=%CD% +popd + +@SET SRC_DIR=%ROOT_DIR%\sources +@SET OCC_LIB_PREFIX=d + +call %SRC_DIR%\env_Salome.bat d +mkdir %ROOT_DIR%\build +cd %ROOT_DIR%\build + +cmake %SRC_DIR% -G "Visual Studio 10" -DPYTHON_EXECUTABLE=%PYTHONHOME%\python_d.exe -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX:PATH=%ROOT_DIR%\install + +start "" %MSVC_EXE% NewGEOM.sln diff --git a/build_Salome_rel.bat b/build_Salome_rel.bat new file mode 100644 index 000000000..4f3a06137 --- /dev/null +++ b/build_Salome_rel.bat @@ -0,0 +1,18 @@ +@ECHO OFF + +REM Find absolute path to ROOT_DIR +@SET PARENT_DIR=%~dp0.. +@SET ROOT_DIR= +pushd %PARENT_DIR% +@SET ROOT_DIR=%CD% +popd + +@SET SRC_DIR=%ROOT_DIR%\sources + +call %SRC_DIR%\env_Salome.bat +mkdir %ROOT_DIR%\build +cd %ROOT_DIR%\build + +cmake %SRC_DIR% -G "Visual Studio 10" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=%ROOT_DIR%\install + +start "" %MSVC_EXE% NewGEOM.sln diff --git a/src/Config/Config_Common.cpp b/src/Config/Config_Common.cpp index b3a93acd1..a8c6df0a5 100644 --- a/src/Config/Config_Common.cpp +++ b/src/Config/Config_Common.cpp @@ -14,7 +14,8 @@ #include // for stringstream #include -#include // for std::transform +#include // for std::transform + bool isElementNode(xmlNodePtr theNode) { return theNode->type == XML_ELEMENT_NODE; @@ -95,6 +96,8 @@ bool getValidatorInfo(xmlNodePtr theNode, std::string& outValidatorId, std::string library(const std::string& theLibName) { + if(theLibName.empty()) + return std::string(); std::string aLibName = theLibName; #ifndef WIN32 static std::string aLibExt( ".so" ); diff --git a/src/Config/Config_FeatureReader.cpp b/src/Config/Config_FeatureReader.cpp index 9ebc93f78..bf780f330 100644 --- a/src/Config/Config_FeatureReader.cpp +++ b/src/Config/Config_FeatureReader.cpp @@ -102,7 +102,12 @@ void Config_FeatureReader::fillFeature(xmlNodePtr theNode, outFeatureMessage->setKeysequence(getProperty(theNode, FEATURE_KEYSEQUENCE)); outFeatureMessage->setGroupId(restoreAttribute(NODE_GROUP, _ID)); outFeatureMessage->setWorkbenchId(restoreAttribute(NODE_WORKBENCH, _ID)); - outFeatureMessage->setDocumentKind(restoreAttribute(NODE_WORKBENCH, WORKBENCH_DOC)); + // Get document kind of a feature, if empty set workbench's kind (might be empty too) + std::string aDocKind = getProperty(theNode, WORKBENCH_DOC); + if(aDocKind.empty()) { + aDocKind = restoreAttribute(NODE_WORKBENCH, WORKBENCH_DOC); + } + outFeatureMessage->setDocumentKind(aDocKind); } void Config_FeatureReader::storeAttribute(xmlNodePtr theNode, diff --git a/src/Config/Config_Keywords.h b/src/Config/Config_Keywords.h index d7ed62fab..159f97c17 100644 --- a/src/Config/Config_Keywords.h +++ b/src/Config/Config_Keywords.h @@ -26,10 +26,9 @@ const static char* WDG_MULTISELECTOR = "multi_selector"; const static char* WDG_SHAPE_SELECTOR = "shape_selector"; const static char* WDG_CHOICE = "choice"; //Specific widgets -const static char* WDG_POINT_SELECTOR = "point_selector"; -const static char* WDG_POINT2D_DISTANCE = "point2ddistance"; -const static char* WDG_FEATURE_SELECTOR = "feature_selector"; -const static char* WDG_FEATURE_OR_ATTRIBUTE_SELECTOR = "feature_or_attribute_selector"; +//const static char* WDG_POINT2D_DISTANCE = "point2ddistance"; +//const static char* WDG_FEATURE_SELECTOR = "feature_selector"; +//const static char* WDG_FEATURE_OR_ATTRIBUTE_SELECTOR = "feature_or_attribute_selector"; const static char* WDG_DOUBLEVALUE_EDITOR = "doublevalue_editor"; const static char* WDG_FILE_SELECTOR= "file_selector"; @@ -54,7 +53,7 @@ const static char* ATTRIBUTE_INTERNAL = "internal"; const static char* ATTRIBUTE_OBLIGATORY = "obligatory"; const static char* ATTRIBUTE_CONCEALMENT = "concealment"; // TODO: Rename -const static char* PREVIOUS_FEATURE_PARAM = "previous_feature_param"; +//const static char* PREVIOUS_FEATURE_PARAM = "previous_feature_param"; const static char* ANY_WDG_TOOLTIP = FEATURE_TOOLTIP; const static char* ANY_WDG_ICON = FEATURE_ICON; const static char* ANY_WDG_LABEL = "label"; diff --git a/src/Config/Config_Prop.h b/src/Config/Config_Prop.h index 4430bade8..496e8fd95 100644 --- a/src/Config/Config_Prop.h +++ b/src/Config/Config_Prop.h @@ -37,7 +37,8 @@ class Config_Prop Shortcut, ShortcutTree, BiColor, - Background + Background, + Directory }; /** diff --git a/src/Config/Config_XMLReader.cpp b/src/Config/Config_XMLReader.cpp index 44c806ce9..818180e11 100644 --- a/src/Config/Config_XMLReader.cpp +++ b/src/Config/Config_XMLReader.cpp @@ -9,11 +9,15 @@ #include #include #include +#include #include +#include #include #include +#include + #ifdef WIN32 #pragma warning(disable : 4996) // for getenv #endif @@ -25,19 +29,31 @@ Config_XMLReader::Config_XMLReader(const std::string& theXmlFileName) : myXmlDoc(NULL) { - std::string prefix = ""; + std::string prefix = ""; + Config_Prop* aProp = Config_PropManager::findProp("Plugins", "default_path"); + if (aProp) + prefix = aProp->value(); /* * Get path to *.xml files (typically ./bin/../plugins/) * the problem: application may be launched using python executable, * to use environment variable (at least for the current moment) */ - char* anEnv = getenv("NEW_GEOM_CONFIG_FILE"); - if (anEnv) { - prefix = std::string(anEnv) + "/"; + if (prefix.empty()) { + char* anEnv = getenv("NEW_GEOM_CONFIG_FILE"); + if (anEnv) { + prefix = std::string(anEnv); + } } - +#ifdef WIN32 + prefix += "\\"; +#else + prefix += "/"; +#endif myDocumentPath = prefix + theXmlFileName; + std::ifstream aTestFile(myDocumentPath); + if (!aTestFile) Events_Error::send("Unable to open " + myDocumentPath); + aTestFile.close(); } Config_XMLReader::~Config_XMLReader() diff --git a/src/Events/Events_Loop.cpp b/src/Events/Events_Loop.cpp index 9447c376b..f9b9d0046 100644 --- a/src/Events/Events_Loop.cpp +++ b/src/Events/Events_Loop.cpp @@ -115,14 +115,18 @@ void Events_Loop::flush(const Events_ID& theID) { if (!myFlushActive) return; - std::map>::iterator aMyGroup = - myGroups.find(theID.eventText()); - if (aMyGroup != myGroups.end()) { // really sends - myFlushed.insert(theID.myID); + std::map >::iterator aMyGroup; + for(aMyGroup = myGroups.find(theID.eventText()); + aMyGroup != myGroups.end(); aMyGroup = myGroups.find(theID.eventText())) + { // really sends + bool aWasFlushed = myFlushed.find(theID.myID) != myFlushed.end(); + if (!aWasFlushed) + myFlushed.insert(theID.myID); std::shared_ptr aGroup = aMyGroup->second; myGroups.erase(aMyGroup); send(aGroup, false); - myFlushed.erase(myFlushed.find(theID.myID)); + if (!aWasFlushed) + myFlushed.erase(myFlushed.find(theID.myID)); } } @@ -147,3 +151,16 @@ void Events_Loop::autoFlush(const Events_ID& theID, const bool theAuto) else myFlushed.erase(myFlushed.find(theID.myID)); } + +bool Events_Loop::isFlushed(const Events_ID& theID) +{ + return myFlushed.find(theID.myID) != myFlushed.end(); +} + +void Events_Loop::setFlushed(const Events_ID& theID, const bool theValue) +{ + if (theValue) + myFlushed.insert(theID.myID); + else + myFlushed.erase(myFlushed.find(theID.myID)); +} diff --git a/src/Events/Events_Loop.h b/src/Events/Events_Loop.h index c8b7798c0..317c62d3b 100644 --- a/src/Events/Events_Loop.h +++ b/src/Events/Events_Loop.h @@ -72,6 +72,11 @@ class Events_Loop //! Enables flush without grouping for the given message EVENTS_EXPORT void autoFlush(const Events_ID& theID, const bool theAuto = true); + + //! Returns true if the evement is flushed right now + EVENTS_EXPORT bool isFlushed(const Events_ID& theID); + //! Sets the flag that the event is flished right now + EVENTS_EXPORT void setFlushed(const Events_ID& theID, const bool theValue); }; #endif diff --git a/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp b/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp index 6493870df..5a31c28f9 100644 --- a/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp +++ b/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -100,12 +99,9 @@ bool ExchangePlugin_ImportFeature::importFile(const std::string& theFileName) anUnknownLabel); // Check if shape is valid if ( aShape.IsNull() ) { - std::string aShapeError = "An error occurred while importing " + theFileName + ": "; - aShapeError = aShapeError + std::string(anError.ToCString()); - Events_Error::send(aShapeError, this); - #ifdef _DEBUG - std::cerr << aShapeError << std::endl; - #endif + const static std::string aShapeError = + "An error occurred while importing " + theFileName + ": " + anError.ToCString(); + setError(aShapeError); return false; } // @@ -154,20 +150,15 @@ LibHandle ExchangePlugin_ImportFeature::loadImportPlugin(const std::string& theF #else anImportError = anImportError + std::string(dlerror()); #endif - Events_Error::send(anImportError, this); -#ifdef _DEBUG - std::cerr << anImportError << std::endl; -#endif + setError(anImportError); return false; } // Test loaded plugin for existence of valid "Import" function: importFunctionPointer fp = (importFunctionPointer) GetProc(anImportLib, "Import"); if (!fp) { - std::string aFunctionError = "No valid \"Import\" function was found in the " + aLibName; - Events_Error::send(aFunctionError, this); -#ifdef _DEBUG - std::cerr << aFunctionError << std::endl; -#endif + const static std::string aFunctionError = + "No valid \"Import\" function was found in the " + aLibName; + setError(aFunctionError); UnLoadLib(anImportLib) return NULL; } diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index 4b4ce8e11..9de0da779 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -5,8 +5,9 @@ SET(PROJECT_HEADERS FeaturesPlugin.h FeaturesPlugin_Plugin.h FeaturesPlugin_Extrusion.h - FeaturesPlugin_Boolean.h - FeaturesPlugin_Group.h + FeaturesPlugin_Boolean.h + FeaturesPlugin_Group.h + FeaturesPlugin_Placement.h ) SET(PROJECT_SOURCES @@ -14,6 +15,7 @@ SET(PROJECT_SOURCES FeaturesPlugin_Extrusion.cpp FeaturesPlugin_Boolean.cpp FeaturesPlugin_Group.cpp + FeaturesPlugin_Placement.cpp ) SET(XML_RESOURCES @@ -21,6 +23,7 @@ SET(XML_RESOURCES extrusion_widget.xml boolean_widget.xml group_widget.xml + placement_widget.xml ) INCLUDE_DIRECTORIES( diff --git a/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp b/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp index d8b8198ed..025f63bab 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp @@ -10,12 +10,7 @@ #include #include #include -#include using namespace std; -#ifdef _DEBUG -#include -#include -#endif #define FACE 4 #define _MODIFY_TAG 1 @@ -65,29 +60,26 @@ void FeaturesPlugin_Boolean::execute() GeomAlgoAPI_Boolean* aFeature = new GeomAlgoAPI_Boolean(anObject, aTool, aType); if(aFeature && !aFeature->isDone()) { - std::string aFeatureError = "Boolean feature: algorithm failed"; - Events_Error::send(aFeatureError, this); + static const std::string aFeatureError = "Boolean feature: algorithm failed"; + setError(aFeatureError); return; } // Check if shape is valid if (aFeature->shape()->isNull()) { - std::string aShapeError = "Boolean feature: resulting shape is Null"; - Events_Error::send(aShapeError, this); -#ifdef _DEBUG - std::cerr << aShapeError << std::endl; -#endif + static const std::string aShapeError = "Boolean feature: resulting shape is Null"; + setError(aShapeError); return; } if(!aFeature->isValid()) { - std::string aFeatureError = "Boolean feature: resulting shape is not valid"; - Events_Error::send(aFeatureError, this); + static const std::string aFeatureError = "Boolean feature: resulting shape is not valid"; + setError(aFeatureError); return; } // if result of Boolean operation is same as was before it means that Boolean operation has no sence // and naming provides no result, so, generate an error in this case if (anObject->isEqual(aFeature->shape())) { - std::string aFeatureError = "Boolean feature: operation was not performed"; - Events_Error::send(aFeatureError, this); + static const std::string aFeatureError = "Boolean feature: operation was not performed"; + setError(aFeatureError); return; } //LoadNamingDS diff --git a/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp b/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp index 55bc605c1..cebc0bb44 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include using namespace std; @@ -19,10 +18,6 @@ using namespace std; #define _FIRST_TAG 2 #define _LAST_TAG 3 #define EDGE 6 -#ifdef _DEBUG -#include -#include -#endif FeaturesPlugin_Extrusion::FeaturesPlugin_Extrusion() { @@ -56,8 +51,8 @@ void FeaturesPlugin_Extrusion::execute() aContext = std::dynamic_pointer_cast(aContextRes)->shape(); } if (!aContext) { - std::string aContextError = "The selection context is bad"; - Events_Error::send(aContextError, this); + static const std::string aContextError = "The selection context is bad"; + setError(aContextError); return; } @@ -68,23 +63,20 @@ void FeaturesPlugin_Extrusion::execute() std::shared_ptr aResultBody = document()->createBody(data()); GeomAlgoAPI_Extrusion aFeature(aFace, aSize); if(!aFeature.isDone()) { - std::string aFeatureError = "Extrusion algorithm failed"; - Events_Error::send(aFeatureError, this); + static const std::string aFeatureError = "Extrusion algorithm failed"; + setError(aFeatureError); return; } // Check if shape is valid if (aFeature.shape()->isNull()) { - std::string aShapeError = "Resulting shape is Null"; - Events_Error::send(aShapeError, this); -#ifdef _DEBUG - std::cerr << aShapeError << std::endl; -#endif + static const std::string aShapeError = "Resulting shape is Null"; + setError(aShapeError); return; } if(!aFeature.isValid()) { std::string aFeatureError = "Warning: resulting shape is not valid"; - Events_Error::send(aFeatureError, this); + setError(aFeatureError); return; } //LoadNamingDS diff --git a/src/FeaturesPlugin/FeaturesPlugin_Group.h b/src/FeaturesPlugin/FeaturesPlugin_Group.h index 7138c1241..e306842a5 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Group.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Group.h @@ -45,7 +45,7 @@ class FeaturesPlugin_Group : public ModelAPI_Feature FEATURESPLUGIN_EXPORT virtual void initAttributes(); /// Result of groups is created on the fly and don't stored to the document - FEATURESPLUGIN_EXPORT virtual bool isPersistentResult() {return false;} + FEATURESPLUGIN_EXPORT virtual bool isPersistentResult() {return true;} /// Use plugin manager for features creation FeaturesPlugin_Group(); diff --git a/src/FeaturesPlugin/FeaturesPlugin_Placement.cpp b/src/FeaturesPlugin/FeaturesPlugin_Placement.cpp new file mode 100644 index 000000000..96d52d77b --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_Placement.cpp @@ -0,0 +1,131 @@ +// File: FeaturesPlugin_Placement.cpp +// Created: 2 Dec 2014 +// Author: Artem ZHIDKOV + +#include "FeaturesPlugin_Placement.h" + +#include +#include +#include + +#include +#include +#include + +#define _MODIFIEDF_TAG 1 +#define _MODIFIEDE_TAG 2 +#define _MODIFIEDV_TAG 3 +#define _FACE 4 +FeaturesPlugin_Placement::FeaturesPlugin_Placement() +{ +} + +void FeaturesPlugin_Placement::initAttributes() +{ + data()->addAttribute(FeaturesPlugin_Placement::BASE_FACE_ID(), ModelAPI_AttributeSelection::type()); + data()->addAttribute(FeaturesPlugin_Placement::ATTRACT_FACE_ID(), ModelAPI_AttributeSelection::type()); +} + +void FeaturesPlugin_Placement::execute() +{ + // Verify the base face + std::shared_ptr aFaceRef = std::dynamic_pointer_cast< + ModelAPI_AttributeSelection>(data()->attribute(FeaturesPlugin_Placement::BASE_FACE_ID())); + if (!aFaceRef) + return; + + std::shared_ptr aBaseFace = + std::dynamic_pointer_cast(aFaceRef->value()); + if (!aBaseFace) + return; + + std::shared_ptr aBaseFaceContext; + ResultPtr aContextRes = aFaceRef->context(); + if (aContextRes) { + if (aContextRes->groupName() == ModelAPI_ResultBody::group()) + aBaseFaceContext = std::dynamic_pointer_cast(aContextRes)->shape(); + else if (aContextRes->groupName() == ModelAPI_ResultConstruction::group()) + aBaseFaceContext = std::dynamic_pointer_cast(aContextRes)->shape(); + } + if (!aBaseFaceContext) { + static const std::string aContextError = "The selection context is bad"; + setError(aContextError); + return; + } + + // Verify the attractive face + aFaceRef = std::dynamic_pointer_cast( + data()->attribute(FeaturesPlugin_Placement::ATTRACT_FACE_ID())); + + std::shared_ptr aSlaveObjectFace = + std::dynamic_pointer_cast(aFaceRef->value()); + if (!aSlaveObjectFace) + return; + + std::shared_ptr aSlaveObject; + aContextRes = aFaceRef->context(); + if (aContextRes) { + if (aContextRes->groupName() == ModelAPI_ResultBody::group()) + aSlaveObject = std::dynamic_pointer_cast(aContextRes)->shape(); + else if (aContextRes->groupName() == ModelAPI_ResultConstruction::group()) + aSlaveObject = std::dynamic_pointer_cast(aContextRes)->shape(); + } + if (!aSlaveObject) { + static const std::string aContextError = "The selection context is bad"; + setError(aContextError); + return; + } + + // Verify faces planarity + std::shared_ptr aBaseFace1(new GeomAPI_Face(aBaseFace)); + std::shared_ptr aSlaveFace1(new GeomAPI_Face(aSlaveObjectFace)); + if (!aBaseFace1->isPlanar() || !aSlaveFace1->isPlanar()) { + static const std::string aPlanarityError = "One of selected face is not planar"; + setError(aPlanarityError); + return; + } + + std::shared_ptr aBasePlane = aBaseFace1->getPlane(); + std::shared_ptr aSlavePlane = aSlaveFace1->getPlane(); + + std::shared_ptr aResultBody = document()->createBody(data()); + GeomAlgoAPI_Placement aFeature(aSlaveObject, aSlavePlane, aBasePlane); + if(!aFeature.isDone()) { + static const std::string aFeatureError = "Placement algorithm failed"; + setError(aFeatureError); + return; + } + + // Check if shape is valid + if (aFeature.shape()->isNull()) { + static const std::string aShapeError = "Resulting shape is Null"; + setError(aShapeError); + return; + } + if(!aFeature.isValid()) { + std::string aFeatureError = "Warning: resulting shape is not valid"; + setError(aFeatureError); + return; + } + //LoadNamingDS + LoadNamingDS(aFeature, aResultBody, aSlaveObject); + + setResult(aResultBody); +} + +//============================================================================ +void FeaturesPlugin_Placement::LoadNamingDS( + GeomAlgoAPI_Placement& theFeature, + std::shared_ptr theResultBody, + std::shared_ptr theSlaveObject) +{ + //load result + theResultBody->storeModified(theSlaveObject, theFeature.shape()); // the initial Slave, the resulting Slave + + GeomAPI_DataMapOfShapeShape* aSubShapes = new GeomAPI_DataMapOfShapeShape(); + theFeature.mapOfShapes(*aSubShapes); + + // put modifed faces in DF + theResultBody->loadAndOrientModifiedShapes(theFeature.makeShape(), theSlaveObject, _FACE, _MODIFIEDF_TAG, *aSubShapes); + +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_Placement.h b/src/FeaturesPlugin/FeaturesPlugin_Placement.h new file mode 100644 index 000000000..cc9e30f3d --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_Placement.h @@ -0,0 +1,59 @@ +// File: FeaturesPlugin_Placement.h +// Created: 2 Dec 2014 +// Author: Artem ZHIDKOV + +#ifndef FeaturesPlugin_Placement_H_ +#define FeaturesPlugin_Placement_H_ + +#include "FeaturesPlugin.h" +#include +#include + +class ModelAPI_ResultBody; +class GeomAPI_Shape; + +class FeaturesPlugin_Placement : public ModelAPI_Feature +{ + public: + /// Placement kind + inline static const std::string& ID() + { + static const std::string MY_PLACEMENT_ID("Placement"); + return MY_PLACEMENT_ID; + } + /// attribute name of referenced face + inline static const std::string& BASE_FACE_ID() + { + static const std::string MY_BASE_FACE_ID("placement_base_face"); + return MY_BASE_FACE_ID; + } + /// attribute name of attractable face + inline static const std::string& ATTRACT_FACE_ID() + { + static const std::string MY_ATTRACT_FACE_ID("placement_attractable_face"); + return MY_ATTRACT_FACE_ID; + } + + /// Returns the kind of a feature + FEATURESPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = FeaturesPlugin_Placement::ID(); + return MY_KIND; + } + + /// Creates a new part document if needed + FEATURESPLUGIN_EXPORT virtual void execute(); + + /// Request for initialization of data model of the feature: adding all attributes + FEATURESPLUGIN_EXPORT virtual void initAttributes(); + + /// Use plugin manager for features creation + FeaturesPlugin_Placement(); +private: + /// Load Naming data structure of the feature to the document + void LoadNamingDS(GeomAlgoAPI_Placement& theFeature, + std::shared_ptr theResultBody, + std::shared_ptr theSlaveObject); +}; + +#endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index 681479032..cd1ceb219 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -29,6 +30,8 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(string theFeatureID) return FeaturePtr(new FeaturesPlugin_Boolean); } else if (theFeatureID == FeaturesPlugin_Group::ID()) { return FeaturePtr(new FeaturesPlugin_Group); + } else if (theFeatureID == FeaturesPlugin_Placement::ID()) { + return FeaturePtr(new FeaturesPlugin_Placement); } // feature of such kind is not found return FeaturePtr(); diff --git a/src/FeaturesPlugin/boolean_widget.xml b/src/FeaturesPlugin/boolean_widget.xml index af4822c2c..e64a63b4c 100644 --- a/src/FeaturesPlugin/boolean_widget.xml +++ b/src/FeaturesPlugin/boolean_widget.xml @@ -11,8 +11,9 @@ icon=":icons/cut_tool.png" tooltip="Select a tool" shape_types="solid" - concealment="true" - /> + concealment="true" > + + + + + + + diff --git a/src/FeaturesPlugin/plugin-Features.xml b/src/FeaturesPlugin/plugin-Features.xml index 749941fca..5177058f3 100644 --- a/src/FeaturesPlugin/plugin-Features.xml +++ b/src/FeaturesPlugin/plugin-Features.xml @@ -7,6 +7,9 @@ + + + ()->Clear(); } +/// Size +int GeomAPI_DataMapOfShapeShape::size() +{ + return implPtr()->Extent(); +} + /// Adds the Key to the Map with the Item. Returns True if the Key was not already in the map bool GeomAPI_DataMapOfShapeShape::bind (std::shared_ptr theKey, std::shared_ptr theItem) { diff --git a/src/GeomAPI/GeomAPI_DataMapOfShapeShape.h b/src/GeomAPI/GeomAPI_DataMapOfShapeShape.h index 94a35b780..e67645e72 100644 --- a/src/GeomAPI/GeomAPI_DataMapOfShapeShape.h +++ b/src/GeomAPI/GeomAPI_DataMapOfShapeShape.h @@ -25,6 +25,9 @@ class GEOMAPI_EXPORT GeomAPI_DataMapOfShapeShape : public GeomAPI_Interface /// Clear void clear(); + /// Size of the map + int size(); + /// Adds the Key to the Map with the Item. Returns True if the Key was not already in the map bool bind (std::shared_ptr theKey, std::shared_ptr theItem); diff --git a/src/GeomAPI/GeomAPI_Edge.cpp b/src/GeomAPI/GeomAPI_Edge.cpp index 5e455f9f3..cdd471f40 100644 --- a/src/GeomAPI/GeomAPI_Edge.cpp +++ b/src/GeomAPI/GeomAPI_Edge.cpp @@ -129,4 +129,4 @@ bool GeomAPI_Edge::isEqual(std::shared_ptr theEdge) return false; return true; -} \ No newline at end of file +} diff --git a/src/GeomAPI/GeomAPI_Face.cpp b/src/GeomAPI/GeomAPI_Face.cpp new file mode 100644 index 000000000..ba111a67d --- /dev/null +++ b/src/GeomAPI/GeomAPI_Face.cpp @@ -0,0 +1,99 @@ +// File: GeomAPI_Face.cpp +// Created: 2 Dec 2014 +// Author: Artem ZHIDKOV + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +GeomAPI_Face::GeomAPI_Face() + : GeomAPI_Shape() +{ +} + +GeomAPI_Face::GeomAPI_Face(const std::shared_ptr& theShape) +{ + if (!theShape->isNull() && theShape->isFace()) { + setImpl(new TopoDS_Shape(theShape->impl())); + } +} + +bool GeomAPI_Face::isEqual(std::shared_ptr theFace) const +{ + if (!theFace->isFace()) + return false; + + const TopoDS_Shape& aMyShape = const_cast(this)->impl(); + const TopoDS_Shape& aInShape = theFace->impl(); + + Handle(Geom_Surface) aMySurf = BRep_Tool::Surface(TopoDS::Face(aMyShape)); + Handle(Geom_Surface) aInSurf = BRep_Tool::Surface(TopoDS::Face(aInShape)); + + // Check that surfaces a the same type + if (aMySurf->DynamicType() != aInSurf->DynamicType()) + return false; + + // Get parameters of surfaces + double aMyUMin, aMyUMax, aMyVMin, aMyVMax; + aMySurf->Bounds(aMyUMin, aMyUMax, aMyVMin, aMyVMax); + double aInUMin, aInUMax, aInVMin, aInVMax; + aInSurf->Bounds(aInUMin, aInUMax, aInVMin, aInVMax); + + // Check that parameters are the same + if (fabs(aMyUMin - aInUMin) > Precision::PConfusion() || + fabs(aMyUMax - aInUMax) > Precision::PConfusion() || + fabs(aMyVMin - aInVMin) > Precision::PConfusion() || + fabs(aMyVMax - aInVMax) > Precision::PConfusion()) + return false; + + return true; +} + +bool GeomAPI_Face::isPlanar() const +{ + const TopoDS_Shape& aShape = const_cast(this)->impl(); + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aShape)); + if (aSurf->IsKind(STANDARD_TYPE(Geom_Plane))) + return true; + return false; +} + +std::shared_ptr GeomAPI_Face::getPlane() const +{ + const TopoDS_Shape& aShape = const_cast(this)->impl(); + BRepAdaptor_Surface aSurfAdapt(TopoDS::Face(aShape)); + + if (aSurfAdapt.GetType() != GeomAbs_Plane) + return std::shared_ptr(); + + // Obtain central point + double aUMin, aUMax, aVMin, aVMax; + aUMin = aSurfAdapt.FirstUParameter(); + aUMax = aSurfAdapt.LastUParameter(); + aVMin = aSurfAdapt.FirstVParameter(); + aVMax = aSurfAdapt.LastVParameter(); + gp_Pnt aCentralPnt; + gp_Vec aDU, aDV; + aSurfAdapt.D1((aUMin+aUMax)*0.5, (aVMin+aVMax)*0.5, aCentralPnt, aDU, aDV); + std::shared_ptr aCenter( + new GeomAPI_Pnt(aCentralPnt.X(), aCentralPnt.Y(), aCentralPnt.Z())); + + // Obtain plane direction + gp_XYZ aNormalVec = aDU.XYZ().Crossed(aDV.XYZ()); + if (aNormalVec.SquareModulus() < Precision::Confusion() * Precision::Confusion()) + return std::shared_ptr(); + std::shared_ptr aNormal( + new GeomAPI_Dir(aNormalVec.X(), aNormalVec.Y(), aNormalVec.Z())); + + std::shared_ptr aResult(new GeomAPI_Pln(aCenter, aNormal)); + return aResult; +} diff --git a/src/GeomAPI/GeomAPI_Face.h b/src/GeomAPI/GeomAPI_Face.h new file mode 100644 index 000000000..c070bf20a --- /dev/null +++ b/src/GeomAPI/GeomAPI_Face.h @@ -0,0 +1,36 @@ +// File: GeomAPI_Face.h +// Created: 2 Dec 2014 +// Author: Artem ZHIDKOV + +#ifndef GeomAPI_Face_H_ +#define GeomAPI_Face_H_ + +#include + +class GeomAPI_Pln; + +/**\class GeomAPI_Face +* \ingroup DataModel + * \brief Interface to the face object + */ +class GEOMAPI_EXPORT GeomAPI_Face : public GeomAPI_Shape +{ +public: + /// Creation of empty (null) shape + GeomAPI_Face(); + + /// Creation of face by the face-shape + GeomAPI_Face(const std::shared_ptr& theShape); + + /// Returns true if the current face is geometrically equal to the given face + virtual bool isEqual(const std::shared_ptr theFace) const; + + /// Returns true if the face is a planar face + bool isPlanar() const; + + /// Returns the base plane of the face (if it is planar) with location in the center of the face + std::shared_ptr getPlane() const; +}; + +#endif + diff --git a/src/GeomAPI/GeomAPI_Shape.cpp b/src/GeomAPI/GeomAPI_Shape.cpp index 5b9694ccc..f656eb2be 100644 --- a/src/GeomAPI/GeomAPI_Shape.cpp +++ b/src/GeomAPI/GeomAPI_Shape.cpp @@ -39,3 +39,9 @@ bool GeomAPI_Shape::isEdge() const const TopoDS_Shape& aShape = const_cast(this)->impl(); return aShape.ShapeType() == TopAbs_EDGE; } + +bool GeomAPI_Shape::isFace() const +{ + const TopoDS_Shape& aShape = const_cast(this)->impl(); + return aShape.ShapeType() == TopAbs_FACE; +} diff --git a/src/GeomAPI/GeomAPI_Shape.h b/src/GeomAPI/GeomAPI_Shape.h index c55d9ab31..e72c4bc90 100644 --- a/src/GeomAPI/GeomAPI_Shape.h +++ b/src/GeomAPI/GeomAPI_Shape.h @@ -30,6 +30,9 @@ class GEOMAPI_EXPORT GeomAPI_Shape : public GeomAPI_Interface /// Returns whether the shape is an edge virtual bool isEdge() const; + /// Returns whether the shape is a face + virtual bool isFace() const; + }; //! Pointer on list of shapes diff --git a/src/GeomAlgoAPI/CMakeLists.txt b/src/GeomAlgoAPI/CMakeLists.txt index 5656a0ad8..8f5a4007c 100644 --- a/src/GeomAlgoAPI/CMakeLists.txt +++ b/src/GeomAlgoAPI/CMakeLists.txt @@ -14,6 +14,7 @@ SET(PROJECT_HEADERS GeomAlgoAPI_Boolean.h GeomAlgoAPI_MakeShape.h GeomAlgoAPI_DFLoader.h + GeomAlgoAPI_Placement.h ) SET(PROJECT_SOURCES @@ -26,6 +27,7 @@ SET(PROJECT_SOURCES GeomAlgoAPI_Boolean.cpp GeomAlgoAPI_MakeShape.cpp GeomAlgoAPI_DFLoader.cpp + GeomAlgoAPI_Placement.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Placement.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Placement.cpp new file mode 100644 index 000000000..7fb667490 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Placement.cpp @@ -0,0 +1,122 @@ +// File: GeomAlgoAPI_Placement.cpp +// Created: 2 Dec 2014 +// Author: Artem ZHIDKOV + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#define DEB_PLACEMENT 1 +GeomAlgoAPI_Placement::GeomAlgoAPI_Placement( + std::shared_ptr theAttractiveFace, + std::shared_ptr theSourcePlane, + std::shared_ptr theDestPlane) + : myDone(false), + myShape(new GeomAPI_Shape()) +{ + build(theAttractiveFace, theSourcePlane, theDestPlane); +} + +void GeomAlgoAPI_Placement::build( + const std::shared_ptr& theAttractiveShape, + const std::shared_ptr& theSourcePlane, + const std::shared_ptr& theDestPlane) +{ + std::shared_ptr aSourceDir = theSourcePlane->direction(); + std::shared_ptr aSourceLoc = theSourcePlane->location(); + std::shared_ptr aDestDir = theDestPlane->direction(); + std::shared_ptr aDestLoc = theDestPlane->location(); + + // Calculate transformation + gp_Trsf aTrsf; + gp_Vec aSrcDir(aSourceDir->x(), aSourceDir->y(), aSourceDir->z()); + gp_Vec aDstDir(aDestDir->x(), aDestDir->y(), aDestDir->z()); + gp_Quaternion aRot(aSrcDir, aDstDir); + aTrsf.SetRotation(aRot); + gp_Vec aSrcCenter(aSourceLoc->x(), aSourceLoc->y(), aSourceLoc->z()); + aSrcCenter.Transform(aTrsf); + gp_Vec aTrans(aDestLoc->x() - aSrcCenter.X(), + aDestLoc->y() - aSrcCenter.Y(), + aDestLoc->z() - aSrcCenter.Z()); + aTrsf.SetTransformation(aRot, aTrans); + + // Transform the shape with copying it + const TopoDS_Shape& aShape = theAttractiveShape->impl(); + BRepBuilderAPI_Transform* aBuilder = new BRepBuilderAPI_Transform(aShape, aTrsf, true); + if(aBuilder) { + setImpl(aBuilder); + myDone = aBuilder->IsDone() == Standard_True; + if (myDone) { + TopoDS_Shape aResult = aBuilder->Shape(); + // fill data map to keep correct orientation of sub-shapes + for (TopExp_Explorer Exp(aResult,TopAbs_FACE); Exp.More(); Exp.Next()) { + std::shared_ptr aCurrentShape(new GeomAPI_Shape()); + aCurrentShape->setImpl(new TopoDS_Shape(Exp.Current())); + myMap.bind(aCurrentShape, aCurrentShape); + } +#ifdef DEB_PLACEMENT + int aNum = myMap.size(); + cout << "MAP of Oriented shapes =" << aNum <setImpl(new TopoDS_Shape(aResult)); + myMkShape = new GeomAlgoAPI_MakeShape (aBuilder); + } + } +} + +//============================================================================ +const bool GeomAlgoAPI_Placement::isValid() const +{ + BRepCheck_Analyzer aChecker(myShape->impl()); + return (aChecker.IsValid() == Standard_True); +} + +//============================================================================ +const bool GeomAlgoAPI_Placement::hasVolume() const +{ + bool hasVolume(false); + if(isValid()) { + const TopoDS_Shape& aRShape = myShape->impl(); + GProp_GProps aGProp; + BRepGProp::VolumeProperties(aRShape, aGProp); + if(aGProp.Mass() > Precision::Confusion()) + hasVolume = true; + } + return hasVolume; +} + +//============================================================================ +const std::shared_ptr& GeomAlgoAPI_Placement::shape () const +{ + return myShape; +} + +//============================================================================ +void GeomAlgoAPI_Placement::mapOfShapes (GeomAPI_DataMapOfShapeShape& theMap) const +{ + theMap = myMap; +} + +//============================================================================ +GeomAlgoAPI_MakeShape * GeomAlgoAPI_Placement::makeShape() const +{ + return myMkShape; +} + +//============================================================================ +GeomAlgoAPI_Placement::~GeomAlgoAPI_Placement() +{ + if (myImpl) + myMap.clear(); +} \ No newline at end of file diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Placement.h b/src/GeomAlgoAPI/GeomAlgoAPI_Placement.h new file mode 100644 index 000000000..09c9e3448 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Placement.h @@ -0,0 +1,68 @@ +// File: GeomAlgoAPI_Placement.h +// Created: 2 Dec 2014 +// Author: Artem ZHIDKOV + +#ifndef GeomAlgoAPI_Placement_H_ +#define GeomAlgoAPI_Placement_H_ + +#include +#include +#include +#include +#include +#include +#include + +/**\class GeomAlgoAPI_Placement + * \ingroup DataAlgo + * \brief Creates the copied object which face is placed on the given plane + */ +class GeomAlgoAPI_Placement : public GeomAPI_Interface +{ +public: + /** \brief Creates an object which is obtained from current object by transformation calculated + * as a movement of the source plane to be coincident with the destination plane + * \param[in] theAttractiveShape shape to be moved + * \param[in] theSourcePlane plane on the shape to be made coincident with destination plane + * \param[in] theDestPlane destination plane + */ + GEOMALGOAPI_EXPORT GeomAlgoAPI_Placement(std::shared_ptr theAttractiveShape, + std::shared_ptr theSourcePlane, + std::shared_ptr theDestPlane); + + /// Returns True if algorithm succeed + GEOMALGOAPI_EXPORT const bool isDone() const + { return myDone; } + + /// Returns True if resulting shape is valid + GEOMALGOAPI_EXPORT const bool isValid() const; + + /// Returns True if resulting shape has volume + GEOMALGOAPI_EXPORT const bool hasVolume() const; + + /// Returns result of the Placement algorithm which may be a Solid or a Face + GEOMALGOAPI_EXPORT const std::shared_ptr& shape () const; + + /// Returns map of sub-shapes of the result. To be used for History keeping + GEOMALGOAPI_EXPORT void mapOfShapes (GeomAPI_DataMapOfShapeShape& theMap) const; + + /// Return interface for for History processing + GEOMALGOAPI_EXPORT GeomAlgoAPI_MakeShape* makeShape () const; + + /// Destructor + GEOMALGOAPI_EXPORT virtual ~GeomAlgoAPI_Placement(); + +private: + /// builds resulting shape + void build(const std::shared_ptr& theAttractiveShape, + const std::shared_ptr& theSourcePlane, + const std::shared_ptr& theDestPlane); + + /// fields + bool myDone; + std::shared_ptr myShape; + GeomAPI_DataMapOfShapeShape myMap; + GeomAlgoAPI_MakeShape * myMkShape; +}; + +#endif diff --git a/src/Model/Model_AttributeReference.cpp b/src/Model/Model_AttributeReference.cpp index e209eb0e1..e65cb91c2 100644 --- a/src/Model/Model_AttributeReference.cpp +++ b/src/Model/Model_AttributeReference.cpp @@ -7,6 +7,11 @@ #include "Model_Events.h" #include "Model_Data.h" #include +#include + +#include +#include +#include using namespace std; @@ -15,12 +20,25 @@ void Model_AttributeReference::setValue(ObjectPtr theObject) if(!theObject) return; if (!myIsInitialized || value() != theObject) { - std::shared_ptr aData = std::dynamic_pointer_cast( - theObject->data()); + std::shared_ptr aData = std::dynamic_pointer_cast( + theObject->data()); + TDF_Label anObjLab = aData->label().Father(); // object label - std::shared_ptr aDoc = - std::dynamic_pointer_cast(owner()->document()); - myRef->Set(aData->label().Father()); // references to the feature label + if (owner()->document() == theObject->document()) { // same document, use reference attribute + + std::shared_ptr aDoc = + std::dynamic_pointer_cast(owner()->document()); + myRef->Set(anObjLab); // references to the object label + // remove external link attributes (if any) + anObjLab.ForgetAttribute(TDataStd_Comment::GetID()); + anObjLab.ForgetAttribute(TDataStd_AsciiString::GetID()); + } else { // different document: store the document name (comment) and entry (string): external + // if these attributes exist, the link is external: keep reference to access the label + TDataStd_Comment::Set(myRef->Label(), theObject->document()->id().c_str()); + TCollection_AsciiString anEntry; + TDF_Tool::Entry(anObjLab, anEntry); + TDataStd_AsciiString::Set(myRef->Label(), anEntry); + } owner()->data()->sendAttributeUpdated(this); } @@ -29,11 +47,28 @@ void Model_AttributeReference::setValue(ObjectPtr theObject) ObjectPtr Model_AttributeReference::value() { if (myIsInitialized) { - std::shared_ptr aDoc = std::dynamic_pointer_cast( - owner()->document()); - if (aDoc) { - TDF_Label aRefLab = myRef->Get(); - return aDoc->object(aRefLab); + Handle(TDataStd_Comment) aDocID; + if (myRef->Label().FindAttribute(TDataStd_Comment::GetID(), aDocID)) { // external ref + DocumentPtr aRefDoc = + ModelAPI_Session::get()->document(TCollection_AsciiString(aDocID->Get()).ToCString()); + if (aRefDoc) { + Handle(TDataStd_AsciiString) anEntry; + if (myRef->Label().FindAttribute(TDataStd_AsciiString::GetID(), anEntry)) { + std::shared_ptr aDR = std::dynamic_pointer_cast(aRefDoc); + TDF_Label aRefLab; + TDF_Tool::Label(aDR->featuresLabel().Data(), anEntry->Get().ToCString(), aRefLab); + if (!aRefLab.IsNull()) { + return aDR->object(aRefLab); + } + } + } + } else { // internal ref + std::shared_ptr aDoc = std::dynamic_pointer_cast( + owner()->document()); + if (aDoc) { + TDF_Label aRefLab = myRef->Get(); + return aDoc->object(aRefLab); + } } } // not initialized diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index 0ae4bf6a8..4f95dc83f 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -127,7 +127,7 @@ bool Model_AttributeSelection::update() bool aNoIndexes = !aLab.FindAttribute(TDataStd_IntPackedMap::GetID(), aSubIds) || aSubIds->Extent() == 0; // for now working only with composite features - FeaturePtr aContextFeature = owner()->document()->feature(aContext); + FeaturePtr aContextFeature = aContext->document()->feature(aContext); CompositeFeaturePtr aComposite = std::dynamic_pointer_cast(aContextFeature); if (!aComposite || aComposite->numberOfSubs() == 0) { @@ -296,7 +296,7 @@ void Model_AttributeSelection::selectBody( void Model_AttributeSelection::selectConstruction( const ResultPtr& theContext, const std::shared_ptr& theSubShape) { - FeaturePtr aContextFeature = owner()->document()->feature(theContext); + FeaturePtr aContextFeature = theContext->document()->feature(theContext); CompositeFeaturePtr aComposite = std::dynamic_pointer_cast(aContextFeature); if (!aComposite || aComposite->numberOfSubs() == 0) { diff --git a/src/Model/Model_Data.cpp b/src/Model/Model_Data.cpp index 77b834ada..b10378943 100644 --- a/src/Model/Model_Data.cpp +++ b/src/Model/Model_Data.cpp @@ -26,10 +26,13 @@ #include #include -#include #include +// myLab contains: +// TDataStd_Name - name of the object +// TDataStd_Integer - state of the object execution + Model_Data::Model_Data() { } @@ -85,7 +88,9 @@ void Model_Data::addAttribute(const std::string& theID, const std::string theAtt anAttr = new Model_AttributeRefAttr(anAttrLab); } else if (theAttrType == ModelAPI_AttributeRefList::type()) { anAttr = new Model_AttributeRefList(anAttrLab); - } else if (theAttrType == GeomData_Point::type()) { + } + // create also GeomData attributes here because only here the OCAF strucure is known + else if (theAttrType == GeomData_Point::type()) { anAttr = new GeomData_Point(anAttrLab); } else if (theAttrType == GeomData_Dir::type()) { anAttr = new GeomData_Dir(anAttrLab); @@ -95,172 +100,34 @@ void Model_Data::addAttribute(const std::string& theID, const std::string theAtt if (anAttr) { myAttrs[theID] = std::shared_ptr(anAttr); anAttr->setObject(myObject); + anAttr->setID(theID); } else { Events_Error::send("Can not create unknown type of attribute " + theAttrType); } } -std::shared_ptr Model_Data::document(const std::string& theID) -{ - std::map >::iterator aFound = - myAttrs.find(theID); - if (aFound == myAttrs.end()) { - // TODO: generate error on unknown attribute request and/or add mechanism for customization - return std::shared_ptr(); - } - std::shared_ptr aRes = std::dynamic_pointer_cast< - ModelAPI_AttributeDocRef>(aFound->second); - if (!aRes) { - // TODO: generate error on invalid attribute type request - } - return aRes; -} - -std::shared_ptr Model_Data::real(const std::string& theID) -{ - std::map >::iterator aFound = - myAttrs.find(theID); - if (aFound == myAttrs.end()) { - // TODO: generate error on unknown attribute request and/or add mechanism for customization - return std::shared_ptr(); - } - std::shared_ptr aRes = std::dynamic_pointer_cast< - ModelAPI_AttributeDouble>(aFound->second); - if (!aRes) { - // TODO: generate error on invalid attribute type request - } - return aRes; -} - -std::shared_ptr Model_Data::integer(const std::string& theID) -{ - std::map >::iterator aFound = - myAttrs.find(theID); - if (aFound == myAttrs.end()) { - // TODO: generate error on unknown attribute request and/or add mechanism for customization - return std::shared_ptr(); - } - std::shared_ptr aRes = std::dynamic_pointer_cast< - ModelAPI_AttributeInteger>(aFound->second); - if (!aRes) { - // TODO: generate error on invalid attribute type request - } - return aRes; -} - -std::shared_ptr Model_Data::boolean(const std::string& theID) -{ - std::map >::iterator aFound = - myAttrs.find(theID); - if (aFound == myAttrs.end()) { - // TODO: generate error on unknown attribute request and/or add mechanism for customization - return std::shared_ptr(); - } - std::shared_ptr aRes = std::dynamic_pointer_cast< - ModelAPI_AttributeBoolean>(aFound->second); - if (!aRes) { - // TODO: generate error on invalid attribute type request - } - return aRes; -} - -std::shared_ptr Model_Data::string(const std::string& theID) -{ - std::map >::iterator aFound = - myAttrs.find(theID); - if (aFound == myAttrs.end()) { - // TODO: generate error on unknown attribute request and/or add mechanism for customization - return std::shared_ptr(); - } - std::shared_ptr aRes = - std::dynamic_pointer_cast(aFound->second); - if (!aRes) { - // TODO: generate error on invalid attribute type request - } - return aRes; - -} - -std::shared_ptr Model_Data::reference(const std::string& theID) -{ - std::map >::iterator aFound = - myAttrs.find(theID); - if (aFound == myAttrs.end()) { - // TODO: generate error on unknown attribute request and/or add mechanism for customization - return std::shared_ptr(); - } - std::shared_ptr aRes = std::dynamic_pointer_cast< - ModelAPI_AttributeReference>(aFound->second); - if (!aRes) { - // TODO: generate error on invalid attribute type request - } - return aRes; -} - -std::shared_ptr Model_Data::selection(const std::string& theID) -{ - std::map >::iterator aFound = - myAttrs.find(theID); - if (aFound == myAttrs.end()) { - // TODO: generate error on unknown attribute request and/or add mechanism for customization - return std::shared_ptr(); - } - std::shared_ptr aRes = - std::dynamic_pointer_cast(aFound->second); - if (!aRes) { - // TODO: generate error on invalid attribute type request - } - return aRes; -} - -std::shared_ptr - Model_Data::selectionList(const std::string& theID) -{ - std::map >::iterator aFound = - myAttrs.find(theID); - if (aFound == myAttrs.end()) { - // TODO: generate error on unknown attribute request and/or add mechanism for customization - return std::shared_ptr(); +// macro for gthe generic returning of the attribute by the ID +#define GET_ATTRIBUTE_BY_ID(ATTR_TYPE, METHOD_NAME) \ + std::shared_ptr Model_Data::METHOD_NAME(const std::string& theID) { \ + std::shared_ptr aRes; \ + std::map::iterator aFound = \ + myAttrs.find(theID); \ + if (aFound != myAttrs.end()) { \ + aRes = std::dynamic_pointer_cast(aFound->second); \ + } \ + return aRes; \ } - std::shared_ptr aRes = - std::dynamic_pointer_cast(aFound->second); - if (!aRes) { - // TODO: generate error on invalid attribute type request - } - return aRes; -} - -std::shared_ptr Model_Data::refattr(const std::string& theID) -{ - std::map >::iterator aFound = - myAttrs.find(theID); - if (aFound == myAttrs.end()) { - // TODO: generate error on unknown attribute request and/or add mechanism for customization - return std::shared_ptr(); - } - std::shared_ptr aRes = std::dynamic_pointer_cast< - ModelAPI_AttributeRefAttr>(aFound->second); - if (!aRes) { - // TODO: generate error on invalid attribute type request - } - return aRes; -} - -std::shared_ptr Model_Data::reflist(const std::string& theID) -{ - std::map >::iterator aFound = - myAttrs.find(theID); - if (aFound == myAttrs.end()) { - // TODO: generate error on unknown attribute request and/or add mechanism for customization - return std::shared_ptr(); - } - std::shared_ptr aRes = std::dynamic_pointer_cast< - ModelAPI_AttributeRefList>(aFound->second); - if (!aRes) { - // TODO: generate error on invalid attribute type request - } - return aRes; -} +// implement nice getting methods for all ModelAPI attributes +GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeDocRef, document); +GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeDouble, real); +GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeInteger, integer); +GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeBoolean, boolean); +GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeString, string); +GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeReference, reference); +GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeSelection, selection); +GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeSelectionList, selectionList); +GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeRefAttr, refattr); +GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeRefList, reflist); std::shared_ptr Model_Data::attribute(const std::string& theID) { @@ -329,7 +196,7 @@ void Model_Data::sendAttributeUpdated(ModelAPI_Attribute* theAttr) static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); ModelAPI_EventCreator::get()->sendUpdated(myObject, anEvent); if (myObject) { - myObject->attributeChanged(); + myObject->attributeChanged(theAttr->id()); } } } @@ -340,20 +207,25 @@ void Model_Data::erase() myLab.ForgetAllAttributes(); } -/// identifeir of the "must be updated" flag in the data tree -Standard_GUID kMustBeUpdatedGUID("baede74c-31a6-4416-9c4d-e48ce65f2005"); +void Model_Data::execState(const ModelAPI_ExecState theState) +{ + if (theState != ModelAPI_StateNothing) + TDataStd_Integer::Set(myLab, (int)theState); +} -void Model_Data::mustBeUpdated(const bool theFlag) +ModelAPI_ExecState Model_Data::execState() { - if (theFlag) - TDataStd_UAttribute::Set(myLab, kMustBeUpdatedGUID); - else - myLab.ForgetAttribute(kMustBeUpdatedGUID); + Handle(TDataStd_Integer) aStateAttr; + if (myLab.FindAttribute(TDataStd_Integer::GetID(), aStateAttr)) { + return ModelAPI_ExecState(aStateAttr->Get()); + } + return ModelAPI_StateMustBeUpdated; // default value } -bool Model_Data::mustBeUpdated() +void Model_Data::setError(const std::string& theError) { - return myLab.IsAttribute(kMustBeUpdatedGUID) == Standard_True; + execState(ModelAPI_StateExecFailed); + Events_Error::send(theError); } int Model_Data::featureId() const @@ -393,7 +265,6 @@ void Model_Data::referencesToObjects( std::shared_ptr aRef = std::dynamic_pointer_cast< ModelAPI_AttributeReference>(anAttr->second); aReferenced.push_back(aRef->value()); - theRefs.push_back(std::pair >(anAttr->first, aReferenced)); } else if (aType == ModelAPI_AttributeRefAttr::type()) { // reference to attribute or object std::shared_ptr aRef = std::dynamic_pointer_cast< ModelAPI_AttributeRefAttr>(anAttr->second); diff --git a/src/Model/Model_Data.h b/src/Model/Model_Data.h index 1d82ad14b..05068cd65 100644 --- a/src/Model/Model_Data.h +++ b/src/Model/Model_Data.h @@ -140,14 +140,17 @@ class Model_Data : public ModelAPI_Data myObject = theObject; } + /// Erases all the data from the data model MODEL_EXPORT virtual void erase(); - /// Makes feature must be updated later (on rebuild). Normally the Updater must call it - /// in case of not-automatic update to true - MODEL_EXPORT virtual void mustBeUpdated(const bool theFlag); + /// Stores the state of the object to execute it later accordingly + MODEL_EXPORT virtual void execState(const ModelAPI_ExecState theState); - /// Returns true if feature must be updated (re-executed) on rebuild - MODEL_EXPORT virtual bool mustBeUpdated(); + /// Returns the state of the latest execution of the feature + MODEL_EXPORT virtual ModelAPI_ExecState execState(); + + /// Registers error during the execution, causes the ExecutionFailed state + MODEL_EXPORT virtual void setError(const std::string& theError); /// Returns the identifier of feature-owner, unique in this document MODEL_EXPORT virtual int featureId() const; diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index 0fa26c8d4..304df74cb 100644 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -51,7 +51,8 @@ Model_Document::Model_Document(const std::string theID, const std::string theKin myDoc(new TDocStd_Document("BinOcaf")) // binary OCAF format { myDoc->SetUndoLimit(UNDO_LIMIT); - myTransactionsAfterSave = 0; + myTransactionsCounter = 0; + myTransactionSave = 0; myNestedNum = -1; myExecuteFeatures = true; // to have something in the document and avoid empty doc open/save problem @@ -191,7 +192,7 @@ bool Model_Document::save(const char* theFileName, std::list& theRe break; } } - myTransactionsAfterSave = 0; + myTransactionSave = myTransactionsCounter; if (isDone) { // save also sub-documents if any theResults.push_back(TCollection_AsciiString(aPath).ToCString()); std::set::iterator aSubIter = mySubs.begin(); @@ -250,8 +251,8 @@ void Model_Document::startOperation() myNestedNum = 0; myDoc->InitDeltaCompaction(); } - myIsEmptyTr[myTransactionsAfterSave] = !myDoc->CommitCommand(); - myTransactionsAfterSave++; + myIsEmptyTr[myTransactionsCounter] = !myDoc->CommitCommand(); + myTransactionsCounter++; myDoc->OpenCommand(); } else { // start the simple command myDoc->NewCommand(); @@ -266,15 +267,15 @@ bool Model_Document::compactNested() { bool allWasEmpty = true; while (myNestedNum != -1) { - myTransactionsAfterSave--; - if (!myIsEmptyTr[myTransactionsAfterSave]) { + myTransactionsCounter--; + if (!myIsEmptyTr[myTransactionsCounter]) { allWasEmpty = false; } - myIsEmptyTr.erase(myTransactionsAfterSave); + myIsEmptyTr.erase(myTransactionsCounter); myNestedNum--; } - myIsEmptyTr[myTransactionsAfterSave] = allWasEmpty; - myTransactionsAfterSave++; + myIsEmptyTr[myTransactionsCounter] = allWasEmpty; + myTransactionsCounter++; if (allWasEmpty) { // Issue 151: if everything is empty, it is a problem for OCCT to work with it, // just commit the empty that returns nothing @@ -329,8 +330,8 @@ void Model_Document::finishOperation() } } else { // returns false if delta is empty and no transaction was made - myIsEmptyTr[myTransactionsAfterSave] = !myDoc->CommitCommand(); // && (myNestedNum == -1); - myTransactionsAfterSave++; + myIsEmptyTr[myTransactionsCounter] = !myDoc->CommitCommand(); // && (myNestedNum == -1); + myTransactionsCounter++; } } @@ -338,11 +339,12 @@ void Model_Document::abortOperation() { if (myNestedNum > 0 && !myDoc->HasOpenCommand()) { // abort all what was done in nested // first compact all nested - compactNested(); - myDoc->Undo(); + if (compactNested()) { + myDoc->Undo(); // undo only compacted, if not: do not undo the empty transaction + } myDoc->ClearRedos(); - myTransactionsAfterSave--; - myIsEmptyTr.erase(myTransactionsAfterSave); + myTransactionsCounter--; + myIsEmptyTr.erase(myTransactionsCounter); } else { if (myNestedNum == 0) // abort only high-level myNestedNum = -1; @@ -364,13 +366,13 @@ bool Model_Document::isOperation() bool Model_Document::isModified() { // is modified if at least one operation was commited and not undoed - return myTransactionsAfterSave > 0 || isOperation(); + return myTransactionsCounter != myTransactionSave || isOperation(); } bool Model_Document::canUndo() { if (myDoc->GetAvailableUndos() > 0 && myNestedNum != 0 - && myTransactionsAfterSave != 0 /* for omitting the first useless transaction */) + && myTransactionsCounter != 0 /* for omitting the first useless transaction */) return true; // check other subs contains operation that can be undoed std::set::iterator aSubIter = mySubs.begin(); @@ -382,10 +384,10 @@ bool Model_Document::canUndo() void Model_Document::undo() { - myTransactionsAfterSave--; + myTransactionsCounter--; if (myNestedNum > 0) myNestedNum--; - if (!myIsEmptyTr[myTransactionsAfterSave]) + if (!myIsEmptyTr[myTransactionsCounter]) myDoc->Undo(); synchronizeFeatures(true, true); // undo for all subs @@ -410,9 +412,9 @@ void Model_Document::redo() { if (myNestedNum != -1) myNestedNum++; - if (!myIsEmptyTr[myTransactionsAfterSave]) + if (!myIsEmptyTr[myTransactionsCounter]) myDoc->Redo(); - myTransactionsAfterSave++; + myTransactionsCounter++; synchronizeFeatures(true, true); // redo for all subs std::set::iterator aSubIter = mySubs.begin(); @@ -885,6 +887,10 @@ void Model_Document::synchronizeBackRefs() ModelAPI_EventCreator::get()->sendUpdated(aCIter->first, anEvent); } else { // was not concealed become concealed => delete event ModelAPI_EventCreator::get()->sendDeleted(aThis, aCIter->first->groupName()); + // redisplay for the viewer (it must be disappeared also) + static Events_ID EVENT_DISP = + Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); + ModelAPI_EventCreator::get()->sendUpdated(aCIter->first, EVENT_DISP); } } } @@ -1009,6 +1015,9 @@ void Model_Document::updateResults(FeaturePtr theFeature) } aResIter++; } + // it may be on undo + if (!theFeature->data() || !theFeature->data()->isValid()) + return; // check that results are presented on all labels int aResSize = theFeature->results().size(); TDF_ChildIterator aLabIter(resultLabel(theFeature->data(), 0).Father()); diff --git a/src/Model/Model_Document.h b/src/Model/Model_Document.h index 519c57a19..0b7a618c6 100644 --- a/src/Model/Model_Document.h +++ b/src/Model/Model_Document.h @@ -181,6 +181,7 @@ class Model_Document : public ModelAPI_Document friend class Model_Application; friend class Model_Session; + friend class Model_Update; friend class Model_AttributeReference; friend class DFBrowser; @@ -188,8 +189,10 @@ class Model_Document : public ModelAPI_Document std::string myID; ///< identifier of the document in the application std::string myKind; ///< kind of the document in the application Handle_TDocStd_Document myDoc; ///< OCAF document - /// number of transactions after the last "save" call, used for "IsModified" method - int myTransactionsAfterSave; + /// counter of transactions + int myTransactionsCounter; + /// counter value of transaction on the last "save" call, used for "IsModified" method + int myTransactionSave; /// number of nested transactions performed (or -1 if not nested) int myNestedNum; /// All features managed by this document (not only in history of OB) diff --git a/src/Model/Model_Events.h b/src/Model/Model_Events.h index 163c84581..e262377c4 100644 --- a/src/Model/Model_Events.h +++ b/src/Model/Model_Events.h @@ -8,6 +8,8 @@ #include #include +#include + /// Allovs to create ModelAPI messages class Model_EventCreator : public ModelAPI_EventCreator { diff --git a/src/Model/Model_FeatureValidator.cpp b/src/Model/Model_FeatureValidator.cpp index 6e609dd5d..b34f03edd 100644 --- a/src/Model/Model_FeatureValidator.cpp +++ b/src/Model/Model_FeatureValidator.cpp @@ -15,8 +15,10 @@ bool Model_FeatureValidator::isValid(const std::shared_ptr& th const std::list& theArguments) const { std::shared_ptr aData = theFeature->data(); - if (!aData) - return false; + // "Action" features has no data, but still valid. e.g "Remove Part" + if (!aData) { + return theFeature->isAction(); + } if (!aData->isValid()) return false; const std::string kAllTypes = ""; @@ -24,10 +26,10 @@ bool Model_FeatureValidator::isValid(const std::shared_ptr& th std::list::iterator it = aLtAttributes.begin(); for (; it != aLtAttributes.end(); it++) { AttributePtr anAttr = aData->attribute(*it); - if (!anAttr->isInitialized()) { + if (!anAttr->isInitialized()) { // attribute is not initialized std::map >::const_iterator aFeatureFind = myNotObligatory.find(theFeature->getKind()); - if (aFeatureFind == myNotObligatory.end() || + if (aFeatureFind == myNotObligatory.end() || // and it is obligatory for filling aFeatureFind->second.find(*it) == aFeatureFind->second.end()) { return false; } @@ -41,3 +43,9 @@ void Model_FeatureValidator::registerNotObligatory(std::string theFeature, std:: std::set& anAttrs = myNotObligatory[theFeature]; anAttrs.insert(theAttribute); } + +bool Model_FeatureValidator::isNotObligatory(std::string theFeature, std::string theAttribute) +{ + std::set& anAttrs = myNotObligatory[theFeature]; + return anAttrs.find(theAttribute) != anAttrs.end(); +} diff --git a/src/Model/Model_FeatureValidator.h b/src/Model/Model_FeatureValidator.h index b262ff0ea..dddfb2a31 100644 --- a/src/Model/Model_FeatureValidator.h +++ b/src/Model/Model_FeatureValidator.h @@ -24,7 +24,10 @@ class Model_FeatureValidator : public ModelAPI_FeatureValidator const std::list& theArguments) const; // sets not obligatory attributes, not checked for initialization - void registerNotObligatory(std::string theFeature, std::string theAttribute); + virtual void registerNotObligatory(std::string theFeature, std::string theAttribute); + + /// Returns true if the attribute in feature is not obligatory for the feature execution + virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); }; #endif diff --git a/src/Model/Model_ResultBody.cpp b/src/Model/Model_ResultBody.cpp index 59c65ac9e..13db22108 100644 --- a/src/Model/Model_ResultBody.cpp +++ b/src/Model/Model_ResultBody.cpp @@ -92,7 +92,7 @@ void Model_ResultBody::storeModified(const std::shared_ptr& theOl TopoDS_Shape aShapeNew = theNewShape->impl(); if (aShapeNew.IsNull()) return; // null shape inside - aBuilder.Generated(aShapeOld, aShapeNew); + aBuilder.Modify(aShapeOld, aShapeNew); } } diff --git a/src/Model/Model_Session.cpp b/src/Model/Model_Session.cpp index d8e516698..88f87b73e 100644 --- a/src/Model/Model_Session.cpp +++ b/src/Model/Model_Session.cpp @@ -141,6 +141,12 @@ std::shared_ptr Model_Session::moduleDocument() Model_Application::getApplication()->getDocument("root")); } +std::shared_ptr Model_Session::document(std::string theDocID) +{ + return std::shared_ptr( + Model_Application::getApplication()->getDocument(theDocID)); +} + bool Model_Session::hasModuleDocument() { return Model_Application::getApplication()->hasDocument("root"); diff --git a/src/Model/Model_Session.h b/src/Model/Model_Session.h index 72977752a..41d62e4f9 100644 --- a/src/Model/Model_Session.h +++ b/src/Model/Model_Session.h @@ -69,6 +69,9 @@ class Model_Session : public ModelAPI_Session, public Events_Listener /// Returns the root document of the application (that may contains sub-documents) MODEL_EXPORT virtual std::shared_ptr moduleDocument(); + /// Returns the document by ID, loads if not loaded yet. Returns null if no such document. + MODEL_EXPORT virtual std::shared_ptr document(std::string theDocID); + /// Return true if root document has been already created MODEL_EXPORT virtual bool hasModuleDocument(); diff --git a/src/Model/Model_Update.cpp b/src/Model/Model_Update.cpp index 8aa00217e..3a70e463a 100644 --- a/src/Model/Model_Update.cpp +++ b/src/Model/Model_Update.cpp @@ -115,37 +115,15 @@ void Model_Update::processEvent(const std::shared_ptr& theMessag //Events_LongOp::start(this); isExecuted = true; - std::list > aDocs; std::shared_ptr aMsg = std::dynamic_pointer_cast(theMessage); if (aMsg) myInitial = aMsg->objects(); else { myInitial.clear(); - // on change flag all documents must be updated - if (isAutomatic) { - aDocs = ModelAPI_Session::get()->allOpenedDocuments(); - } - } - // collect all documents involved into the update process - set >::iterator aFIter = myInitial.begin(); - for (; aFIter != myInitial.end(); aFIter++) { - aDocs.push_back((*aFIter)->document()); - } - // iterate all features of features-documents to update them (including hidden) - std::set > alreadyUsed; - list >::iterator aDIter = aDocs.begin(); - for (; aDIter != aDocs.end(); aDIter++) { - if (alreadyUsed.find(*aDIter) != alreadyUsed.end()) - continue; - alreadyUsed.insert(*aDIter); - int aNbFeatures = (*aDIter)->size(ModelAPI_Feature::group(), true); - for (int aFIndex = 0; aFIndex < aNbFeatures; aFIndex++) { - FeaturePtr aFeature = std::dynamic_pointer_cast( - (*aDIter)->object(ModelAPI_Feature::group(), aFIndex, true)); - if (aFeature) - updateFeature(aFeature); - } } + // iterate all documents: features in Root first, then - subs + updateInDoc(ModelAPI_Session::get()->moduleDocument()); + myUpdated.clear(); // flush to update display static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); @@ -160,20 +138,58 @@ void Model_Update::processEvent(const std::shared_ptr& theMessag isExecuted = false; } -void Model_Update::redisplayWithResults(FeaturePtr theFeature) { - // maske updated and redisplay all results +void Model_Update::updateInDoc(std::shared_ptr theDoc) +{ + // all features one by one + int aNbFeatures = theDoc->size(ModelAPI_Feature::group(), true); + for (int aFIndex = 0; aFIndex < aNbFeatures; aFIndex++) { + FeaturePtr aFeature = std::dynamic_pointer_cast( + theDoc->object(ModelAPI_Feature::group(), aFIndex, true)); + if (aFeature) + updateFeature(aFeature); + } + // all sub-documents one by one + std::shared_ptr aDoc = std::dynamic_pointer_cast(theDoc); + if (aDoc) { + const std::set& aSubs = aDoc->subDocuments(); + for(std::set::iterator aSub = aSubs.begin(); aSub != aSubs.end(); aSub++) { + DocumentPtr aSubDoc = theDoc->subDocument(*aSub); + if (aSubDoc) { + updateInDoc(aSubDoc); + } + } + } +} + +void Model_Update::redisplayWithResults(FeaturePtr theFeature, const ModelAPI_ExecState theState) +{ + // make updated and redisplay all results static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); const std::list >& aResults = theFeature->results(); std::list >::const_iterator aRIter = aResults.begin(); for (; aRIter != aResults.cend(); aRIter++) { std::shared_ptr aRes = *aRIter; - aRes->data()->mustBeUpdated(false); + aRes->data()->execState(theState); myUpdated[aRes] = true; ModelAPI_EventCreator::get()->sendUpdated(aRes, EVENT_DISP); } // to redisplay "presentable" feature (for ex. distance constraint) ModelAPI_EventCreator::get()->sendUpdated(theFeature, EVENT_DISP); - theFeature->data()->mustBeUpdated(false); + theFeature->data()->execState(theState); +} + +/// Updates the state by the referenced object: if something bad with it, set state for this one +ModelAPI_ExecState stateByReference(ObjectPtr theTarget, const ModelAPI_ExecState theCurrent) +{ + if (theTarget) { + ModelAPI_ExecState aRefState = theTarget->data()->execState(); + if (aRefState == ModelAPI_StateMustBeUpdated) { + return ModelAPI_StateMustBeUpdated; + } else if (aRefState != ModelAPI_StateDone) { + return ModelAPI_StateInvalidArgument; + } + } + return theCurrent; } bool Model_Update::updateFeature(FeaturePtr theFeature) @@ -185,7 +201,8 @@ bool Model_Update::updateFeature(FeaturePtr theFeature) ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators(); bool aMustbeUpdated = myInitial.find(theFeature) != myInitial.end(); if (theFeature) { // only real feature contains references to other objects - if (theFeature->data()->mustBeUpdated()) aMustbeUpdated = true; + if (theFeature->data()->execState() != ModelAPI_StateDone) + aMustbeUpdated = true; // composite feature must be executed after sub-features execution CompositeFeaturePtr aComposite = @@ -197,7 +214,9 @@ bool Model_Update::updateFeature(FeaturePtr theFeature) aMustbeUpdated = true; } } + ModelAPI_ExecState aState = ModelAPI_StateDone; // check all references: if referenced objects are updated, this object also must be updated + // also check state of referenced objects: if they are not ready, inherit corresponding state std::list > > aRefs; std::shared_ptr aData = std::dynamic_pointer_cast(theFeature->data()); @@ -209,6 +228,7 @@ bool Model_Update::updateFeature(FeaturePtr theFeature) if (updateObject(*aRefObj)) { aMustbeUpdated = true; } + aState = stateByReference(*aRefObj, aState); } } @@ -218,71 +238,94 @@ bool Model_Update::updateFeature(FeaturePtr theFeature) if (std::dynamic_pointer_cast(theFeature->document())->executeFeatures() || !theFeature->isPersistentResult()) { if (aFactory->validate(theFeature)) { - if (isAutomatic || (myJustCreatedOrUpdated.find(theFeature) != myJustCreatedOrUpdated.end()) || - !theFeature->isPersistentResult() /* execute quick, not persistent results */) + if (isAutomatic || + (myJustCreatedOrUpdated.find(theFeature) != myJustCreatedOrUpdated.end()) || + !theFeature->isPersistentResult() /* execute quick, not persistent results */) { - //std::cout<<"Execute feature "<getKind()< aRefs = - theFeature->data()->attributes(ModelAPI_AttributeSelection::type()); - list::iterator aRefsIter = aRefs.begin(); - for (; aRefsIter != aRefs.end(); aRefsIter++) { - std::shared_ptr aSel = - std::dynamic_pointer_cast(*aRefsIter); - aSel->update(); // this must be done on execution since it may be long operation - } - aRefs = theFeature->data()->attributes(ModelAPI_AttributeSelectionList::type()); - for (aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) { - std::shared_ptr aSel = - std::dynamic_pointer_cast(*aRefsIter); - for(int a = aSel->size() - 1; a >= 0; a--) { - aSel->value(a)->update(); + if (aState == ModelAPI_StateDone) {// all referenced objects are ready to be used + //std::cout<<"Execute feature "<getKind()< aRefs = + theFeature->data()->attributes(ModelAPI_AttributeSelection::type()); + list::iterator aRefsIter = aRefs.begin(); + for (; aRefsIter != aRefs.end(); aRefsIter++) { + std::shared_ptr aSel = + std::dynamic_pointer_cast(*aRefsIter); + if (!aSel->update()) { // this must be done on execution since it may be long operation + if (!aFactory->isNotObligatory(theFeature->getKind(), theFeature->data()->id(aSel))) + aState = ModelAPI_StateInvalidArgument; + } } - } - // for sketch after update of plane (by update of selection attribute) - // but before execute, all sub-elements also must be updated (due to the plane changes) - if (aComposite) { - int aSubsNum = aComposite->numberOfSubs(); - for(int a = 0; a < aSubsNum; a++) { - FeaturePtr aSub = aComposite->subFeature(a); - bool aWasModified = myUpdated[aSub]; - myUpdated.erase(myUpdated.find(aSub)); // erase to update for sure (plane may be changed) - myInitial.insert(aSub); - updateFeature(aSub); - myUpdated[aSub] = aWasModified; // restore value + aRefs = theFeature->data()->attributes(ModelAPI_AttributeSelectionList::type()); + for (aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) { + std::shared_ptr aSel = + std::dynamic_pointer_cast(*aRefsIter); + for(int a = aSel->size() - 1; a >= 0; a--) { + std::shared_ptr aSelAttr = + std::dynamic_pointer_cast(aSel->value(a)); + if (aSelAttr) { + if (!aSelAttr->update()) { + if (!aFactory->isNotObligatory( + theFeature->getKind(), theFeature->data()->id(aSel))) + aState = ModelAPI_StateInvalidArgument; + } + } + } } - // re-execute after update: solver may update the previous values, so, shapes must be - // updated - for(int a = 0; a < aSubsNum; a++) { - if (aComposite->subFeature(a) && aFactory->validate(aComposite->subFeature(a))) - aComposite->subFeature(a)->execute(); + // for sketch after update of plane (by update of selection attribute) + // but before execute, all sub-elements also must be updated (due to the plane changes) + if (aComposite) { + int aSubsNum = aComposite->numberOfSubs(); + for(int a = 0; a < aSubsNum; a++) { + FeaturePtr aSub = aComposite->subFeature(a); + bool aWasModified = myUpdated[aSub]; + myUpdated.erase(myUpdated.find(aSub)); // erase to update for sure (plane may be changed) + myInitial.insert(aSub); + updateFeature(aSub); + myUpdated[aSub] = aWasModified; // restore value + } + // re-execute after update: solver may update the previous values, so, shapes must be + // updated + for(int a = 0; a < aSubsNum; a++) { + if (aComposite->subFeature(a) && aFactory->validate(aComposite->subFeature(a))) + aComposite->subFeature(a)->execute(); + } } } // execute in try-catch to avoid internal problems of the feature - try { - theFeature->execute(); - } catch(...) { - Events_Error::send( - "Feature " + theFeature->getKind() + " has failed during the execution"); + if (aState == ModelAPI_StateDone) { + theFeature->data()->execState(ModelAPI_StateDone); + try { + theFeature->execute(); + if (theFeature->data()->execState() != ModelAPI_StateDone) { + aState = ModelAPI_StateExecFailed; + } + } catch(...) { + aState = ModelAPI_StateExecFailed; + Events_Error::send( + "Feature " + theFeature->getKind() + " has failed during the execution"); + } + } + if (aState != ModelAPI_StateDone) { theFeature->eraseResults(); } - redisplayWithResults(theFeature); + redisplayWithResults(theFeature, aState); } else { // must be updatet, but not updated yet - theFeature->data()->mustBeUpdated(true); + theFeature->data()->execState(ModelAPI_StateMustBeUpdated); const std::list >& aResults = theFeature->results(); std::list >::const_iterator aRIter = aResults.begin(); for (; aRIter != aResults.cend(); aRIter++) { std::shared_ptr aRes = *aRIter; - aRes->data()->mustBeUpdated(true); + aRes->data()->execState(ModelAPI_StateMustBeUpdated); } } } else { theFeature->eraseResults(); - redisplayWithResults(theFeature); // result also must be updated + redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated } } else { // for automatically updated features (on abort, etc) it is necessary to redisplay anyway - redisplayWithResults(theFeature); + redisplayWithResults(theFeature, ModelAPI_StateNothing); } } else { // returns also true is results were updated: for sketch that refers to sub-features but results of sub-features were changed const std::list >& aResults = theFeature->results(); diff --git a/src/Model/Model_Update.h b/src/Model/Model_Update.h index 31d532da5..dd687177a 100644 --- a/src/Model/Model_Update.h +++ b/src/Model/Model_Update.h @@ -6,6 +6,7 @@ #define Model_Update_H_ #include "Model.h" +#include #include "Events_Listener.h" #include #include @@ -39,7 +40,9 @@ class Model_Update : public Events_Listener /// Processes the feature argument update: executes the results MODEL_EXPORT virtual void processEvent(const std::shared_ptr& theMessage); - protected: +protected: + /// updates all features in the document and then - in sub-documents + void updateInDoc(std::shared_ptr theDoc); /// Recoursively checks and updates the feature if needed (calls the execute method) /// Returns true if feature was updated. bool updateFeature(std::shared_ptr theFeature); @@ -48,7 +51,8 @@ class Model_Update : public Events_Listener /// Returns true if object was updated. bool updateObject(std::shared_ptr theObject, const bool theCyclic = true); /// Sends the redisplay events for feature and results, updates the updated status - void redisplayWithResults(std::shared_ptr theFeature); + void redisplayWithResults(std::shared_ptr theFeature, + const ModelAPI_ExecState theState); }; #endif diff --git a/src/Model/Model_Validator.cpp b/src/Model/Model_Validator.cpp index cc3a612a5..d8967d0e6 100644 --- a/src/Model/Model_Validator.cpp +++ b/src/Model/Model_Validator.cpp @@ -175,10 +175,12 @@ bool Model_ValidatorsFactory::validate(const std::shared_ptr& return false; } } + // check all attributes for validity std::shared_ptr aData = theFeature->data(); - if (!aData || !aData->isValid()) - return false; + // Validity of data is checked by "Model_FeatureValidator" (kDefaultId) + // if (!aData || !aData->isValid()) + // return false; static const std::string kAllTypes = ""; std::map >::const_iterator aFeatureIter = myAttrs.find(theFeature->getKind()); @@ -224,6 +226,19 @@ void Model_ValidatorsFactory::registerNotObligatory(std::string theFeature, std: } } +bool Model_ValidatorsFactory::isNotObligatory(std::string theFeature, std::string theAttribute) +{ + const static std::string kDefaultId = "Model_FeatureValidator"; + std::map::const_iterator it = myIDs.find(kDefaultId); + if (it != myIDs.end()) { + Model_FeatureValidator* aValidator = dynamic_cast(it->second); + if (aValidator) { + return aValidator->isNotObligatory(theFeature, theAttribute); + } + } + return false; // default +} + void Model_ValidatorsFactory::registerConcealment(std::string theFeature, std::string theAttribute) { std::map >::iterator aFind = myConcealed.find(theFeature); diff --git a/src/Model/Model_Validator.h b/src/Model/Model_Validator.h index a6d369963..a739a7978 100644 --- a/src/Model/Model_Validator.h +++ b/src/Model/Model_Validator.h @@ -76,6 +76,9 @@ class Model_ValidatorsFactory : public ModelAPI_ValidatorsFactory /// so, it is not needed for the standard validation mechanism virtual void registerNotObligatory(std::string theFeature, std::string theAttribute); + /// Returns true if the attribute in feature is not obligatory for the feature execution + virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); + /// register that this attribute conceals in the object browser /// all referenced features after execution virtual void registerConcealment(std::string theFeature, std::string theAttribute); diff --git a/src/ModelAPI/CMakeLists.txt b/src/ModelAPI/CMakeLists.txt index bbc99cbb1..ca13fe13d 100644 --- a/src/ModelAPI/CMakeLists.txt +++ b/src/ModelAPI/CMakeLists.txt @@ -39,6 +39,7 @@ SET(PROJECT_HEADERS ) SET(PROJECT_SOURCES + ModelAPI_Events.cpp ModelAPI_Feature.cpp ModelAPI_Session.cpp ModelAPI_Tools.cpp diff --git a/src/ModelAPI/ModelAPI_Attribute.h b/src/ModelAPI/ModelAPI_Attribute.h index 27d65eb9b..041e27b7c 100644 --- a/src/ModelAPI/ModelAPI_Attribute.h +++ b/src/ModelAPI/ModelAPI_Attribute.h @@ -19,11 +19,12 @@ class ModelAPI_Attribute { ///< needed here to emit signal that feature changed on change of the attribute std::shared_ptr myObject; + std::string myID; ///< identifier of this attribute in Data class protected: // accessible from the attributes - bool myIsInitialized; - bool myIsArgument; - bool myIsImmutable; + bool myIsInitialized; ///< is some value assigned to this attribute + bool myIsArgument; ///< is this attribute used as an argument for execution + bool myIsImmutable; ///< is this attribute can be changed programmatically (e.g. by constraint) public: @@ -88,6 +89,12 @@ class ModelAPI_Attribute return myIsImmutable; } + /// ID of the attribute in Data + MODELAPI_EXPORT const std::string& id() const + { + return myID; + } + protected: /// Objects are created for features automatically ModelAPI_Attribute() @@ -97,6 +104,13 @@ class ModelAPI_Attribute myIsImmutable = false; } + /// Sets the ID of the attribute in Data (called from Data) + MODELAPI_EXPORT void setID(const std::string theID) + { + myID = theID; + } + + friend class Model_Data; }; //! Pointer on attribute object diff --git a/src/ModelAPI/ModelAPI_Data.h b/src/ModelAPI/ModelAPI_Data.h index 8cc137477..8e33c85ff 100644 --- a/src/ModelAPI/ModelAPI_Data.h +++ b/src/ModelAPI/ModelAPI_Data.h @@ -26,6 +26,15 @@ class ModelAPI_AttributeSelection; class ModelAPI_AttributeSelectionList; class GeomAPI_Shape; +/// Enumeration that contains the execution status of the Object +enum ModelAPI_ExecState { + ModelAPI_StateDone, ///< execution was performed and result is up to date + ModelAPI_StateMustBeUpdated, ///< execution must be performed to obtain the up to date result + ModelAPI_StateExecFailed, ///< execution was failed (results are deleted in this case) + ModelAPI_StateInvalidArgument, ///< execution was not performed (results are deleted in this case) + ModelAPI_StateNothing ///< internal state that actually means that nothing must be changed +}; + /**\class ModelAPI_Data * \ingroup DataModel * \brief General object of the application that allows @@ -100,12 +109,14 @@ class MODELAPI_EXPORT ModelAPI_Data { } - /// Makes feature must be updated later (on rebuild). Normally the Updater must call it - /// in case of not-automatic update to true - virtual void mustBeUpdated(const bool theFlag) = 0; + /// Stores the state of the object to execute it later accordingly + virtual void execState(const ModelAPI_ExecState theState) = 0; + + /// Returns the state of the latest execution of the feature + virtual ModelAPI_ExecState execState() = 0; - /// Returns true if feature must be updated (re-executed) on rebuild - virtual bool mustBeUpdated() = 0; + /// Registers error during the execution, causes the ExecutionFailed state + virtual void setError(const std::string& theError) = 0; /// Returns the identifier of feature-owner, unique in this document virtual int featureId() const = 0; diff --git a/src/ModelAPI/ModelAPI_Events.cpp b/src/ModelAPI/ModelAPI_Events.cpp new file mode 100644 index 000000000..074ba0501 --- /dev/null +++ b/src/ModelAPI/ModelAPI_Events.cpp @@ -0,0 +1,34 @@ +/* + * ModelAPI_Events.cpp + * + * Created on: Dec 8, 2014 + * Author: sbh + */ + +#include +#include + +ModelAPI_ObjectUpdatedMessage::ModelAPI_ObjectUpdatedMessage(const Events_ID theID, + const void* theSender) + : Events_MessageGroup(theID, theSender) +{ + +} + +ModelAPI_ObjectUpdatedMessage::~ModelAPI_ObjectUpdatedMessage() +{ + +} + +ModelAPI_ObjectDeletedMessage::ModelAPI_ObjectDeletedMessage(const Events_ID theID, + const void* theSender) + : Events_MessageGroup(theID, theSender) +{ + +} + +ModelAPI_ObjectDeletedMessage::~ModelAPI_ObjectDeletedMessage() +{ + +} + diff --git a/src/ModelAPI/ModelAPI_Events.h b/src/ModelAPI/ModelAPI_Events.h index 9141c146c..b9bd7cef8 100644 --- a/src/ModelAPI/ModelAPI_Events.h +++ b/src/ModelAPI/ModelAPI_Events.h @@ -2,16 +2,17 @@ // Created: 10 Apr 2014 // Author: Mikhail PONIKAROV -#ifndef ModelAPI_Events_H_ -#define ModelAPI_Events_H_ +#ifndef MODELAPI_EVENTS_H_ +#define MODELAPI_EVENTS_H_ #include +#include #include + #include #include #include -#include "ModelAPI_Object.h" class ModelAPI_Document; @@ -35,13 +36,11 @@ static const char * EVENT_OBJECT_TOSHOW = "ObjectShow"; static const char * EVENT_OBJECT_TOHIDE = "ObjectHide"; /// Message that feature was changed (used for Object Browser update): moved, updated and deleted -class ModelAPI_ObjectUpdatedMessage : public Events_MessageGroup +class MODELAPI_EXPORT ModelAPI_ObjectUpdatedMessage : public Events_MessageGroup { protected: - ModelAPI_ObjectUpdatedMessage(const Events_ID theID, const void* theSender = 0) - : Events_MessageGroup(theID, theSender) - { - } + ModelAPI_ObjectUpdatedMessage(const Events_ID theID, const void* theSender = 0); + virtual ~ModelAPI_ObjectUpdatedMessage(); public: /// Returns the feature that has been updated @@ -55,13 +54,11 @@ class ModelAPI_ObjectUpdatedMessage : public Events_MessageGroup }; /// Message that feature was deleted (used for Object Browser update) -class ModelAPI_ObjectDeletedMessage : public Events_MessageGroup +class MODELAPI_EXPORT ModelAPI_ObjectDeletedMessage : public Events_MessageGroup { protected: - ModelAPI_ObjectDeletedMessage(const Events_ID theID, const void* theSender = 0) - : Events_MessageGroup(theID, theSender) - { - } + ModelAPI_ObjectDeletedMessage(const Events_ID theID, const void* theSender = 0); + virtual ~ModelAPI_ObjectDeletedMessage(); public: /// Returns the feature that has been updated diff --git a/src/ModelAPI/ModelAPI_Feature.h b/src/ModelAPI/ModelAPI_Feature.h index 431b065b7..6ea57af29 100644 --- a/src/ModelAPI/ModelAPI_Feature.h +++ b/src/ModelAPI/ModelAPI_Feature.h @@ -53,6 +53,11 @@ class ModelAPI_Feature : public ModelAPI_Object /// Computes or recomputes the results virtual void execute() = 0; + /// Registers error during the execution, causes the ExecutionFailed state + virtual void setError(const std::string& theError) { + data()->setError(theError); + } + /// returns the current results of the feature MODELAPI_EXPORT const std::list >& results(); /// returns the first result in the list or NULL reference diff --git a/src/ModelAPI/ModelAPI_FeatureValidator.h b/src/ModelAPI/ModelAPI_FeatureValidator.h index 6d44a735a..b29fda799 100644 --- a/src/ModelAPI/ModelAPI_FeatureValidator.h +++ b/src/ModelAPI/ModelAPI_FeatureValidator.h @@ -17,6 +17,9 @@ class ModelAPI_FeatureValidator : public ModelAPI_Validator /// \param theArguments list of string, feature attribute names: dependent attributes virtual bool isValid(const std::shared_ptr& theFeature, const std::list& theArguments) const = 0; + + /// Returns true if the attribute in feature is not obligatory for the feature execution + virtual bool isNotObligatory(std::string theFeature, std::string theAttribute) = 0; }; #endif diff --git a/src/ModelAPI/ModelAPI_Object.h b/src/ModelAPI/ModelAPI_Object.h index be4880540..3c8e6a6e8 100644 --- a/src/ModelAPI/ModelAPI_Object.h +++ b/src/ModelAPI/ModelAPI_Object.h @@ -55,7 +55,8 @@ class ModelAPI_Object virtual std::string groupName() = 0; /// Called on change of any argument-attribute of this object - MODELAPI_EXPORT virtual void attributeChanged() + /// \param theID identifier of changed attribute + MODELAPI_EXPORT virtual void attributeChanged(const std::string& theID) {} /// To use virtuality for destructors diff --git a/src/ModelAPI/ModelAPI_Result.h b/src/ModelAPI/ModelAPI_Result.h index 91304744e..cde508254 100644 --- a/src/ModelAPI/ModelAPI_Result.h +++ b/src/ModelAPI/ModelAPI_Result.h @@ -6,7 +6,7 @@ #define ModelAPI_Result_H_ #include "ModelAPI_Object.h" -#include "GeomAPI_Shape.h" +#include class ModelAPI_Feature; diff --git a/src/ModelAPI/ModelAPI_Session.h b/src/ModelAPI/ModelAPI_Session.h index 811174e7c..67186674d 100644 --- a/src/ModelAPI/ModelAPI_Session.h +++ b/src/ModelAPI/ModelAPI_Session.h @@ -71,6 +71,9 @@ class MODELAPI_EXPORT ModelAPI_Session /// Returns the root document of the application (that may contains sub-documents) virtual std::shared_ptr moduleDocument() = 0; + /// Returns the document by ID, loads if not loaded yet. Returns null if no such document. + virtual std::shared_ptr document(std::string theDocID) = 0; + /// Return true if root document has been already created virtual bool hasModuleDocument() = 0; diff --git a/src/ModelAPI/ModelAPI_Validator.h b/src/ModelAPI/ModelAPI_Validator.h index a4eb79416..3dfb14f10 100644 --- a/src/ModelAPI/ModelAPI_Validator.h +++ b/src/ModelAPI/ModelAPI_Validator.h @@ -83,6 +83,9 @@ class MODELAPI_EXPORT ModelAPI_ValidatorsFactory /// so, it is not needed for the standard validation mechanism virtual void registerNotObligatory(std::string theFeature, std::string theAttribute) = 0; + /// Returns true if the attribute in feature is not obligatory for the feature execution + virtual bool isNotObligatory(std::string theFeature, std::string theAttribute) = 0; + /// register that this attribute conceals in the object browser /// all referenced features after execution virtual void registerConcealment(std::string theFeature, std::string theAttribute) = 0; diff --git a/src/ModuleBase/CMakeLists.txt b/src/ModuleBase/CMakeLists.txt index ddf454e2c..e80812b3c 100644 --- a/src/ModuleBase/CMakeLists.txt +++ b/src/ModuleBase/CMakeLists.txt @@ -12,15 +12,9 @@ SET(PROJECT_HEADERS ModuleBase_WidgetDoubleValue.h ModuleBase_WidgetEditor.h ModuleBase_WidgetFactory.h - ModuleBase_WidgetFeature.h - ModuleBase_WidgetFeatureOrAttribute.h - ModuleBase_WidgetPoint2D.h ModuleBase_WidgetSwitch.h ModuleBase_WidgetShapeSelector.h ModuleBase_IWorkshop.h - ModuleBase_WidgetPoint2dDistance.h - ModuleBase_WidgetValue.h - ModuleBase_WidgetValueFeature.h ModuleBase_Definitions.h ModuleBase_SelectionValidator.h ModuleBase_ISelection.h @@ -34,6 +28,8 @@ SET(PROJECT_HEADERS ModuleBase_WidgetMultiSelector.h ModuleBase_ViewerFilters.h ModuleBase_ResultPrs.h + ModuleBase_IViewWindow.h + ModuleBase_WidgetLabel.h ) SET(PROJECT_SOURCES @@ -46,14 +42,8 @@ SET(PROJECT_SOURCES ModuleBase_WidgetDoubleValue.cpp ModuleBase_WidgetEditor.cpp ModuleBase_WidgetFactory.cpp - ModuleBase_WidgetFeature.cpp - ModuleBase_WidgetFeatureOrAttribute.cpp - ModuleBase_WidgetPoint2D.cpp ModuleBase_WidgetSwitch.cpp ModuleBase_WidgetShapeSelector.cpp - ModuleBase_WidgetPoint2dDistance.cpp - ModuleBase_WidgetValue.cpp - ModuleBase_WidgetValueFeature.cpp ModuleBase_WidgetChoice.cpp ModuleBase_WidgetFileSelector.cpp ModuleBase_DoubleSpinBox.cpp @@ -61,6 +51,7 @@ SET(PROJECT_SOURCES ModuleBase_WidgetMultiSelector.cpp ModuleBase_ViewerFilters.cpp ModuleBase_ResultPrs.cpp + ModuleBase_WidgetLabel.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/ModuleBase/ModuleBase_Definitions.h b/src/ModuleBase/ModuleBase_Definitions.h index 8cfed34b4..78a858bdd 100644 --- a/src/ModuleBase/ModuleBase_Definitions.h +++ b/src/ModuleBase/ModuleBase_Definitions.h @@ -2,10 +2,10 @@ #define ModuleBase_Definitions_H #include -#include +#include typedef QList QIntList; //!< list of int values typedef QList QShortList; //!< list of short int values typedef QList QDoubleList; //!< list of double values -typedef QList QFeatureList; //!< List of features +typedef QList QObjectPtrList; //!< List of ModelAPI_Objects #endif diff --git a/src/ModuleBase/ModuleBase_IModule.cpp b/src/ModuleBase/ModuleBase_IModule.cpp index daece8b0d..bd0c987e4 100644 --- a/src/ModuleBase/ModuleBase_IModule.cpp +++ b/src/ModuleBase/ModuleBase_IModule.cpp @@ -4,33 +4,58 @@ #include "ModuleBase_ViewerPrs.h" #include "ModuleBase_Operation.h" #include "ModuleBase_ISelection.h" +#include "ModuleBase_OperationDescription.h" #include #include +#include #include +#include +#include +#include ModuleBase_IModule::ModuleBase_IModule(ModuleBase_IWorkshop* theParent) : QObject(theParent), myWorkshop(theParent) { + connect(myWorkshop, SIGNAL(operationStarted(ModuleBase_Operation*)), + SLOT(onOperationStarted(ModuleBase_Operation*))); + + connect(myWorkshop, SIGNAL(operationStopped(ModuleBase_Operation*)), + SLOT(onOperationStopped(ModuleBase_Operation*))); + + connect(myWorkshop, SIGNAL(operationResumed(ModuleBase_Operation*)), + SLOT(onOperationResumed(ModuleBase_Operation*))); + + connect(myWorkshop, SIGNAL(operationComitted(ModuleBase_Operation*)), + SLOT(onOperationComitted(ModuleBase_Operation*))); + + connect(myWorkshop, SIGNAL(operationAborted(ModuleBase_Operation*)), + SLOT(onOperationAborted(ModuleBase_Operation*))); + connect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged())); - connect(myWorkshop->viewer(), SIGNAL(mousePress(QMouseEvent*)), this, - SLOT(onMousePressed(QMouseEvent*))); - connect(myWorkshop->viewer(), SIGNAL(mouseRelease(QMouseEvent*)), this, - SLOT(onMouseReleased(QMouseEvent*))); - connect(myWorkshop->viewer(), SIGNAL(mouseMove(QMouseEvent*)), this, - SLOT(onMouseMoved(QMouseEvent*))); - connect(myWorkshop->viewer(), SIGNAL(keyRelease(QKeyEvent*)), this, - SLOT(onKeyRelease(QKeyEvent*))); - connect(myWorkshop->viewer(), SIGNAL(mouseDoubleClick(QMouseEvent*)), this, - SLOT(onMouseDoubleClick(QMouseEvent*))); + + + //connect(myWorkshop->viewer(), SIGNAL(mousePress(QMouseEvent*)), this, + // SLOT(onMousePressed(QMouseEvent*))); + //connect(myWorkshop->viewer(), SIGNAL(mouseRelease(QMouseEvent*)), this, + // SLOT(onMouseReleased(QMouseEvent*))); + //connect(myWorkshop->viewer(), SIGNAL(mouseMove(QMouseEvent*)), this, + // SLOT(onMouseMoved(QMouseEvent*))); + //connect(myWorkshop->viewer(), SIGNAL(keyRelease(QKeyEvent*)), this, + // SLOT(onKeyRelease(QKeyEvent*))); + //connect(myWorkshop->viewer(), SIGNAL(mouseDoubleClick(QMouseEvent*)), this, + // SLOT(onMouseDoubleClick(QMouseEvent*))); } void ModuleBase_IModule::launchOperation(const QString& theCmdId) { + if (!myWorkshop->canStartOperation(theCmdId)) + return; + ModuleBase_Operation* anOperation = createOperation(theCmdId.toStdString()); ModuleBase_ISelection* aSelection = myWorkshop->selection(); // Initialise operation with preliminary selection @@ -47,3 +72,71 @@ void ModuleBase_IModule::sendOperation(ModuleBase_Operation* theOperation) aMessage->setPointer(theOperation); Events_Loop::loop()->send(aMessage); } + +ModuleBase_Operation* ModuleBase_IModule::getNewOperation(const std::string& theFeatureId) +{ + return new ModuleBase_Operation(theFeatureId.c_str(), this); +} + +ModuleBase_Operation* ModuleBase_IModule::createOperation(const std::string& theFeatureId) +{ + ModuleBase_Operation* anOperation = getNewOperation(theFeatureId); + + // If the operation is launched as sub-operation of another then we have to initialise + // parent feature + ModuleBase_Operation* aCurOperation = myWorkshop->currentOperation(); + if (aCurOperation) { + FeaturePtr aFeature = aCurOperation->feature(); + CompositeFeaturePtr aCompFea = std::dynamic_pointer_cast(aFeature); + if (aCompFea) + anOperation->setParentFeature(aCompFea); + } + + std::string aPluginFileName = myFeaturesInFiles[theFeatureId]; + Config_WidgetReader aWdgReader = Config_WidgetReader(aPluginFileName); + aWdgReader.readAll(); + std::string aXmlCfg = aWdgReader.featureWidgetCfg(theFeatureId); + std::string aDescription = aWdgReader.featureDescription(theFeatureId); + + anOperation->getDescription()->setDescription(QString::fromStdString(aDescription)); + anOperation->getDescription()->setXmlRepresentation(QString::fromStdString(aXmlCfg)); + + return anOperation; +} + +void ModuleBase_IModule::createFeatures() +{ + registerValidators(); + + Config_ModuleReader aXMLReader = Config_ModuleReader(); + aXMLReader.readAll(); + myFeaturesInFiles = aXMLReader.featuresInFiles(); +} + + +void ModuleBase_IModule::actionCreated(QAction* theFeature) +{ + connect(theFeature, SIGNAL(triggered(bool)), this, SLOT(onFeatureTriggered())); +} + + +void ModuleBase_IModule::onFeatureTriggered() +{ + QAction* aCmd = dynamic_cast(sender()); + //Do nothing on uncheck + if (aCmd->isCheckable() && !aCmd->isChecked()) + return; + launchOperation(aCmd->data().toString()); +} + + +void ModuleBase_IModule::editFeature(FeaturePtr theFeature) +{ + std::string aFeatureId = theFeature->getKind(); + if (!myWorkshop->canStartOperation(aFeatureId.c_str())) + return; + + ModuleBase_Operation* anOperation = createOperation(aFeatureId); + anOperation->setFeature(theFeature); + sendOperation(anOperation); +} \ No newline at end of file diff --git a/src/ModuleBase/ModuleBase_IModule.h b/src/ModuleBase/ModuleBase_IModule.h index 5787ccfb0..46d0e81ca 100644 --- a/src/ModuleBase/ModuleBase_IModule.h +++ b/src/ModuleBase/ModuleBase_IModule.h @@ -1,107 +1,140 @@ -#ifndef ModuleBase_IModule_H -#define ModuleBase_IModule_H - -#include "ModuleBase.h" -#include "ModuleBase_IWorkshop.h" - -#include -#include - - -class QAction; +#ifndef ModuleBase_IModule_H +#define ModuleBase_IModule_H + +#include "ModuleBase.h" +#include "ModuleBase_IWorkshop.h" + +#include + +#include +#include + +#include +#include + +class QAction; class QMouseEvent; class QKeyEvent; -class Config_WidgetAPI; -class ModuleBase_ModelWidget; -class ModuleBase_Operation; -class ModuleBase_IWorkshop; - -/** - * Interface to a module - */ -class MODULEBASE_EXPORT ModuleBase_IModule : public QObject -{ - Q_OBJECT - public: - - ModuleBase_IModule(ModuleBase_IWorkshop* theParent); - - virtual ~ModuleBase_IModule() {} - - /// Reads description of features from XML file - virtual void createFeatures() = 0; - - /// Called on creation of menu item in desktop - virtual void featureCreated(QAction*) = 0; - - /// Creates an operation and send it to loop - /// \param theCmdId the operation name - virtual void launchOperation(const QString& theCmdId); - - /// Called when it is necessary to update a command state (enable or disable it) - //virtual bool isFeatureEnabled(const QString& theCmdId) const = 0; - - /// Creates custom widgets for property panel - virtual QWidget* createWidgetByType(const std::string& theType, QWidget* theParent, - Config_WidgetAPI* theWidgetApi, - QList& theModelWidgets) - { - return 0; - } - - ModuleBase_IWorkshop* workshop() const { return myWorkshop; } - -protected slots: - - /// Called on selection changed event - virtual void onSelectionChanged() {} - +class Config_WidgetAPI; +class ModuleBase_ModelWidget; +class ModuleBase_Operation; +class ModuleBase_IWorkshop; + +/** + * Interface to a module + */ +class MODULEBASE_EXPORT ModuleBase_IModule : public QObject +{ + Q_OBJECT + public: + + ModuleBase_IModule(ModuleBase_IWorkshop* theParent); + + virtual ~ModuleBase_IModule() {} + + /// Reads description of features from XML file + virtual void createFeatures(); + + /// Called on creation of menu item in desktop + virtual void actionCreated(QAction*); + + /// Called when user selects feature for editing + virtual void editFeature(FeaturePtr theFeature); + + /// Creates an operation and send it to loop + /// \param theCmdId the operation name + virtual void launchOperation(const QString& theCmdId); + + /// Called when it is necessary to update a command state (enable or disable it) + //virtual bool isFeatureEnabled(const QString& theCmdId) const = 0; + + /// Creates custom widgets for property panel + virtual QWidget* createWidgetByType(const std::string& theType, QWidget* theParent, + Config_WidgetAPI* theWidgetApi, std::string theParentId, + QList& theModelWidgets) + { + return 0; + } + + ModuleBase_IWorkshop* workshop() const { return myWorkshop; } + + /// Call back forlast tuning of property panel before operation performance + /// It is called as on clearing of property panel as on filling with new widgets + virtual void propertyPanelDefined(ModuleBase_Operation* theOperation) {} + +public slots: + void onFeatureTriggered(); + +protected slots: + /// SLOT, that is called after the operation is started. Connect on the focus activated signal + virtual void onOperationStarted(ModuleBase_Operation* theOperation) {} + + /// SLOT, that is called after the operation is stopped. Switched off the modfications performed + /// by the operation start + virtual void onOperationStopped(ModuleBase_Operation* theOperation) {} + + virtual void onOperationResumed(ModuleBase_Operation* theOperation) {} + + virtual void onOperationComitted(ModuleBase_Operation* theOperation) {} + + virtual void onOperationAborted(ModuleBase_Operation* theOperation) {} + + + /// Called on selection changed event + virtual void onSelectionChanged() {} + /// SLOT, that is called by mouse press in the viewer. /// The mouse released point is sent to the current operation to be processed. /// \param theEvent the mouse event - virtual void onMousePressed(QMouseEvent* theEvent) {} + //virtual void onMousePressed(QMouseEvent* theEvent) {} /// SLOT, that is called by mouse release in the viewer. /// The mouse released point is sent to the current operation to be processed. /// \param theEvent the mouse event - virtual void onMouseReleased(QMouseEvent* theEvent) {} + //virtual void onMouseReleased(QMouseEvent* theEvent) {} /// SLOT, that is called by mouse move in the viewer. /// The mouse moved point is sent to the current operation to be processed. /// \param theEvent the mouse event - virtual void onMouseMoved(QMouseEvent* theEvent) {} + //virtual void onMouseMoved(QMouseEvent* theEvent) {} /// SLOT, that is called by the mouse double click in the viewer. /// \param theEvent the mouse event - virtual void onMouseDoubleClick(QMouseEvent* theEvent) {} + //virtual void onMouseDoubleClick(QMouseEvent* theEvent) {} /// SLOT, that is called by the key in the viewer is clicked. /// \param theEvent the mouse event - virtual void onKeyRelease(QKeyEvent* theEvent) {} - - protected: - /// Sends the operation for launching - /// \param theOperation the operation - void sendOperation(ModuleBase_Operation* theOperation); - - /// Creates a new operation - /// \param theCmdId the operation name - /// \param theFeatureKind a kind of feature to get the feature xml description - virtual ModuleBase_Operation* createOperation(const std::string& theCmdId, - const std::string& theFeatureKind = "") = 0; - - -protected: - - ModuleBase_IWorkshop* myWorkshop; - -}; - -//! This function must return a new module instance. -extern "C" { -typedef ModuleBase_IModule* (*CREATE_FUNC)(ModuleBase_IWorkshop*); -} - -#define CREATE_MODULE "createModule" - -#endif //ModuleBase_IModule + //virtual void onKeyRelease(QKeyEvent* theEvent) {} + + protected: + /// Sends the operation for launching + /// \param theOperation the operation + void sendOperation(ModuleBase_Operation* theOperation); + + /// Creates a new operation + /// \param theCmdId the operation name + /// \param theFeatureKind a kind of feature to get the feature xml description + virtual ModuleBase_Operation* createOperation(const std::string& theFeatureId); + + /// Register validators for this module + virtual void registerValidators() {} + + /// Returns new instance of operation object (used in createOperation for customization) + virtual ModuleBase_Operation* getNewOperation(const std::string& theFeatureId); + +protected: + + ModuleBase_IWorkshop* myWorkshop; + std::map myFeaturesInFiles; +}; + + + +//! This function must return a new module instance. +extern "C" { +typedef ModuleBase_IModule* (*CREATE_FUNC)(ModuleBase_IWorkshop*); +} + +#define CREATE_MODULE "createModule" + +#endif //ModuleBase_IModule diff --git a/src/ModuleBase/ModuleBase_IPropertyPanel.h b/src/ModuleBase/ModuleBase_IPropertyPanel.h index 7f8d9d32d..393137e5b 100644 --- a/src/ModuleBase/ModuleBase_IPropertyPanel.h +++ b/src/ModuleBase/ModuleBase_IPropertyPanel.h @@ -19,7 +19,7 @@ class MODULEBASE_EXPORT ModuleBase_IPropertyPanel : public QDockWidget { Q_OBJECT public: - ModuleBase_IPropertyPanel(QWidget* theParent) : QDockWidget(theParent) {} + ModuleBase_IPropertyPanel(QWidget* theParent) : QDockWidget(theParent), myIsEditing(false) {} /// Returns currently active widget virtual ModuleBase_ModelWidget* activeWidget() const = 0; @@ -27,14 +27,22 @@ public: /// Returns all property panel's widget created by WidgetFactory virtual const QList& modelWidgets() const = 0; + /// Editing mode depends on mode of current operation. This value is defined by it. + void setEditingMode(bool isEditing) { myIsEditing = isEditing; } + bool isEditingMode() const { return myIsEditing; } + signals: /// The signal about key release on the control, that corresponds to the attribute /// \param theEvent key release event void keyReleased(QKeyEvent* theEvent); + /// The signal about the widget activation /// \param theWidget the activated widget void widgetActivated(ModuleBase_ModelWidget* theWidget); + /// Emited when there is no next widget + void noMoreWidgets(); + public slots: /// Activate the next widget in the property panel /// \param theWidget a widget. The next widget should be activated @@ -42,6 +50,14 @@ public slots: /// Activate the next from current widget in the property panel virtual void activateNextWidget() = 0; + + // Makes the given widget active, highlights it and removes + // highlighting from the previous active widget + // emits widgetActivated(theWidget) signal + virtual void activateWidget(ModuleBase_ModelWidget* theWidget) = 0; + +protected: + bool myIsEditing; }; #endif \ No newline at end of file diff --git a/src/ModuleBase/ModuleBase_ISelection.h b/src/ModuleBase/ModuleBase_ISelection.h index c1b06ca1b..037be3bd0 100644 --- a/src/ModuleBase/ModuleBase_ISelection.h +++ b/src/ModuleBase/ModuleBase_ISelection.h @@ -31,14 +31,14 @@ class ModuleBase_ISelection virtual QList getHighlighted(int theShapeTypeToSkip = -1) const = 0; /** - * Returns list of features currently selected in 3d viewer + * Returns list of features currently selected in object browser */ - virtual QList selectedObjects() const = 0; + virtual QObjectPtrList selectedObjects() const = 0; /** * Returns list of currently selected results */ - virtual QList selectedPresentations() const = 0; + virtual QObjectPtrList selectedPresentations() const = 0; //! Returns list of currently selected QModelIndexes virtual QModelIndexList selectedIndexes() const = 0; diff --git a/src/ModuleBase/ModuleBase_IViewWindow.h b/src/ModuleBase/ModuleBase_IViewWindow.h new file mode 100644 index 000000000..fcf763e44 --- /dev/null +++ b/src/ModuleBase/ModuleBase_IViewWindow.h @@ -0,0 +1,20 @@ + + +#ifndef ModuleBase_IViewWindow_H +#define ModuleBase_IViewWindow_H + +#include + + +/** +* Interface to ViewWindow object which contains 3d scene +*/ +class ModuleBase_IViewWindow +{ +public: + /// Returns OCCT object which contains 3d view object + virtual Handle(V3d_View) v3dView() const = 0; +}; + + +#endif \ No newline at end of file diff --git a/src/ModuleBase/ModuleBase_IViewer.h b/src/ModuleBase/ModuleBase_IViewer.h index 3e573d223..c701f6108 100644 --- a/src/ModuleBase/ModuleBase_IViewer.h +++ b/src/ModuleBase/ModuleBase_IViewer.h @@ -9,6 +9,7 @@ class QMouseEvent; class QKeyEvent; class QContextMenuEvent; +class ModuleBase_IViewWindow; /** * A Base object for definition of connector object to @@ -64,16 +65,18 @@ Q_OBJECT signals: void lastViewClosed(); - void tryCloseView(); - void deleteView(); - void viewCreated(); - void mousePress(QMouseEvent* theEvent); - void mouseRelease(QMouseEvent* theEvent); - void mouseDoubleClick(QMouseEvent* theEvent); - void mouseMove(QMouseEvent* theEvent); - void keyPress(QKeyEvent* theEvent); - void keyRelease(QKeyEvent* theEvent); - void activated(); + void tryCloseView(ModuleBase_IViewWindow* theWnd); + void deleteView(ModuleBase_IViewWindow* theWnd); + void viewCreated(ModuleBase_IViewWindow* theWnd); + void activated(ModuleBase_IViewWindow* theWnd); + + void mousePress(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); + void mouseRelease(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); + void mouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); + void mouseMove(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); + + void keyPress(ModuleBase_IViewWindow* theWnd, QKeyEvent* theEvent); + void keyRelease(ModuleBase_IViewWindow* theWnd, QKeyEvent* theEvent); void selectionChanged(); void contextMenuRequested(QContextMenuEvent*); diff --git a/src/ModuleBase/ModuleBase_IWorkshop.h b/src/ModuleBase/ModuleBase_IWorkshop.h index 12e9aef22..94c1800d1 100644 --- a/src/ModuleBase/ModuleBase_IWorkshop.h +++ b/src/ModuleBase/ModuleBase_IWorkshop.h @@ -50,6 +50,9 @@ Q_OBJECT //! Returns currently active operation virtual ModuleBase_Operation* currentOperation() const = 0; + //! Returns true if the operation with id theId can be started + virtual bool canStartOperation(QString theId) = 0; + //! Returns AIS opbject by data object virtual AISObjectPtr findPresentation(const ObjectPtr& theObject) const = 0; @@ -58,13 +61,30 @@ Q_OBJECT //! Select features clearing previous selection. //! If the list is empty then selection will be cleared - virtual void setSelected(const QList& theFeatures) = 0; + virtual void setSelected(const QObjectPtrList& theFeatures) = 0; signals: void selectionChanged(); - void operationStarted(ModuleBase_Operation*); - void operationStopped(ModuleBase_Operation*); + /// Signal about an operation is started. It is emitted after the start() of operation is done. + void operationStarted(ModuleBase_Operation* theOperation); + + /// Signal about an operation is stopped. It is emitted after the stop() of operation is done. + /// \param theOperation a stopped operation + void operationStopped(ModuleBase_Operation* theOperation); + + /// Signal about an operation is resumed. It is emitted after the resume() of operation is done. + void operationResumed(ModuleBase_Operation* theOperation); + + /// Emitted when current operation is comitted + void operationComitted(ModuleBase_Operation* theOperation); + + /// Emitted when current operation is aborted + void operationAborted(ModuleBase_Operation* theOperation); + + /// Signal which is emited after activation of property panel + void propertyPanelActivated(); + }; #endif diff --git a/src/ModuleBase/ModuleBase_ModelWidget.h b/src/ModuleBase/ModuleBase_ModelWidget.h index 7e77804ac..af9e6a8cd 100644 --- a/src/ModuleBase/ModuleBase_ModelWidget.h +++ b/src/ModuleBase/ModuleBase_ModelWidget.h @@ -6,6 +6,7 @@ #define MODULEBASE_MODELWIDGET_H #include +#include #include @@ -14,7 +15,6 @@ #include class Config_WidgetAPI; -class ModuleBase_WidgetValue; class QKeyEvent; /**\class ModuleBase_ModelWidget @@ -51,10 +51,14 @@ Q_OBJECT /// Defines if it is supposed that the widget should interact with the viewer. virtual bool isViewerSelector() { return false; } + /// Defines if it is supported to set the value in this widget + /// By default it returns true + virtual bool canSetValue() const { return true; }; + /// Set the given wrapped value to the current widget /// This value should be processed in the widget according to the needs /// \param theValue the wrapped widget value - virtual bool setValue(ModuleBase_WidgetValue* theValue) + virtual bool setSelection(ModuleBase_ViewerPrs theValue) { return false; } @@ -70,6 +74,12 @@ Q_OBJECT /// \return the state whether the widget can accept the focus virtual bool focusTo(); + /// The methiod called when widget is activated + virtual void activate() {} + + /// The methiod called when widget is deactivated + virtual void deactivate() {} + /// Returns the internal parent wiget control, that can be shown anywhere /// \returns the widget virtual QWidget* getControl() const = 0; diff --git a/src/ModuleBase/ModuleBase_Operation.cpp b/src/ModuleBase/ModuleBase_Operation.cpp index c7525d742..89b1957d3 100644 --- a/src/ModuleBase/ModuleBase_Operation.cpp +++ b/src/ModuleBase/ModuleBase_Operation.cpp @@ -9,7 +9,6 @@ #include "ModuleBase_OperationDescription.h" #include "ModuleBase_ModelWidget.h" -#include "ModuleBase_WidgetValueFeature.h" #include "ModuleBase_ViewerPrs.h" #include "ModuleBase_IPropertyPanel.h" #include "ModuleBase_ISelection.h" @@ -30,6 +29,8 @@ #include +#include + #ifdef _DEBUG #include #endif @@ -74,42 +75,21 @@ bool ModuleBase_Operation::isNestedOperationsEnabled() const return true; } -void ModuleBase_Operation::storeCustomValue() -{ - if (!myFeature) { -#ifdef _DEBUG - qDebug() << "ModuleBase_Operation::storeCustom: " << - "trying to store value without opening a transaction."; -#endif - return; - } - - ModuleBase_ModelWidget* aCustom = dynamic_cast(sender()); - if (aCustom) - aCustom->storeValue(); -} - -void ModuleBase_Operation::startOperation() -{ - if (!myIsEditing) - createFeature(); -} +//void ModuleBase_Operation::storeCustomValue() +//{ +// if (!myFeature) { +//#ifdef _DEBUG +// qDebug() << "ModuleBase_Operation::storeCustom: " << +// "trying to store value without opening a transaction."; +//#endif +// return; +// } +// +// ModuleBase_ModelWidget* aCustom = dynamic_cast(sender()); +// if (aCustom) +// aCustom->storeValue(); +//} -void ModuleBase_Operation::stopOperation() -{ -} - -void ModuleBase_Operation::abortOperation() -{ -} - -void ModuleBase_Operation::commitOperation() -{ -} - -void ModuleBase_Operation::afterCommitOperation() -{ -} bool ModuleBase_Operation::canBeCommitted() const { @@ -126,11 +106,10 @@ void ModuleBase_Operation::flushCreated() Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED)); } -FeaturePtr ModuleBase_Operation::createFeature( - const bool theFlushMessage, CompositeFeaturePtr theCompositeFeature) +FeaturePtr ModuleBase_Operation::createFeature(const bool theFlushMessage) { - if (theCompositeFeature) { - myFeature = theCompositeFeature->addFeature(getDescription()->operationId().toStdString()); + if (myParentFeature) { + myFeature = myParentFeature->addFeature(getDescription()->operationId().toStdString()); } else { std::shared_ptr aDoc = document(); myFeature = aDoc->addFeature(getDescription()->operationId().toStdString()); @@ -167,7 +146,7 @@ bool ModuleBase_Operation::hasObject(ObjectPtr theObj) const std::list aResults = aFeature->results(); std::list::const_iterator aIt; for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) { - if ((*aIt) == theObj) + if (theObj == (*aIt)) return true; } } @@ -185,15 +164,24 @@ void ModuleBase_Operation::start() { ModelAPI_Session::get()->startOperation(); + if (!myIsEditing) + createFeature(); + startOperation(); emit started(); } -void ModuleBase_Operation::resume() +void ModuleBase_Operation::postpone() { if (myPropertyPanel) - connect(myPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)), - this, SLOT(onWidgetActivated(ModuleBase_ModelWidget*))); + disconnect(myPropertyPanel, 0, this, 0); + emit postponed(); +} + +void ModuleBase_Operation::resume() +{ + // connect(myPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)), + // this, SLOT(onWidgetActivated(ModuleBase_ModelWidget*))); emit resumed(); } @@ -213,13 +201,10 @@ void ModuleBase_Operation::abort() bool ModuleBase_Operation::commit() { if (canBeCommitted()) { - commitOperation(); - emit committed(); + if (myPropertyPanel) + disconnect(myPropertyPanel, 0, this, 0); - if (myPropertyPanel) - disconnect(myPropertyPanel, 0, this, 0); - - stopOperation(); + commitOperation(); // check whether there are modifications performed during the current operation // in the model // in case if there are no modifications, do not increase the undo/redo stack @@ -228,7 +213,9 @@ bool ModuleBase_Operation::commit() else ModelAPI_Session::get()->abortOperation(); + stopOperation(); emit stopped(); + emit committed(); afterCommitOperation(); return true; @@ -255,14 +242,18 @@ bool ModuleBase_Operation::activateByPreselection() ModuleBase_ModelWidget* aWgt, *aFilledWgt = 0; QList::const_iterator aWIt; - QList::const_iterator aPIt; + QList::const_iterator aPIt; bool isSet = false; for (aWIt = aWidgets.constBegin(), aPIt = myPreSelection.constBegin(); (aWIt != aWidgets.constEnd()) && (aPIt != myPreSelection.constEnd()); - ++aWIt, ++aPIt) { + ++aWIt) { aWgt = (*aWIt); - ModuleBase_WidgetValueFeature* aValue = (*aPIt); - if (!aWgt->setValue(aValue)) { + ModuleBase_ViewerPrs aValue = (*aPIt); + if (!aWgt->canSetValue()) + continue; + + ++aPIt; + if (!aWgt->setSelection(aValue)) { isSet = false; break; } else { @@ -271,8 +262,9 @@ bool ModuleBase_Operation::activateByPreselection() } } if (isSet && canBeCommitted()) { - // if all widgets are filled with selection - commit(); + // if all widgets are filled with selection - commit + // in order to commit the operation outside of starting procedure - use timer event + QTimer::singleShot(50, this, SLOT(commit())); return true; } else { @@ -282,18 +274,6 @@ bool ModuleBase_Operation::activateByPreselection() return true; } } - - //ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget(); - //if ((myPreSelection.size() > 0) && aActiveWgt) { - // const ModuleBase_ViewerPrs& aPrs = myPreSelection.first(); - // ModuleBase_WidgetValueFeature aValue; - // aValue.setObject(aPrs.object()); - // if (aActiveWgt->setValue(&aValue)) { - // myPreSelection.removeOne(aPrs); - // myPropertyPanel->activateNextWidget(); - // } - // // If preselection is enough to make a valid feature - apply it immediately - //} return false; } @@ -309,7 +289,7 @@ void ModuleBase_Operation::initSelection(ModuleBase_ISelection* theSelection, QList aSelected = theSelection->getSelected(); std::list aResults = aFeature->results(); - QList aResList; + QObjectPtrList aResList; std::list::const_iterator aIt; for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) aResList.append(*aIt); @@ -323,41 +303,42 @@ void ModuleBase_Operation::initSelection(ModuleBase_ISelection* theSelection, // convert the selection values to the values, which are set to the operation widgets - Handle(V3d_View) aView = theViewer->activeView(); - foreach (ModuleBase_ViewerPrs aPrs, aPreSelected) { - ModuleBase_WidgetValueFeature* aValue = new ModuleBase_WidgetValueFeature(); - aValue->setObject(aPrs.object()); + //Handle(V3d_View) aView = theViewer->activeView(); + //foreach (ModuleBase_ViewerPrs aPrs, aPreSelected) { + // ModuleBase_WidgetValueFeature* aValue = new ModuleBase_WidgetValueFeature(); + // aValue->setObject(aPrs.object()); - double aX, anY; - if (getViewerPoint(aPrs, theViewer, aX, anY)) - aValue->setPoint(std::shared_ptr(new GeomAPI_Pnt2d(aX, anY))); - myPreSelection.append(aValue); - } -} - -void ModuleBase_Operation::onWidgetActivated(ModuleBase_ModelWidget* theWidget) -{ - //activateByPreselection(); - //if (theWidget && myPropertyPanel) { - // myPropertyPanel->activateNextWidget(); - //// //emit activateNextWidget(myActiveWidget); + // double aX, anY; + // if (getViewerPoint(aPrs, theViewer, aX, anY)) + // aValue->setPoint(std::shared_ptr(new GeomAPI_Pnt2d(aX, anY))); + // myPreSelection.append(aValue); //} + myPreSelection = aPreSelected; } -bool ModuleBase_Operation::setWidgetValue(ObjectPtr theFeature, double theX, double theY) -{ - ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget(); - if (!aActiveWgt) - return false; - ModuleBase_WidgetValueFeature* aValue = new ModuleBase_WidgetValueFeature(); - aValue->setObject(theFeature); - aValue->setPoint(std::shared_ptr(new GeomAPI_Pnt2d(theX, theY))); - bool isApplyed = aActiveWgt->setValue(aValue); - - delete aValue; - myIsModified = (myIsModified || isApplyed); - return isApplyed; -} +//void ModuleBase_Operation::onWidgetActivated(ModuleBase_ModelWidget* theWidget) +//{ +// //activateByPreselection(); +// //if (theWidget && myPropertyPanel) { +// // myPropertyPanel->activateNextWidget(); +// //// //emit activateNextWidget(myActiveWidget); +// //} +//} + +//bool ModuleBase_Operation::setWidgetValue(ObjectPtr theFeature, double theX, double theY) +//{ +// ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget(); +// if (!aActiveWgt) +// return false; +// ModuleBase_WidgetValueFeature* aValue = new ModuleBase_WidgetValueFeature(); +// aValue->setObject(theFeature); +// aValue->setPoint(std::shared_ptr(new GeomAPI_Pnt2d(theX, theY))); +// bool isApplyed = aActiveWgt->setValue(aValue); +// +// delete aValue; +// myIsModified = (myIsModified || isApplyed); +// return isApplyed; +//} bool ModuleBase_Operation::getViewerPoint(ModuleBase_ViewerPrs thePrs, ModuleBase_IViewer* theViewer, @@ -368,14 +349,18 @@ bool ModuleBase_Operation::getViewerPoint(ModuleBase_ViewerPrs thePrs, void ModuleBase_Operation::clearPreselection() { - while (!myPreSelection.isEmpty()) { - delete myPreSelection.takeFirst(); - } + myPreSelection.clear(); } void ModuleBase_Operation::setPropertyPanel(ModuleBase_IPropertyPanel* theProp) { myPropertyPanel = theProp; - connect(myPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)), this, - SLOT(onWidgetActivated(ModuleBase_ModelWidget*))); + myPropertyPanel->setEditingMode(isEditOperation()); + //connect(myPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)), this, + // SLOT(onWidgetActivated(ModuleBase_ModelWidget*))); } + +bool ModuleBase_Operation::isGranted(QString theId) const +{ + return myNestedFeatures.contains(theId); +} \ No newline at end of file diff --git a/src/ModuleBase/ModuleBase_Operation.h b/src/ModuleBase/ModuleBase_Operation.h index f1b0ae218..acefc9ee8 100644 --- a/src/ModuleBase/ModuleBase_Operation.h +++ b/src/ModuleBase/ModuleBase_Operation.h @@ -23,7 +23,6 @@ class ModuleBase_OperationDescription; class ModuleBase_IPropertyPanel; class ModuleBase_ISelection; class ModuleBase_IViewer; -class ModuleBase_WidgetValueFeature; class QKeyEvent; @@ -65,7 +64,7 @@ Q_OBJECT * the operation is not granted. * The method has to be redefined for granted operations. */ - virtual bool isGranted(ModuleBase_Operation* theOperation) const { return false; } + virtual bool isGranted(QString theId) const; /// Sets a list of model widgets, according to the operation feature xml definition /// \param theXmlRepresentation an xml feature definition @@ -110,11 +109,11 @@ Q_OBJECT /// Returns True if the current operation works with the given object (feature or result) virtual bool hasObject(ObjectPtr theObj) const; - virtual void keyReleased(const int theKey) {}; + //virtual void keyReleased(const int theKey) {}; /// If operation needs to redisplay its result during operation /// then this method has to return True - virtual bool hasPreview() const { return false; } + //virtual bool hasPreview() const { return false; } /// Initialisation of operation with preliminary selection /// \param theSelected the list of selected presentations @@ -130,12 +129,19 @@ Q_OBJECT /// Activates widgets by preselection if it is accepted virtual bool activateByPreselection(); + /// If the operation works with feature which is sub-feature of another one + /// then this variable has to be initialised by parent feature + /// before operation feature creating + void setParentFeature(CompositeFeaturePtr theParent) { myParentFeature = theParent; } + CompositeFeaturePtr parentFeature() const { return myParentFeature; } + signals: void started(); /// the operation is started void aborted(); /// the operation is aborted void committed(); /// the operation is committed void stopped(); /// the operation is aborted or committed void resumed(); /// the operation is resumed + void postponed(); /// the operation is postponed public slots: /// Starts operation @@ -145,6 +151,10 @@ signals: /// be better to inherit own operator from base one and redefine startOperation method /// instead. void start(); + + /// Deactivates current operation which can be resumed later. + void postpone(); + /// Resumes operation /// Public slot. Verifies whether operation can be started and starts operation. /// This slot is not virtual and cannot be redefined. Redefine startOperation method @@ -152,10 +162,12 @@ signals: /// be better to inherit own operator from base one and redefine startOperation method /// instead. void resume(); + /// Aborts operation /// Public slot. Aborts operation. This slot is not virtual and cannot be redefined. /// Redefine abortOperation method to change behavior of operation instead void abort(); + /// Commits operation /// Public slot. Commits operation. This slot is not virtual and cannot be redefined. /// Redefine commitOperation method to change behavior of operation instead @@ -169,31 +181,35 @@ signals: // Data model methods. /// Stores a custom value in model. - virtual void storeCustomValue(); + //virtual void storeCustomValue(); /// Slots which listen the mode widget activation /// \param theWidget the model widget - virtual void onWidgetActivated(ModuleBase_ModelWidget* theWidget); + //virtual void onWidgetActivated(ModuleBase_ModelWidget* theWidget); protected: /// Virtual method called when operation started (see start() method for more description) /// Default impl calls corresponding slot and commits immediately. - virtual void startOperation(); + virtual void startOperation() {} + + /// Implementation of specific steps on postpone operation + virtual void postponeOperation() {} /// Virtual method called when operation stopped - committed or aborted. - virtual void stopOperation(); + virtual void stopOperation() {} /// Virtual method called when operation aborted (see abort() method for more description) - virtual void abortOperation(); + virtual void abortOperation() {} /// Virtual method called when operation committed (see commit() method for more description) - virtual void commitOperation(); + virtual void commitOperation() {} /// Virtual method called after operation committed (see commit() method for more description) - virtual void afterCommitOperation(); + virtual void afterCommitOperation() {} /// Send update message by loop void flushUpdated(); + /// Send created message by loop void flushCreated(); @@ -201,8 +217,7 @@ signals: /// \param theFlushMessage the flag whether the create message should be flushed /// \param theCompositeFeature the feature that must be used for adding the created object or null /// \returns the created - virtual FeaturePtr createFeature(const bool theFlushMessage = true, - CompositeFeaturePtr theCompositeFeature = CompositeFeaturePtr()); + virtual FeaturePtr createFeature(const bool theFlushMessage = true); /// Verifies whether this operator can be commited. /// \return Returns TRUE if current operation can be committed, e.g. all parameters are filled @@ -216,7 +231,7 @@ signals: /// \param theX the horizontal coordinate /// \param theY the vertical coordinate /// \return true if the point is set - virtual bool setWidgetValue(ObjectPtr theFeature, double theX, double theY); + //virtual bool setWidgetValue(ObjectPtr theFeature, double theX, double theY); /// Return a widget value point by the selection and the viewer position /// The default realization returns false @@ -248,10 +263,16 @@ signals: QStringList myNestedFeatures; /// List of pre-selected object - QList myPreSelection; + QList myPreSelection; /// Access to property panel ModuleBase_IPropertyPanel* myPropertyPanel; + + /// If the operation works with feature which is sub-feature of another one + /// then this variable has to be initialised by parent feature + /// before operation feature creating + CompositeFeaturePtr myParentFeature; + }; #endif diff --git a/src/ModuleBase/ModuleBase_Tools.cpp b/src/ModuleBase/ModuleBase_Tools.cpp index 8df14bdc3..0f57b4c7b 100644 --- a/src/ModuleBase/ModuleBase_Tools.cpp +++ b/src/ModuleBase/ModuleBase_Tools.cpp @@ -3,9 +3,10 @@ // Author: Vitaly Smetannikov #include "ModuleBase_Tools.h" -#include -#include -#include +#include +#include +#include +#include namespace ModuleBase_Tools { @@ -43,4 +44,58 @@ void zeroMargins(QLayout* theLayout) theLayout->setSpacing(5); } +QPixmap composite(const QString& theAdditionalIcon, const int theXShift, + const int theYShift, const QString& theIcon) +{ + QImage anIcon(theIcon); + QImage anAditional(theAdditionalIcon); + + if (anIcon.isNull()) + return QPixmap(); + + int anAddWidth = anAditional.width(); + int anAddHeight = anAditional.height(); + + int aWidth = anIcon.width(); + int aHeight = anIcon.height(); + + int aStartWidthPos = aWidth-anAddWidth-1; + int aStartHeightPos = aHeight-anAddHeight-1; + + for (int i = 0; i < anAddWidth; i++) + { + for (int j = 0; j < anAddHeight; j++) + { + if (qAlpha(anAditional.pixel(i, j)) > 0) + anIcon.setPixel(i + aStartWidthPos, j + aStartHeightPos, anAditional.pixel(i, j)); + } + } + return QPixmap::fromImage(anIcon); } + +QPixmap lighter(const QString& theIcon, const int theLighterValue) +{ + QImage anIcon(theIcon); + if (anIcon.isNull()) + return QPixmap(); + + QImage aResult(theIcon); + for ( int i = 0; i < anIcon.width(); i++ ) + { + for ( int j = 0; j < anIcon.height(); j++ ) + { + QRgb anRgb = anIcon.pixel( i, j ); + QColor aPixelColor(qRed(anRgb), qGreen(anRgb), qBlue(anRgb), + qAlpha( aResult.pixel( i, j ) )); + + QColor aLighterColor = aPixelColor.lighter(theLighterValue); + aResult.setPixel(i, j, qRgba( aLighterColor.red(), aLighterColor.green(), + aLighterColor.blue(), aLighterColor.alpha() ) ); + } + } + return QPixmap::fromImage(aResult); +} + +} + + diff --git a/src/ModuleBase/ModuleBase_Tools.h b/src/ModuleBase/ModuleBase_Tools.h index 6c903d3fb..3f9ca0219 100644 --- a/src/ModuleBase/ModuleBase_Tools.h +++ b/src/ModuleBase/ModuleBase_Tools.h @@ -7,10 +7,10 @@ #include "ModuleBase.h" -#include -#include +#include -class GeomAPI_Shape; +class QWidget; +class QLayout; namespace ModuleBase_Tools { @@ -23,6 +23,32 @@ MODULEBASE_EXPORT void adjustMargins(QLayout* theLayout); MODULEBASE_EXPORT void zeroMargins(QWidget* theWidget); MODULEBASE_EXPORT void zeroMargins(QLayout* theLayout); + +/** + * Methods to modify a resource pixmap + */ +//! Create composite pixmap. +//! Pixmap \a theAdditionalIcon is drawn over pixmap \a dest with coordinates +//! specified relatively to the upper left corner of \a theIcon. + +//! \param theAdditionalIcon resource text of the additional pixmap +//! \param theXShift horizontal shift +//! \param theYShift vertical shift +//! \param theIcon resource text of the background pixmap +//! \return resulting pixmap +MODULEBASE_EXPORT QPixmap composite(const QString& theAdditionalIcon, const int theXShift, + const int theYShift, const QString& theIcon); + +//! Generates the pixmap lighter than the resources pixmap. +//! Pixmap \a theIcon is lighted according to the given value. +//! If the lighter value is greater than 100, this functions returns a lighter pixmap. +//! Setting lighter value to 150 returns a color that is 50% brighter. If the factor is less than 100, +//! the return pixmap is darker. If the factor is 0 or negative, the return pixmap is unspecified. + +//! \param resource text of the pixmap +//! \param theLighterValue a lighter factor +//! \return resulting pixmap +MODULEBASE_EXPORT QPixmap lighter(const QString& theIcon, const int theLighterValue = 200); } #endif diff --git a/src/ModuleBase/ModuleBase_ViewerFilters.cpp b/src/ModuleBase/ModuleBase_ViewerFilters.cpp index a7e2cd3f7..94625a480 100644 --- a/src/ModuleBase/ModuleBase_ViewerFilters.cpp +++ b/src/ModuleBase/ModuleBase_ViewerFilters.cpp @@ -37,7 +37,11 @@ Standard_Boolean ModuleBase_ShapeDocumentFilter::IsOk(const Handle(SelectMgr_Ent if (aObj) { DocumentPtr aDoc = aObj->document(); SessionPtr aMgr = ModelAPI_Session::get(); - return (aDoc == aMgr->activeDocument() /* MPV: for the current moment selection in other document is not possible || (aDoc == aMgr->moduleDocument()*/); + return (aDoc == aMgr->activeDocument() || aDoc == aMgr->moduleDocument()); + } + else { + // This is not object controlled by the filter + return Standard_True; } } } @@ -74,6 +78,10 @@ Standard_Boolean ModuleBase_ShapeInPlaneFilter::IsOk(const Handle(SelectMgr_Enti bool aD3 = myPlane.Distance(aLastPnt) < Precision::Confusion(); return aD1 && aD2 && aD3; } + default: + // This is not object controlled by the filter + return Standard_True; + break; } } else { // This is not object controlled by the filter diff --git a/src/ModuleBase/ModuleBase_ViewerFilters.h b/src/ModuleBase/ModuleBase_ViewerFilters.h index e4aa93ae2..4860776f4 100644 --- a/src/ModuleBase/ModuleBase_ViewerFilters.h +++ b/src/ModuleBase/ModuleBase_ViewerFilters.h @@ -44,8 +44,10 @@ DEFINE_STANDARD_HANDLE(ModuleBase_ShapeInPlaneFilter, SelectMgr_Filter); class ModuleBase_ShapeInPlaneFilter: public SelectMgr_Filter { public: - Standard_EXPORT ModuleBase_ShapeInPlaneFilter(const gp_Pln& thePane): - SelectMgr_Filter(), myPlane(thePane) {} + Standard_EXPORT ModuleBase_ShapeInPlaneFilter(): SelectMgr_Filter() {} + + void setPlane(const gp_Pln& thePane) { myPlane = thePane; } + gp_Pln plane() const { return myPlane; } Standard_EXPORT virtual Standard_Boolean IsOk(const Handle(SelectMgr_EntityOwner)& theOwner) const; diff --git a/src/ModuleBase/ModuleBase_WidgetChoice.cpp b/src/ModuleBase/ModuleBase_WidgetChoice.cpp index b2d017db6..9629f0fd2 100644 --- a/src/ModuleBase/ModuleBase_WidgetChoice.cpp +++ b/src/ModuleBase/ModuleBase_WidgetChoice.cpp @@ -81,5 +81,6 @@ QList ModuleBase_WidgetChoice::getControls() const void ModuleBase_WidgetChoice::onCurrentIndexChanged(int theIndex) { emit valuesChanged(); - emit focusOutWidget(this); + // Don't transfer focus + // emit focusOutWidget(this); } diff --git a/src/ModuleBase/ModuleBase_WidgetEditor.cpp b/src/ModuleBase/ModuleBase_WidgetEditor.cpp index ee5bc67f4..6d5f90653 100644 --- a/src/ModuleBase/ModuleBase_WidgetEditor.cpp +++ b/src/ModuleBase/ModuleBase_WidgetEditor.cpp @@ -24,6 +24,7 @@ #include #include #include +#include ModuleBase_WidgetEditor::ModuleBase_WidgetEditor(QWidget* theParent, const Config_WidgetAPI* theData, @@ -60,6 +61,16 @@ double editedValue(double theValue, bool& isDone) bool ModuleBase_WidgetEditor::focusTo() { + // We can not launch here modal process for value editing because + // it can be called on other focusOutWidget event and will block it + QTimer::singleShot(1, this, SLOT(showPopupEditor())); + return true; +} + +void ModuleBase_WidgetEditor::showPopupEditor() +{ + // White while all events will be processed + QApplication::processEvents(); double aValue = mySpinBox->value(); bool isDone; aValue = editedValue(aValue, isDone); @@ -71,8 +82,6 @@ bool ModuleBase_WidgetEditor::focusTo() } emit valuesChanged(); emit focusOutWidget(this); - - return false; } void ModuleBase_WidgetEditor::editFeatureValue(FeaturePtr theFeature, diff --git a/src/ModuleBase/ModuleBase_WidgetEditor.h b/src/ModuleBase/ModuleBase_WidgetEditor.h index 508e5ee53..ded826289 100644 --- a/src/ModuleBase/ModuleBase_WidgetEditor.h +++ b/src/ModuleBase/ModuleBase_WidgetEditor.h @@ -47,6 +47,10 @@ Q_OBJECT /// \param theAttribute the feature attribute static void editFeatureValue(FeaturePtr theFeature, const std::string theAttribute); + private slots: + /// Shous popup window under cursor for data editing + void showPopupEditor(); + private: FeaturePtr myFeature; ///< the current widget feature QStringList myFeatureKinds; ///< the kinds of possible features diff --git a/src/ModuleBase/ModuleBase_WidgetFactory.cpp b/src/ModuleBase/ModuleBase_WidgetFactory.cpp index cc66a69b8..d000e87e0 100644 --- a/src/ModuleBase/ModuleBase_WidgetFactory.cpp +++ b/src/ModuleBase/ModuleBase_WidgetFactory.cpp @@ -9,15 +9,14 @@ #include #include -#include -#include -#include +//#include +//#include #include #include #include #include #include -#include +//#include #include #include #include @@ -25,6 +24,7 @@ #include #include #include +#include #include #include @@ -109,20 +109,16 @@ void ModuleBase_WidgetFactory::createWidget(QWidget* theParent) theParent->setLayout(aWidgetLay); } + QWidget* ModuleBase_WidgetFactory::labelControl(QWidget* theParent) { - QWidget* result = new QWidget(theParent); - QVBoxLayout* aLabelLay = new QVBoxLayout(result); - QLabel* aLabel = new QLabel(result); - aLabel->setWordWrap(true); - aLabel->setText(qs(myWidgetApi->getProperty(INFO_WDG_TEXT))); - aLabel->setToolTip(qs(myWidgetApi->getProperty(INFO_WDG_TOOLTIP))); - aLabelLay->addWidget(aLabel); - aLabelLay->addStretch(1); - result->setLayout(aLabelLay); - return result; + ModuleBase_WidgetLabel* aWgt = + new ModuleBase_WidgetLabel(theParent, myWidgetApi, myParentId); + myModelWidgets.append(aWgt); + return aWgt->getControl(); } + QWidget* ModuleBase_WidgetFactory::createWidgetByType(const std::string& theType, QWidget* theParent) { @@ -139,21 +135,15 @@ QWidget* ModuleBase_WidgetFactory::createWidgetByType(const std::string& theType } else if (theType == WDG_BOOLVALUE) { result = booleanControl(theParent); - } else if (theType == WDG_POINT_SELECTOR) { - result = pointSelectorControl(theParent); + //} else if (theType == WDG_FEATURE_SELECTOR) { + // result = featureSelectorControl(theParent); - } else if (theType == WDG_FEATURE_SELECTOR) { - result = featureSelectorControl(theParent); - - } else if (theType == WDG_FEATURE_OR_ATTRIBUTE_SELECTOR) { - result = featureOrAttributeSelectorControl(theParent); + //} else if (theType == WDG_FEATURE_OR_ATTRIBUTE_SELECTOR) { + // result = featureOrAttributeSelectorControl(theParent); } else if (theType == WDG_DOUBLEVALUE_EDITOR) { result = doubleValueEditor(theParent); - } else if (theType == WDG_POINT2D_DISTANCE) { - result = point2dDistanceControl(theParent); - } else if (theType == WDG_FILE_SELECTOR) { result = fileSelectorControl(theParent); @@ -170,7 +160,7 @@ QWidget* ModuleBase_WidgetFactory::createWidgetByType(const std::string& theType result = createContainer(theType, theParent); } else { result = myWorkshop->module()->createWidgetByType(theType, theParent, myWidgetApi, - myModelWidgets); + myParentId, myModelWidgets); #ifdef _DEBUG if (!result) {qDebug("ModuleBase_WidgetFactory::fillWidget: find bad widget type");} #endif @@ -206,30 +196,6 @@ QWidget* ModuleBase_WidgetFactory::doubleSpinBoxControl(QWidget* theParent) return aDblWgt->getControl(); } -QWidget* ModuleBase_WidgetFactory::pointSelectorControl(QWidget* theParent) -{ - ModuleBase_WidgetPoint2D* aWidget = - new ModuleBase_WidgetPoint2D(theParent, myWidgetApi,myParentId); - myModelWidgets.append(aWidget); - return aWidget->getControl(); -} - -QWidget* ModuleBase_WidgetFactory::featureSelectorControl(QWidget* theParent) -{ - ModuleBase_WidgetFeature* aWidget = - new ModuleBase_WidgetFeature(theParent, myWidgetApi,myParentId); - myModelWidgets.append(aWidget); - return aWidget->getControl(); -} - -QWidget* ModuleBase_WidgetFactory::featureOrAttributeSelectorControl(QWidget* theParent) -{ - ModuleBase_WidgetFeatureOrAttribute* aWidget = - new ModuleBase_WidgetFeatureOrAttribute(theParent, myWidgetApi, myParentId); - myModelWidgets.append(aWidget); - return aWidget->getControl(); -} - QWidget* ModuleBase_WidgetFactory::doubleValueEditor(QWidget* theParent) { ModuleBase_WidgetEditor* aWidget = @@ -254,14 +220,6 @@ QWidget* ModuleBase_WidgetFactory::booleanControl(QWidget* theParent) return aBoolWgt->getControl(); } -QWidget* ModuleBase_WidgetFactory::point2dDistanceControl(QWidget* theParent) -{ - ModuleBase_WidgetPoint2dDistance* aDistWgt = - new ModuleBase_WidgetPoint2dDistance(theParent, myWidgetApi, myParentId); - myModelWidgets.append(aDistWgt); - return aDistWgt->getControl(); -} - QWidget* ModuleBase_WidgetFactory::fileSelectorControl(QWidget* theParent) { ModuleBase_WidgetFileSelector* aFileSelectorWgt = @@ -298,3 +256,4 @@ QString ModuleBase_WidgetFactory::qs(const std::string& theStdString) const { return QString::fromStdString(theStdString); } + diff --git a/src/ModuleBase/ModuleBase_WidgetFactory.h b/src/ModuleBase/ModuleBase_WidgetFactory.h index fd267d418..581e67cba 100644 --- a/src/ModuleBase/ModuleBase_WidgetFactory.h +++ b/src/ModuleBase/ModuleBase_WidgetFactory.h @@ -39,13 +39,9 @@ class MODULEBASE_EXPORT ModuleBase_WidgetFactory QWidget* createContainer(const std::string& theType, QWidget* theParent = NULL); QWidget* labelControl(QWidget* theParent); QWidget* doubleSpinBoxControl(QWidget* theParent); - QWidget* pointSelectorControl(QWidget* theParent); - QWidget* featureSelectorControl(QWidget* theParent); - QWidget* featureOrAttributeSelectorControl(QWidget* theParent); QWidget* doubleValueEditor(QWidget* theParent); QWidget* shapeSelectorControl(QWidget* theParent); QWidget* booleanControl(QWidget* theParent); - QWidget* point2dDistanceControl(QWidget* theParent); QWidget* fileSelectorControl(QWidget* theParent); QWidget* choiceControl(QWidget* theParent); QWidget* lineEditControl(QWidget* theParent); diff --git a/src/ModuleBase/ModuleBase_WidgetFeature.cpp b/src/ModuleBase/ModuleBase_WidgetFeature.cpp deleted file mode 100644 index 3b28aeb6a..000000000 --- a/src/ModuleBase/ModuleBase_WidgetFeature.cpp +++ /dev/null @@ -1,160 +0,0 @@ -// File: ModuleBase_WidgetFeature.cpp -// Created: 25 Apr 2014 -// Author: Natalia ERMOLAEVA - -#include - -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -ModuleBase_WidgetFeature::ModuleBase_WidgetFeature(QWidget* theParent, - const Config_WidgetAPI* theData, - const std::string& theParentId) - : ModuleBase_ModelWidget(theParent, theData, theParentId) -{ - myContainer = new QWidget(theParent); - QHBoxLayout* aControlLay = new QHBoxLayout(myContainer); - ModuleBase_Tools::adjustMargins(aControlLay); - - QString aLabelText = QString::fromStdString(theData->widgetLabel()); - myLabel = new QLabel(aLabelText, myContainer); - aControlLay->addWidget(myLabel); - - myEditor = new QLineEdit(myContainer); - QString anObjName = QString::fromStdString(attributeID()); - myEditor->setObjectName(anObjName); - myEditor->setReadOnly(true); - aControlLay->addWidget(myEditor); - - QString aTTip = QString::fromStdString(theData->widgetTooltip()); - myEditor->setToolTip(aTTip); - aControlLay->addWidget(myEditor); - aControlLay->setStretch(1, 1); -} - -ModuleBase_WidgetFeature::~ModuleBase_WidgetFeature() -{ -} - -bool ModuleBase_WidgetFeature::setValue(ModuleBase_WidgetValue* theValue) -{ - bool isDone = false; - - if (theValue) { - ModuleBase_WidgetValueFeature* aFeatureValue = - dynamic_cast(theValue); - if (aFeatureValue) - isDone = setObject(aFeatureValue->object()); - } - return isDone; -} - -bool ModuleBase_WidgetFeature::setObject(const ObjectPtr& theObject, bool theSendEvent) -{ - SessionPtr aMgr = ModelAPI_Session::get(); - ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); - std::list aValidators; - std::list > anArguments; - aFactory->validators(parentID(), attributeID(), aValidators, anArguments); - - // Check the type of selected object - std::list::iterator aValidator = aValidators.begin(); - bool isValid = true; - for (; aValidator != aValidators.end(); aValidator++) { - const ModelAPI_ResultValidator* aResValidator = - dynamic_cast(*aValidator); - if (aResValidator) { - isValid = false; - if (aResValidator->isValid(theObject)) { - isValid = true; - break; - } - } - } - if (!isValid) - return false; - - // Check the acceptability of the object as attribute - aValidator = aValidators.begin(); - std::list >::iterator aArgs = anArguments.begin(); - for (; aValidator != aValidators.end(); aValidator++, aArgs++) { - const ModelAPI_RefAttrValidator* aAttrValidator = - dynamic_cast(*aValidator); - if (aAttrValidator) { - if (!aAttrValidator->isValid(myFeature, *aArgs, theObject)) { - return false; - } - } - } - - myObject = theObject; - myEditor->setText(theObject ? theObject->data()->name().c_str() : ""); - if (theSendEvent) - emit valuesChanged(); - return true; -} - -bool ModuleBase_WidgetFeature::storeValue() const -{ - //FeaturePtr aFeature = std::dynamic_pointer_cast(theObject); - if (!myObject) - return false; - - std::shared_ptr aData = myFeature->data(); - std::shared_ptr aRef = std::dynamic_pointer_cast< - ModelAPI_AttributeRefAttr>(aData->attribute(attributeID())); - - ModuleBase_WidgetFeature* that = (ModuleBase_WidgetFeature*) this; - aRef->setObject(myObject); - myFeature->execute(); - updateObject(myFeature); - return true; -} - -bool ModuleBase_WidgetFeature::restoreValue() -{ - std::shared_ptr aData = myFeature->data(); - std::shared_ptr aRef = std::dynamic_pointer_cast< - ModelAPI_AttributeRefAttr>(aData->attribute(attributeID())); - - ObjectPtr anObjPtr = aRef->object(); - if (anObjPtr) { - myObject = anObjPtr; - myEditor->setText(myObject ? myObject->data()->name().c_str() : ""); - return true; - } - return false; -} - -QWidget* ModuleBase_WidgetFeature::getControl() const -{ - return myContainer; -} - -QList ModuleBase_WidgetFeature::getControls() const -{ - QList aList; - aList.append(myEditor); - return aList; -} diff --git a/src/ModuleBase/ModuleBase_WidgetFeature.h b/src/ModuleBase/ModuleBase_WidgetFeature.h deleted file mode 100644 index ec7413654..000000000 --- a/src/ModuleBase/ModuleBase_WidgetFeature.h +++ /dev/null @@ -1,96 +0,0 @@ -// File: ModuleBase_WidgetFeature.h -// Created: 25 Apr 2014 -// Author: Natalia ERMOLAEVA - -#ifndef ModuleBase_WidgetFeature_H -#define ModuleBase_WidgetFeature_H - -#include -#include "ModuleBase_ModelWidget.h" - -#include -#include - -class ModuleBase_WidgetValue; -class ModelAPI_Feature; -class QWidget; -class QLabel; -class QLineEdit; -class QToolButton; - -/**\class ModuleBase_WidgetFeature - * \ingroup GUI - * \brief Custom widget. An abstract class to be redefined to fill with some GUI controls - */ -class MODULEBASE_EXPORT ModuleBase_WidgetFeature : public ModuleBase_ModelWidget -{ -Q_OBJECT - public: - /// Constructor - /// \theParent the parent object - /// \theParent the parent object - /// \theData the widget configuation. The attribute of the model widget is obtained from - ModuleBase_WidgetFeature(QWidget* theParent, const Config_WidgetAPI* theData, - const std::string& theParentId); - /// Destructor - virtual ~ModuleBase_WidgetFeature(); - - /// Set the given wrapped value to the current widget - /// This value should be processed in the widget according to the needs - /// \param theValue the wrapped widget value - virtual bool setValue(ModuleBase_WidgetValue* theValue); - - /// Saves the internal parameters to the given feature - /// \param theFeature a model feature to be changed - virtual bool storeValue() const; - - virtual bool restoreValue(); - - /// Returns the internal parent wiget control, that can be shown anywhere - /// \returns the widget - QWidget* getControl() const; - - /// Returns list of widget controls - /// \return a control list - virtual QList getControls() const; - /// Defines if it is supposed that the widget should interact with the viewer. - virtual bool isViewerSelector() { return true; } - - protected: - /// Fill the widget values by given point - /// \param thePoint the point - /// \return the boolean result of the feature set - bool setObject(const ObjectPtr& theObject, bool theSendEvent = true); - - /// Returns current widget feature - /// \return the feature - const ObjectPtr object() const - { - return myObject; - } - - /// Returns the widget editor - /// \return the editor - QLineEdit* editor() const - { - return myEditor; - } - - /// Returns the possible feature kinds - /// \return the list of kinds - const QStringList& featureKinds() const - { - return myObjectKinds; - } - - protected: - ObjectPtr myObject; ///< the current widget feature - QStringList myObjectKinds; ///< the kinds of possible features - - private: - QWidget* myContainer; /// the parent top control - QLabel* myLabel; /// the editor information label - QLineEdit* myEditor; ///< the feature editor to visualize the feature name -}; - -#endif diff --git a/src/ModuleBase/ModuleBase_WidgetFeatureOrAttribute.cpp b/src/ModuleBase/ModuleBase_WidgetFeatureOrAttribute.cpp deleted file mode 100644 index 9c052588d..000000000 --- a/src/ModuleBase/ModuleBase_WidgetFeatureOrAttribute.cpp +++ /dev/null @@ -1,179 +0,0 @@ -// File: ModuleBase_WidgetFeatureOrAttribute.cpp -// Created: 25 Apr 2014 -// Author: Natalia ERMOLAEVA - -#include - -#include -#include - -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include - -#include - -#include -#include -#include -#include - -ModuleBase_WidgetFeatureOrAttribute::ModuleBase_WidgetFeatureOrAttribute(QWidget* theParent, - const Config_WidgetAPI* theData, - const std::string& theParentId) - : ModuleBase_WidgetFeature(theParent, theData, theParentId) -{ -} - -ModuleBase_WidgetFeatureOrAttribute::~ModuleBase_WidgetFeatureOrAttribute() -{ -} - -bool ModuleBase_WidgetFeatureOrAttribute::setValue(ModuleBase_WidgetValue* theValue) -{ - bool isDone = false; - - if (theValue) { - ModuleBase_WidgetValueFeature* aFeatureValue = - dynamic_cast(theValue); - if (aFeatureValue) { - ObjectPtr aObject = aFeatureValue->object(); - - std::shared_ptr anAttribute = findAttribute(aFeatureValue); - if (anAttribute) { - isDone = setAttribute(anAttribute, false); - } - else if (aObject) { - isDone = setObject(aObject, false); - } - - if (isDone) - emit valuesChanged(); - } - } - return isDone; -} - -bool ModuleBase_WidgetFeatureOrAttribute::storeValue() const -{ - //FeaturePtr aFeature = std::dynamic_pointer_cast(theFeature); - //if (!aFeature) - // return false; - - std::shared_ptr aData = myFeature->data(); - std::shared_ptr aRef = std::dynamic_pointer_cast< - ModelAPI_AttributeRefAttr>(aData->attribute(attributeID())); - - if (myObject) - aRef->setObject(myObject); - if (myAttribute) - aRef->setAttr(myAttribute); - - myFeature->execute(); - updateObject(myFeature); - - return true; -} - -bool ModuleBase_WidgetFeatureOrAttribute::restoreValue() -{ - std::shared_ptr aData = myFeature->data(); - std::shared_ptr aRef = std::dynamic_pointer_cast< - ModelAPI_AttributeRefAttr>(aData->attribute(attributeID())); - - ObjectPtr aObj = aRef->object(); - FeaturePtr aFeature = ModelAPI_Feature::feature(aRef->object()); - if (aFeature) { - myObject = aFeature; - myAttribute = aRef->attr(); - - std::string aText = ""; - if (aFeature) - aText = aFeature->data()->name().c_str(); - if (myAttribute) - aText = myAttribute->attributeType().c_str(); - - editor()->setText(aText.c_str()); - return true; - } - return false; -} - -std::shared_ptr ModuleBase_WidgetFeatureOrAttribute::findAttribute( - ModuleBase_WidgetValue* theValue) -{ - std::shared_ptr anAttribute; - ModuleBase_WidgetValueFeature* aFeatureValue = - dynamic_cast(theValue); - if (!aFeatureValue) - return anAttribute; - - std::shared_ptr aValuePoint = aFeatureValue->point(); - if (aValuePoint) { - ObjectPtr aObject = aFeatureValue->object(); - FeaturePtr aFeature = ModelAPI_Feature::feature(aObject); - if (aFeature) { - // find the given point in the feature attributes - std::list > anAttiributes = aFeature->data() - ->attributes(GeomDataAPI_Point2D::type()); - std::list >::const_iterator anIt = anAttiributes - .begin(), aLast = anAttiributes.end(); - for (; anIt != aLast && !anAttribute; anIt++) { - std::shared_ptr aCurPoint = std::dynamic_pointer_cast< - GeomDataAPI_Point2D>(*anIt); - if (aCurPoint && aCurPoint->pnt()->distance(aValuePoint) < Precision::Confusion()) - anAttribute = aCurPoint; - } - } - } - return anAttribute; -} - -bool ModuleBase_WidgetFeatureOrAttribute::setAttribute( - const std::shared_ptr& theAttribute, bool theSendEvent) -{ - if (!theAttribute) // || !featureKinds().contains(theAttribute->attributeType().c_str())) - return false; - - SessionPtr aMgr = ModelAPI_Session::get(); - ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); - std::list aValidators; - std::list > anArguments; - aFactory->validators(parentID(), attributeID(), aValidators, anArguments); - - // Check the acceptability of the attribute - std::list::iterator aValidator = aValidators.begin(); - int aSize = aValidators.size(); - std::list >::iterator aArgs = anArguments.begin(); - for (; aValidator != aValidators.end(); aValidator++, aArgs++) { - const ModelAPI_RefAttrValidator* aAttrValidator = - dynamic_cast(*aValidator); - if (aAttrValidator) { - if (!aAttrValidator->isValid(myFeature, *aArgs, theAttribute)) { - return false; - } - } - } - - myAttribute = theAttribute; - editor()->setText(theAttribute ? theAttribute->attributeType().c_str() : ""); - if (theSendEvent) - emit valuesChanged(); - return true; -} - diff --git a/src/ModuleBase/ModuleBase_WidgetFeatureOrAttribute.h b/src/ModuleBase/ModuleBase_WidgetFeatureOrAttribute.h deleted file mode 100644 index 5fac25197..000000000 --- a/src/ModuleBase/ModuleBase_WidgetFeatureOrAttribute.h +++ /dev/null @@ -1,62 +0,0 @@ -// File: ModuleBase_WidgetFeatureOrAttribute.h -// Created: 25 Apr 2014 -// Author: Natalia ERMOLAEVA - -#ifndef ModuleBase_WidgetFeatureOrAttribute_H -#define ModuleBase_WidgetFeatureOrAttribute_H - -#include -#include "ModuleBase_WidgetFeature.h" - -#include - -class ModuleBase_WidgetValue; -class ModelAPI_Attribute; - -/**\class ModuleBase_WidgetFeatureOrAttribute - * \ingroup GUI - * \brief Custom widget. An abstract class to be redefined to fill with some GUI controls - */ -class MODULEBASE_EXPORT ModuleBase_WidgetFeatureOrAttribute : public ModuleBase_WidgetFeature -{ -Q_OBJECT - public: - /// Constructor - /// \theParent the parent object - /// \theParent the parent object - /// \theData the widget configuation. The attribute of the model widget is obtained from - ModuleBase_WidgetFeatureOrAttribute(QWidget* theParent, const Config_WidgetAPI* theData, - const std::string& theParentId); - /// Destructor - virtual ~ModuleBase_WidgetFeatureOrAttribute(); - - /// Set the given wrapped value to the current widget - /// This value should be processed in the widget according to the needs - /// \param theValue the wrapped widget value - virtual bool setValue(ModuleBase_WidgetValue* theValue); - - /// Saves the internal parameters to the given feature - /// \param theFeature a model feature to be changed - virtual bool storeValue() const; - - virtual bool restoreValue(); - /// Defines if it is supposed that the widget should interact with the viewer. - virtual bool isViewerSelector() { return true; } - - protected: - /// Returns the feature attribute if it can be found by the given value - /// \param theValue the widget value - /// \return an attribute or null - std::shared_ptr findAttribute(ModuleBase_WidgetValue* theValue); - - /// Set the attribute - /// \param theAttribute value - /// \return the boolean result of the attribute set - bool setAttribute(const std::shared_ptr& theAttribute, bool theSendEvent = - true); - - protected: - std::shared_ptr myAttribute; /// < the attribute -}; - -#endif diff --git a/src/ModuleBase/ModuleBase_WidgetLabel.cpp b/src/ModuleBase/ModuleBase_WidgetLabel.cpp new file mode 100644 index 000000000..e5b090be6 --- /dev/null +++ b/src/ModuleBase/ModuleBase_WidgetLabel.cpp @@ -0,0 +1,35 @@ +// File: ModuleBase_WidgetLabel.cpp +// Created: 03 Dec 2014 +// Author: Vitaly SMETANNIKOV + +#include "ModuleBase_WidgetLabel.h" + +#include + +#include + + +ModuleBase_WidgetLabel::ModuleBase_WidgetLabel(QWidget* theParent, + const Config_WidgetAPI* theData, + const std::string& theParentId) + : ModuleBase_ModelWidget(theParent, theData, theParentId) +{ + QString aText = QString::fromStdString(theData->getProperty("title")); + myLabel = new QLabel(aText, theParent); + myLabel->setWordWrap(true); + myLabel->setIndent(5); +} + +ModuleBase_WidgetLabel::~ModuleBase_WidgetLabel() +{ +} + +QList ModuleBase_WidgetLabel::getControls() const +{ + return QList(); +} + +QWidget* ModuleBase_WidgetLabel::getControl() const +{ + return myLabel; +} diff --git a/src/ModuleBase/ModuleBase_WidgetLabel.h b/src/ModuleBase/ModuleBase_WidgetLabel.h new file mode 100644 index 000000000..7935316da --- /dev/null +++ b/src/ModuleBase/ModuleBase_WidgetLabel.h @@ -0,0 +1,47 @@ +// File: ModuleBase_WidgetLabel.h +// Created: 03 Dec 2014 +// Author: Vitaly SMETANNIKOV + +#ifndef ModuleBase_WidgetLabel_H +#define ModuleBase_WidgetLabel_H + +#include "ModuleBase.h" +#include "ModuleBase_ModelWidget.h" + +class QLabel; + +class MODULEBASE_EXPORT ModuleBase_WidgetLabel : public ModuleBase_ModelWidget +{ +Q_OBJECT + public: + ModuleBase_WidgetLabel(QWidget* theParent, const Config_WidgetAPI* theData, + const std::string& theParentId); + + virtual ~ModuleBase_WidgetLabel(); + + /// Defines if it is supported to set the value in this widget + /// It returns false because this is an info widget + virtual bool canSetValue() const { return false; }; + + virtual bool storeValue() const + { + return true; + } + + virtual bool restoreValue() + { + return true; + } + + virtual QList getControls() const; + + QWidget* getControl() const; + + /// This control doesn't accept focus + virtual bool focusTo() { return false; } + +private: + QLabel* myLabel; +}; + +#endif \ No newline at end of file diff --git a/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp b/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp index ea21968a1..34d5d8a8e 100644 --- a/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp +++ b/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp @@ -54,9 +54,10 @@ ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParen myListControl = new QListWidget(myMainWidget); aMainLay->addWidget(myListControl, 2, 0, 2, -1); - aMainLay->setColumnStretch(1, 1); + aMainLay->setRowStretch(2, 1); + aMainLay->addWidget(new QLabel(myMainWidget)); + aMainLay->setRowMinimumHeight(3, 20); myMainWidget->setLayout(aMainLay); - //TODO: Move into the base class myUseSubShapes = theData->getBooleanAttribute("use_subshapes", false); //TODO_END @@ -163,7 +164,7 @@ void ModuleBase_WidgetMultiSelector::activateSelection(bool toActivate) void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged() { activateShapeSelection(); - QList anEmptyList; + QObjectPtrList anEmptyList; myWorkshop->setSelected(anEmptyList); // Clear mySelection, myListControl and storeValue() onSelectionChanged(); diff --git a/src/ModuleBase/ModuleBase_WidgetPoint2D.cpp b/src/ModuleBase/ModuleBase_WidgetPoint2D.cpp deleted file mode 100644 index 130870221..000000000 --- a/src/ModuleBase/ModuleBase_WidgetPoint2D.cpp +++ /dev/null @@ -1,177 +0,0 @@ -// File: ModuleBase_WidgetPoint2D.cpp -// Created: 25 Apr 2014 -// Author: Natalia ERMOLAEVA - -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -ModuleBase_WidgetPoint2D::ModuleBase_WidgetPoint2D(QWidget* theParent, - const Config_WidgetAPI* theData, - const std::string& theParentId) - : ModuleBase_ModelWidget(theParent, theData, theParentId) -{ - myOptionParam = theData->getProperty(PREVIOUS_FEATURE_PARAM); - QString aPageName = QString::fromStdString(theData->getProperty(CONTAINER_PAGE_NAME)); - myGroupBox = new QGroupBox(aPageName, theParent); - myGroupBox->setFlat(false); - - QGridLayout* aGroupLay = new QGridLayout(myGroupBox); - ModuleBase_Tools::adjustMargins(aGroupLay); - aGroupLay->setColumnStretch(1, 1); - { - QLabel* aLabel = new QLabel(myGroupBox); - aLabel->setText("X"); - aLabel->setPixmap(QPixmap(":pictures/x_point.png")); - aGroupLay->addWidget(aLabel, 0, 0); - - myXSpin = new ModuleBase_DoubleSpinBox(myGroupBox); - myXSpin->setMinimum(-DBL_MAX); - myXSpin->setMaximum(DBL_MAX); - myXSpin->setToolTip("X"); - aGroupLay->addWidget(myXSpin, 0, 1); - - connect(myXSpin, SIGNAL(valueChanged(double)), this, SIGNAL(valuesChanged())); - } - { - QLabel* aLabel = new QLabel(myGroupBox); - aLabel->setText("Y"); - aLabel->setPixmap(QPixmap(":pictures/y_point.png")); - aGroupLay->addWidget(aLabel, 1, 0); - - myYSpin = new ModuleBase_DoubleSpinBox(myGroupBox); - myYSpin->setMinimum(-DBL_MAX); - myYSpin->setMaximum(DBL_MAX); - myYSpin->setToolTip("X"); - aGroupLay->addWidget(myYSpin, 1, 1); - - connect(myYSpin, SIGNAL(valueChanged(double)), this, SIGNAL(valuesChanged())); - } -} - -ModuleBase_WidgetPoint2D::~ModuleBase_WidgetPoint2D() -{ -} - -bool ModuleBase_WidgetPoint2D::setValue(ModuleBase_WidgetValue* theValue) -{ - bool isDone = false; - if (theValue) { - ModuleBase_WidgetValueFeature* aFeatureValue = - dynamic_cast(theValue); - if (aFeatureValue) { - std::shared_ptr aPoint = aFeatureValue->point(); - if (aPoint) { - setPoint(aPoint); - isDone = true; - } - } - } - return isDone; -} - -void ModuleBase_WidgetPoint2D::setPoint(const std::shared_ptr& thePoint) -{ - - bool isBlocked = this->blockSignals(true); - myXSpin->setValue(thePoint->x()); - myYSpin->setValue(thePoint->y()); - this->blockSignals(isBlocked); - - emit valuesChanged(); -} - -bool ModuleBase_WidgetPoint2D::storeValue() const -{ - std::shared_ptr aData = myFeature->data(); - std::shared_ptr aPoint = std::dynamic_pointer_cast( - aData->attribute(attributeID())); - - ModuleBase_WidgetPoint2D* that = (ModuleBase_WidgetPoint2D*) this; - bool isBlocked = that->blockSignals(true); - bool isImmutable = aPoint->setImmutable(true); -#ifdef _DEBUG - std::string _attr_name = myAttributeID; - double _X = myXSpin->value(); - double _Y = myYSpin->value(); -#endif - aPoint->setValue(myXSpin->value(), myYSpin->value()); - updateObject(myFeature); - aPoint->setImmutable(isImmutable); - that->blockSignals(isBlocked); - - return true; -} - -bool ModuleBase_WidgetPoint2D::restoreValue() -{ - std::shared_ptr aData = myFeature->data(); - std::shared_ptr aPoint = std::dynamic_pointer_cast( - aData->attribute(attributeID())); - -#ifdef _DEBUG - std::string _attr_name = myAttributeID; - double _X = aPoint->x(); - double _Y = aPoint->y(); -#endif - bool isBlocked = this->blockSignals(true); - myXSpin->setValue(aPoint->x()); - myYSpin->setValue(aPoint->y()); - this->blockSignals(isBlocked); - return true; -} - -QWidget* ModuleBase_WidgetPoint2D::getControl() const -{ - return myGroupBox; -} - -QList ModuleBase_WidgetPoint2D::getControls() const -{ - QList aControls; - aControls.push_back(myXSpin); - aControls.push_back(myYSpin); - - return aControls; -} - -bool ModuleBase_WidgetPoint2D::initFromPrevious(ObjectPtr theObject) -{ - if (myOptionParam.length() == 0) - return false; - std::shared_ptr aData = theObject->data(); - std::shared_ptr aPoint = std::dynamic_pointer_cast( - aData->attribute(myOptionParam)); - if (aPoint) { - bool isBlocked = this->blockSignals(true); - myXSpin->setValue(aPoint->x()); - myYSpin->setValue(aPoint->y()); - this->blockSignals(isBlocked); - - emit valuesChanged(); - emit storedPoint2D(theObject, myOptionParam); - return true; - } - return false; -} diff --git a/src/ModuleBase/ModuleBase_WidgetPoint2D.h b/src/ModuleBase/ModuleBase_WidgetPoint2D.h deleted file mode 100644 index 394211980..000000000 --- a/src/ModuleBase/ModuleBase_WidgetPoint2D.h +++ /dev/null @@ -1,77 +0,0 @@ -// File: ModuleBase_WidgetPoint2D.h -// Created: 25 Apr 2014 -// Author: Natalia ERMOLAEVA - -#ifndef ModuleBase_WidgetPoint2D_H -#define ModuleBase_WidgetPoint2D_H - -#include -#include "ModuleBase_ModelWidget.h" - -#include - -class ModelAPI_Feature; -class ModuleBase_WidgetValue; -class GeomAPI_Pnt2d; - -class QGroupBox; -class ModuleBase_DoubleSpinBox; - -/**\class ModuleBase_WidgetPoint2D - * \ingroup GUI - * \brief Custom widget. An abstract class to be redefined to fill with some GUI controls - */ -class MODULEBASE_EXPORT ModuleBase_WidgetPoint2D : public ModuleBase_ModelWidget -{ -Q_OBJECT - public: - /// Constructor - /// \theParent the parent object - /// \theParent the parent object - /// \theData the widget configuation. The attribute of the model widget is obtained from - ModuleBase_WidgetPoint2D(QWidget* theParent, const Config_WidgetAPI* theData, - const std::string& theParentId); - /// Destructor - virtual ~ModuleBase_WidgetPoint2D(); - - /// Set the given wrapped value to the current widget - /// This value should be processed in the widget according to the needs - /// \param theValue the wrapped widget value - virtual bool setValue(ModuleBase_WidgetValue* theValue); - - /// Saves the internal parameters to the given feature - /// \param theObject a model feature to be changed - virtual bool storeValue() const; - - virtual bool restoreValue(); - - /// Returns the internal parent wiget control, that can be shown anywhere - /// \returns the widget - QWidget* getControl() const; - - /// Returns list of widget controls - /// \return a control list - virtual QList getControls() const; - - bool initFromPrevious(ObjectPtr theObject); - -signals: - /// Signal about the point 2d set to the feature - /// \param the feature - /// \param the attribute of the feature - void storedPoint2D(ObjectPtr theObject, const std::string& theAttribute); - - protected: - /// Fill the widget values by given point - /// \param thePoint the point - void setPoint(const std::shared_ptr& thePoint); - - private: - QGroupBox* myGroupBox; ///< the parent group box for all intenal widgets - ModuleBase_DoubleSpinBox* myXSpin; ///< the spin box for the X coordinate - ModuleBase_DoubleSpinBox* myYSpin; ///< the spin box for the Y coordinate - - std::string myOptionParam; /// Parameter name which has to be taken from previous feature -}; - -#endif diff --git a/src/ModuleBase/ModuleBase_WidgetPoint2dDistance.cpp b/src/ModuleBase/ModuleBase_WidgetPoint2dDistance.cpp deleted file mode 100644 index 210f4bcba..000000000 --- a/src/ModuleBase/ModuleBase_WidgetPoint2dDistance.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// File: ModuleBase_WidgetPoint2dDistance.h -// Created: 23 June 2014 -// Author: Vitaly Smetannikov - -#include -#include -#include - -#include -#include -#include - -#include -#include - -ModuleBase_WidgetPoint2dDistance::ModuleBase_WidgetPoint2dDistance(QWidget* theParent, - const Config_WidgetAPI* theData, - const std::string& theParentId) - : ModuleBase_WidgetDoubleValue(theParent, theData, theParentId) -{ - myFirstPntName = theData->getProperty("first_point"); -} - -ModuleBase_WidgetPoint2dDistance::~ModuleBase_WidgetPoint2dDistance() -{ -} - -bool ModuleBase_WidgetPoint2dDistance::setValue(ModuleBase_WidgetValue* theValue) -{ - bool isDone = false; - - if (theValue) { - ModuleBase_WidgetValueFeature* aFeatureValue = - dynamic_cast(theValue); - if (aFeatureValue) { - std::shared_ptr aPnt = aFeatureValue->point(); - ObjectPtr aObject = aFeatureValue->object(); - FeaturePtr aFeature = std::dynamic_pointer_cast(aObject); - if (aFeature && aPnt) { - setPoint(aFeature, aPnt); - isDone = true; - } - } - } - return isDone; -} - -void ModuleBase_WidgetPoint2dDistance::setPoint(FeaturePtr theFeature, - const std::shared_ptr& thePnt) -{ - std::shared_ptr aData = theFeature->data(); - std::shared_ptr aPoint = std::dynamic_pointer_cast( - aData->attribute(myFirstPntName)); - if (!aPoint) - return; - - double aRadius = thePnt->distance(aPoint->pnt()); - AttributeDoublePtr aReal = aData->real(attributeID()); - if (aReal && (aReal->value() != aRadius)) { - aReal->setValue(aRadius); - mySpinBox->setValue(aRadius); - } -} diff --git a/src/ModuleBase/ModuleBase_WidgetPoint2dDistance.h b/src/ModuleBase/ModuleBase_WidgetPoint2dDistance.h deleted file mode 100644 index e80aa393b..000000000 --- a/src/ModuleBase/ModuleBase_WidgetPoint2dDistance.h +++ /dev/null @@ -1,39 +0,0 @@ -// File: ModuleBase_WidgetPoint2dDistance.h -// Created: 23 June 2014 -// Author: Vitaly Smetannikov - -#ifndef ModuleBase_WidgetPoint2dDistance_H -#define ModuleBase_WidgetPoint2dDistance_H - -#include "ModuleBase.h" -#include "ModuleBase_WidgetDoubleValue.h" - -class ModuleBase_WidgetValue; -class GeomAPI_Pnt2d; - -class MODULEBASE_EXPORT ModuleBase_WidgetPoint2dDistance : public ModuleBase_WidgetDoubleValue -{ -Q_OBJECT - public: - /// Constructor - /// \theParent the parent object - /// \theData the widget configuation. The attribute of the model widget is obtained from - ModuleBase_WidgetPoint2dDistance(QWidget* theParent, const Config_WidgetAPI* theData, - const std::string& theParentId); - - virtual ~ModuleBase_WidgetPoint2dDistance(); - - /// Set the given wrapped value to the current widget - /// This value should be processed in the widget according to the needs - /// \param theValue the wrapped widget value - virtual bool setValue(ModuleBase_WidgetValue* theValue); - - protected: - /// Set the second point which defines a value in the widget as a distance with a first point defined by feature - void setPoint(FeaturePtr theFeature, const std::shared_ptr& thePnt); - - private: - std::string myFirstPntName; -}; - -#endif diff --git a/src/ModuleBase/ModuleBase_WidgetShapeSelector.cpp b/src/ModuleBase/ModuleBase_WidgetShapeSelector.cpp index 91cc255e8..cf0e748db 100644 --- a/src/ModuleBase/ModuleBase_WidgetShapeSelector.cpp +++ b/src/ModuleBase/ModuleBase_WidgetShapeSelector.cpp @@ -8,13 +8,13 @@ #include #include #include -#include #include #include #include #include #include + #include #include #include @@ -27,6 +27,11 @@ #include #include #include +#include +#include +#include +#include + #include #include @@ -43,6 +48,7 @@ #include #include #include +#include #include #include @@ -127,43 +133,95 @@ bool ModuleBase_WidgetShapeSelector::storeValue() const DataPtr aData = myFeature->data(); if (myUseSubShapes) { - std::shared_ptr aSelect = - std::dynamic_pointer_cast(aData->attribute(attributeID())); - ResultPtr aBody = std::dynamic_pointer_cast(mySelectedObject); if (aBody) { - aSelect->setValue(aBody, myShape); - updateObject(myFeature); - return true; + AttributePtr aAttr = aData->attribute(attributeID()); + + // We have to check several attributes types + AttributeSelectionPtr aSelectAttr = + std::dynamic_pointer_cast(aAttr); + if (aSelectAttr) { + aSelectAttr->setValue(aBody, myShape); + updateObject(myFeature); + return true; + } else { + AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID()); + if (aRefAttr) { + aRefAttr->setObject(mySelectedObject); + updateObject(myFeature); + return true; + } + } } } else { - std::shared_ptr aRef = - std::dynamic_pointer_cast(aData->attribute(attributeID())); - - ObjectPtr aObject = aRef->value(); - if (!(aObject && aObject->isSame(mySelectedObject))) { - aRef->setValue(mySelectedObject); - updateObject(myFeature); - return true; + AttributeReferencePtr aRef = aData->reference(attributeID()); + if (aRef) { + ObjectPtr aObject = aRef->value(); + if (!(aObject && aObject->isSame(mySelectedObject))) { + aRef->setValue(mySelectedObject); + updateObject(myFeature); + return true; + } + } else { + AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID()); + if (aRefAttr) { + ObjectPtr aObject = aRefAttr->object(); + if (!(aObject && aObject->isSame(mySelectedObject))) { + aRefAttr->setObject(mySelectedObject); + updateObject(myFeature); + return true; + } + } } } return false; } +//******************************************************************** +void ModuleBase_WidgetShapeSelector::clearAttribute() +{ + DataPtr aData = myFeature->data(); + AttributeSelectionPtr aSelect = aData->selection(attributeID()); + if (aSelect) { + aSelect->setValue(ResultPtr(), std::shared_ptr(new GeomAPI_Shape())); + return; + } + AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID()); + if (aRefAttr) { + aRefAttr->setObject(ObjectPtr()); + return; + } + AttributeReferencePtr aRef = aData->reference(attributeID()); + if (aRef) { + aRef->setObject(ObjectPtr()); + } +} + //******************************************************************** bool ModuleBase_WidgetShapeSelector::restoreValue() { DataPtr aData = myFeature->data(); bool isBlocked = this->blockSignals(true); if (myUseSubShapes) { - std::shared_ptr aSelect = aData->selection(attributeID()); + AttributeSelectionPtr aSelect = aData->selection(attributeID()); if (aSelect) { mySelectedObject = aSelect->context(); myShape = aSelect->value(); + } else { + AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID()); + if (aRefAttr) { + mySelectedObject = aRefAttr->object(); + } } } else { - std::shared_ptr aRef = aData->reference(attributeID()); - mySelectedObject = aRef->value(); + AttributeReferencePtr aRef = aData->reference(attributeID()); + if (aRef) + mySelectedObject = aRef->value(); + else { + AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID()); + if (aRefAttr) + mySelectedObject = aRefAttr->object(); + } } updateSelectionName(); @@ -182,64 +240,73 @@ QList ModuleBase_WidgetShapeSelector::getControls() const //******************************************************************** void ModuleBase_WidgetShapeSelector::onSelectionChanged() { - QList aObjects = myWorkshop->selection()->selectedObjects(); - if (aObjects.size() > 0) { - ObjectPtr aObject = aObjects.first(); - if ((!mySelectedObject) && (!aObject)) - return; + // In order to make reselection possible + // TODO: check with MPV clearAttribute(); - // Check that the selected object is result (others can not be accepted) - ResultPtr aRes = std::dynamic_pointer_cast(aObject); - if (!aRes) - return; + //QObjectPtrList aObjects = myWorkshop->selection()->selectedPresentations(); + QList aSelected = myWorkshop->selection()->getSelected(); + if (aSelected.size() > 0) + setSelection(aSelected.first()); +} - if (myFeature) { - // We can not select a result of our feature - const std::list>& aResList = myFeature->results(); - std::list >::const_iterator aIt; - for (aIt = aResList.cbegin(); aIt != aResList.cend(); ++aIt) { - if ((*aIt) == aRes) - return; - } +//******************************************************************** +bool ModuleBase_WidgetShapeSelector::setSelection(ModuleBase_ViewerPrs theValue) +{ + ObjectPtr aObject = theValue.object(); + if ((!mySelectedObject) && (!aObject)) + return false; + + // Check that the selected object is result (others can not be accepted) + ResultPtr aRes = std::dynamic_pointer_cast(aObject); + if (!aRes) + return false; + + if (myFeature) { + // We can not select a result of our feature + const std::list>& aResList = myFeature->results(); + std::list >::const_iterator aIt; + for (aIt = aResList.cbegin(); aIt != aResList.cend(); ++aIt) { + if ((*aIt) == aRes) + return false; } - // Check that object belongs to active document or PartSet - DocumentPtr aDoc = aRes->document(); - SessionPtr aMgr = ModelAPI_Session::get(); - if (!(aDoc == aMgr->activeDocument()) || (aDoc == aMgr->moduleDocument())) - return; + } + // Check that object belongs to active document or PartSet + DocumentPtr aDoc = aRes->document(); + SessionPtr aMgr = ModelAPI_Session::get(); + if (!(aDoc == aMgr->activeDocument()) && !(aDoc == aMgr->moduleDocument())) + return false; - // Check that the result has a shape - GeomShapePtr aShape = ModelAPI_Tools::shape(aRes); - if (!aShape) - return; + // Check that the result has a shape + GeomShapePtr aShape = ModelAPI_Tools::shape(aRes); + if (!aShape) + return false; - /// Check that object has acceptable type - if (!acceptObjectType(aObject)) - return; + /// Check that object has acceptable type + if (!acceptObjectType(aObject)) + return false; - // Get sub-shapes from local selection - if (myUseSubShapes) { - NCollection_List aShapeList; - std::list aOwners; - myWorkshop->selection()->selectedShapes(aShapeList, aOwners); - if (aShapeList.Extent() > 0) { - aShape = std::shared_ptr(new GeomAPI_Shape()); - aShape->setImpl(new TopoDS_Shape(aShapeList.First())); - } + // Get sub-shapes from local selection + if (myUseSubShapes) { + if (!theValue.shape().IsNull()) { + aShape = std::shared_ptr(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(theValue.shape())); } + } - // Check that the selection corresponds to selection type - if (myUseSubShapes) { - if (!acceptSubShape(aShape)) - return; - } else { - if (!acceptObjectShape(aObject)) - return; - } + // Check that the selection corresponds to selection type + if (myUseSubShapes) { + if (!acceptSubShape(aShape)) + return false; + } else { + if (!acceptObjectShape(aObject)) + return false; + } + if (isValid(aObject, aShape)) { setObject(aObject, aShape); - //activateSelection(false); emit focusOutWidget(this); + return true; } + return false; } //******************************************************************** @@ -249,13 +316,8 @@ void ModuleBase_WidgetShapeSelector::setObject(ObjectPtr theObj, std::shared_ptr myShape = theShape; if (mySelectedObject) { raisePanel(); - if (!myUseSubShapes) { - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_TOHIDE); - ModelAPI_EventCreator::get()->sendUpdated(mySelectedObject, anEvent); - } } updateSelectionName(); - activateSelection(false); emit valuesChanged(); } @@ -336,6 +398,8 @@ void ModuleBase_WidgetShapeSelector::updateSelectionName() //******************************************************************** void ModuleBase_WidgetShapeSelector::activateSelection(bool toActivate) { + if (myIsActive == toActivate) + return; myIsActive = toActivate; updateSelectionName(); @@ -383,36 +447,67 @@ void ModuleBase_WidgetShapeSelector::raisePanel() const } //******************************************************************** -bool ModuleBase_WidgetShapeSelector::focusTo() +//bool ModuleBase_WidgetShapeSelector::setSelection(ModuleBase_ViewerPrs theValue) +//{ +// if (theValue.object()) { +// ObjectPtr aObject = theValue.object(); +// if (acceptObjectShape(aObject)) { +// setObject(aObject); +// return true; +// } +// } +// return false; +//} + +//******************************************************************** +void ModuleBase_WidgetShapeSelector::activate() { activateSelection(true); - return ModuleBase_ModelWidget::focusTo(); } //******************************************************************** -bool ModuleBase_WidgetShapeSelector::eventFilter(QObject* theObj, QEvent* theEvent) +void ModuleBase_WidgetShapeSelector::deactivate() { - if (theObj == myTextLine) { - if (theEvent->type() == QEvent::FocusIn) - activateSelection(true); - } - return ModuleBase_ModelWidget::eventFilter(theObj, theEvent); + activateSelection(false); } //******************************************************************** -bool ModuleBase_WidgetShapeSelector::setValue(ModuleBase_WidgetValue* theValue) +bool ModuleBase_WidgetShapeSelector::isValid(ObjectPtr theObj, std::shared_ptr theShape) { - if (theValue) { - ModuleBase_WidgetValueFeature* aFeatureValue = - dynamic_cast(theValue); - if (aFeatureValue && aFeatureValue->object()) { - ObjectPtr aObject = aFeatureValue->object(); - if (acceptObjectShape(aObject)) { - setObject(aObject); - return true; + SessionPtr aMgr = ModelAPI_Session::get(); + ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); + std::list aValidators; + std::list > anArguments; + aFactory->validators(parentID(), attributeID(), aValidators, anArguments); + + // Check the type of selected object + std::list::iterator aValidator = aValidators.begin(); + bool isValid = true; + for (; aValidator != aValidators.end(); aValidator++) { + const ModelAPI_ResultValidator* aResValidator = + dynamic_cast(*aValidator); + if (aResValidator) { + isValid = false; + if (aResValidator->isValid(theObj)) { + isValid = true; + break; } } } - return false; -} + if (!isValid) + return false; + // Check the acceptability of the object as attribute + aValidator = aValidators.begin(); + std::list >::iterator aArgs = anArguments.begin(); + for (; aValidator != aValidators.end(); aValidator++, aArgs++) { + const ModelAPI_RefAttrValidator* aAttrValidator = + dynamic_cast(*aValidator); + if (aAttrValidator) { + if (!aAttrValidator->isValid(myFeature, *aArgs, theObj)) { + return false; + } + } + } + return true; +} \ No newline at end of file diff --git a/src/ModuleBase/ModuleBase_WidgetShapeSelector.h b/src/ModuleBase/ModuleBase_WidgetShapeSelector.h index 7284d8ae5..d2b27af6b 100644 --- a/src/ModuleBase/ModuleBase_WidgetShapeSelector.h +++ b/src/ModuleBase/ModuleBase_WidgetShapeSelector.h @@ -35,13 +35,10 @@ Q_OBJECT virtual ~ModuleBase_WidgetShapeSelector(); /// Saves the internal parameters to the given feature - /// \param theObject a model feature to be changed virtual bool storeValue() const; virtual bool restoreValue(); - virtual bool focusTo(); - /// Returns the internal parent wiget control, that can be shown anywhere /// \returns the widget QWidget* getControl() const @@ -61,7 +58,15 @@ Q_OBJECT /// Set the given wrapped value to the current widget /// This value should be processed in the widget according to the needs /// \param theValue the wrapped widget value - virtual bool setValue(ModuleBase_WidgetValue* theValue); + virtual bool setSelection(ModuleBase_ViewerPrs theValue); + + + /// The methiod called when widget is activated + virtual void activate(); + + /// The methiod called when widget is deactivated + virtual void deactivate(); + public slots: @@ -72,8 +77,6 @@ Q_OBJECT void onSelectionChanged(); protected: - bool eventFilter(QObject* theObj, QEvent* theEvent); - void updateSelectionName(); void raisePanel() const; @@ -93,8 +96,14 @@ Q_OBJECT // Set the given object as a value of the widget void setObject(ObjectPtr theObj, std::shared_ptr theShape = std::shared_ptr()); + /// Check the selected with validators if installed + virtual bool isValid(ObjectPtr theObj, std::shared_ptr theShape); + + /// Clear attribute + void clearAttribute(); + //----------- Class members ------------- - private: + protected: QWidget* myContainer; QLabel* myLabel; QLineEdit* myTextLine; diff --git a/src/ModuleBase/ModuleBase_WidgetValue.cpp b/src/ModuleBase/ModuleBase_WidgetValue.cpp deleted file mode 100644 index 83a9d27a7..000000000 --- a/src/ModuleBase/ModuleBase_WidgetValue.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// File: ModuleBase_WidgetValue.cpp -// Created: 25 Apr 2014 -// Author: Natalia ERMOLAEVA - -#include - -ModuleBase_WidgetValue::ModuleBase_WidgetValue() -{ -} - -ModuleBase_WidgetValue::~ModuleBase_WidgetValue() -{ -} diff --git a/src/ModuleBase/ModuleBase_WidgetValue.h b/src/ModuleBase/ModuleBase_WidgetValue.h deleted file mode 100644 index 38b8e51b3..000000000 --- a/src/ModuleBase/ModuleBase_WidgetValue.h +++ /dev/null @@ -1,23 +0,0 @@ -// File: ModuleBase_WidgetValue.h -// Created: 25 Apr 2014 -// Author: Natalia ERMOLAEVA - -#ifndef ModuleBase_WidgetValue_H -#define ModuleBase_WidgetValue_H - -#include - -/**\class ModuleBase_WidgetValue - * \ingroup GUI - * \brief Custom widget value. An abstract class to be redefined and to be set in the model widget - */ -class MODULEBASE_EXPORT ModuleBase_WidgetValue -{ - public: - /// Constructor - ModuleBase_WidgetValue(); - /// Destructor - virtual ~ModuleBase_WidgetValue(); -}; - -#endif diff --git a/src/ModuleBase/ModuleBase_WidgetValueFeature.cpp b/src/ModuleBase/ModuleBase_WidgetValueFeature.cpp deleted file mode 100644 index 43d3a7cfe..000000000 --- a/src/ModuleBase/ModuleBase_WidgetValueFeature.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// File: ModuleBase_WidgetValueFeature.cpp -// Created: 25 Apr 2014 -// Author: Natalia ERMOLAEVA - -#include - -#include - -ModuleBase_WidgetValueFeature::ModuleBase_WidgetValueFeature() -{ -} - -ModuleBase_WidgetValueFeature::~ModuleBase_WidgetValueFeature() -{ -} - -void ModuleBase_WidgetValueFeature::setObject(const ObjectPtr& theFeature) -{ - myResult = theFeature; -} - -const ObjectPtr& ModuleBase_WidgetValueFeature::object() const -{ - return myResult; -} - -void ModuleBase_WidgetValueFeature::setPoint(const std::shared_ptr& thePoint) -{ - myPoint = thePoint; -} - -const std::shared_ptr& ModuleBase_WidgetValueFeature::point() const -{ - return myPoint; -} diff --git a/src/ModuleBase/ModuleBase_WidgetValueFeature.h b/src/ModuleBase/ModuleBase_WidgetValueFeature.h deleted file mode 100644 index d11a6bfd9..000000000 --- a/src/ModuleBase/ModuleBase_WidgetValueFeature.h +++ /dev/null @@ -1,50 +0,0 @@ -// File: ModuleBase_WidgetValueFeature.h -// Created: 25 Apr 2014 -// Author: Natalia ERMOLAEVA - -#ifndef ModuleBase_WidgetValueFeature_H -#define ModuleBase_WidgetValueFeature_H - -#include -#include - -#include - -#include - -class GeomAPI_Pnt2d; - -/**\class ModuleBase_WidgetValueFeature - * \ingroup GUI - * \brief Custom widget value. The widget contains a feature and 2D point. - */ -class ModuleBase_WidgetValueFeature : public ModuleBase_WidgetValue -{ - public: - /// Constructor - MODULEBASE_EXPORT ModuleBase_WidgetValueFeature(); - /// Destructor - MODULEBASE_EXPORT virtual ~ModuleBase_WidgetValueFeature(); - - /// Fill the widget values by given point - /// \param thePoint the point - MODULEBASE_EXPORT void setObject(const ObjectPtr& theFeature); - - /// Returns the widget values by given point - /// \return theFeature the current feature - MODULEBASE_EXPORT const ObjectPtr& object() const; - - /// Fill the widget values by given point - /// \param thePoint the point - MODULEBASE_EXPORT void setPoint(const std::shared_ptr& thePoint); - - /// Returns the widget point - /// \return the current point - MODULEBASE_EXPORT const std::shared_ptr& point() const; - - private: - ObjectPtr myResult; - std::shared_ptr myPoint; -}; - -#endif diff --git a/src/NewGeom/NewGeom_Module.cpp b/src/NewGeom/NewGeom_Module.cpp index 9f8bc4543..5755c626f 100644 --- a/src/NewGeom/NewGeom_Module.cpp +++ b/src/NewGeom/NewGeom_Module.cpp @@ -57,6 +57,14 @@ public: return myMgr->addPreference(myModName, theLbl, pId, theType, theSection, theName); } + virtual void setItemProperty(const QString& thePropName, + const QVariant& theValue, + const int theId = -1) + { + myMgr->setItemProperty(thePropName, theValue, theId); + } + + virtual SUIT_PreferenceMgr* prefMgr() const { return myMgr; } private: diff --git a/src/NewGeom/NewGeom_SalomeViewer.cpp b/src/NewGeom/NewGeom_SalomeViewer.cpp index 419c5d0b8..ef6d6c539 100644 --- a/src/NewGeom/NewGeom_SalomeViewer.cpp +++ b/src/NewGeom/NewGeom_SalomeViewer.cpp @@ -10,12 +10,34 @@ #include #include + +Handle(V3d_View) NewGeom_SalomeView::v3dView() const +{ + SUIT_ViewManager* aMgr = myViewer->getViewManager(); + OCCViewer_ViewWindow* aWnd = static_cast(aMgr->getActiveView()); + Handle(V3d_View) aView = aWnd->getViewPort()->getView(); + return aView; +} + +//********************************************** +//********************************************** +//********************************************** + + + NewGeom_SalomeViewer::NewGeom_SalomeViewer(QObject* theParent) : ModuleBase_IViewer(theParent), - mySelector(0) + mySelector(0), myView(0), myIsSelectionChanged(false) { } +NewGeom_SalomeViewer::~NewGeom_SalomeViewer() +{ + if (myView) + delete myView; +} + + //********************************************** Handle(AIS_InteractiveContext) NewGeom_SalomeViewer::AISContext() const { @@ -59,11 +81,19 @@ void NewGeom_SalomeViewer::setSelector(NewGeom_OCCSelector* theSel) OCCViewer_Viewer* aViewer = mySelector->viewer(); SUIT_ViewManager* aMgr = aViewer->getViewManager(); + myView = new NewGeom_SalomeView(mySelector->viewer()); + + // TODO: Provide ModuleBase_IViewWindow interface connect(aMgr, SIGNAL(lastViewClosed(SUIT_ViewManager*)), this, SIGNAL(lastViewClosed())); - connect(aMgr, SIGNAL(tryCloseView(SUIT_ViewManager*)), this, SIGNAL(tryCloseView())); - connect(aMgr, SIGNAL(deleteView(SUIT_ViewManager*)), this, SIGNAL(deleteView())); - connect(aMgr, SIGNAL(viewCreated(SUIT_ViewManager*)), this, SIGNAL(viewCreated())); - connect(aMgr, SIGNAL(activated(SUIT_ViewManager*)), this, SIGNAL(activated())); + + connect(aMgr, SIGNAL(tryCloseView(SUIT_ViewWindow*)), + this, SLOT(onTryCloseView(SUIT_ViewWindow*))); + connect(aMgr, SIGNAL(deleteView(SUIT_ViewWindow*)), + this, SLOT(onDeleteView(SUIT_ViewWindow*))); + connect(aMgr, SIGNAL(viewCreated(SUIT_ViewWindow*)), + this, SLOT(onViewCreated(SUIT_ViewWindow*))); + connect(aMgr, SIGNAL(activated(SUIT_ViewWindow*)), + this, SLOT(onActivated(SUIT_ViewWindow*))); connect(aMgr, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)), this, SLOT(onMousePress(SUIT_ViewWindow*, QMouseEvent*))); @@ -73,53 +103,84 @@ void NewGeom_SalomeViewer::setSelector(NewGeom_OCCSelector* theSel) SLOT(onMouseDoubleClick(SUIT_ViewWindow*, QMouseEvent*))); connect(aMgr, SIGNAL(mouseMove(SUIT_ViewWindow*, QMouseEvent*)), this, SLOT(onMouseMove(SUIT_ViewWindow*, QMouseEvent*))); + connect(aMgr, SIGNAL(keyPress(SUIT_ViewWindow*, QKeyEvent*)), this, SLOT(onKeyPress(SUIT_ViewWindow*, QKeyEvent*))); connect(aMgr, SIGNAL(keyRelease(SUIT_ViewWindow*, QKeyEvent*)), this, SLOT(onKeyRelease(SUIT_ViewWindow*, QKeyEvent*))); - connect(aViewer, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged())); + connect(aViewer, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged())); +} + +//********************************************** +void NewGeom_SalomeViewer::onSelectionChanged() +{ + // Selection event must be sent only after mouse release + myIsSelectionChanged = true; } //********************************************** void NewGeom_SalomeViewer::onMousePress(SUIT_ViewWindow*, QMouseEvent* theEvent) { - emit mousePress(theEvent); + emit mousePress(myView, theEvent); } //********************************************** void NewGeom_SalomeViewer::onMouseRelease(SUIT_ViewWindow*, QMouseEvent* theEvent) { - emit mouseRelease(theEvent); - //if ((theEvent->button() == Qt::RightButton) && - // (theEvent->modifiers() == Qt::NoModifier)) { - // QContextMenuEvent aEvent(QContextMenuEvent::Mouse, theEvent->pos(), theEvent->globalPos()); - // emit contextMenuRequested(&aEvent); - //} + emit mouseRelease(myView, theEvent); + if (myIsSelectionChanged) { + emit selectionChanged(); + myIsSelectionChanged = false; + } } //********************************************** void NewGeom_SalomeViewer::onMouseDoubleClick(SUIT_ViewWindow*, QMouseEvent* theEvent) { - emit mouseDoubleClick(theEvent); + emit mouseDoubleClick(myView, theEvent); } //********************************************** void NewGeom_SalomeViewer::onMouseMove(SUIT_ViewWindow*, QMouseEvent* theEvent) { - emit mouseMove(theEvent); + emit mouseMove(myView, theEvent); } //********************************************** void NewGeom_SalomeViewer::onKeyPress(SUIT_ViewWindow*, QKeyEvent* theEvent) { - emit keyPress(theEvent); + emit keyPress(myView, theEvent); } //********************************************** void NewGeom_SalomeViewer::onKeyRelease(SUIT_ViewWindow*, QKeyEvent* theEvent) { - emit keyRelease(theEvent); + emit keyRelease(myView, theEvent); +} + +//********************************************** +void NewGeom_SalomeViewer::onTryCloseView(SUIT_ViewWindow*) +{ + emit tryCloseView(myView); +} + +//********************************************** +void NewGeom_SalomeViewer::onDeleteView(SUIT_ViewWindow*) +{ + emit deleteView(myView); +} + +//********************************************** +void NewGeom_SalomeViewer::onViewCreated(SUIT_ViewWindow*) +{ + emit viewCreated(myView); +} + +//********************************************** +void NewGeom_SalomeViewer::onActivated(SUIT_ViewWindow*) +{ + emit activated(myView); } //********************************************** diff --git a/src/NewGeom/NewGeom_SalomeViewer.h b/src/NewGeom/NewGeom_SalomeViewer.h index 5148dcc6d..8362a7d1e 100644 --- a/src/NewGeom/NewGeom_SalomeViewer.h +++ b/src/NewGeom/NewGeom_SalomeViewer.h @@ -5,12 +5,33 @@ #include "NewGeom.h" #include +#include + +#include class SUIT_ViewWindow; class QMouseEvent; class QKeyEvent; class NewGeom_OCCSelector; +class OCCViewer_Viewer; +class SUIT_ViewManager; + + +class NewGeom_SalomeView: public ModuleBase_IViewWindow +{ +public: + NewGeom_SalomeView(OCCViewer_Viewer* theViewer) { myViewer = theViewer; } + + virtual Handle(V3d_View) v3dView() const; + + void setViewer(OCCViewer_Viewer* theViewer) { myViewer = theViewer; } + OCCViewer_Viewer* viewer() const { return myViewer; } + +private: + OCCViewer_Viewer* myViewer; +}; + class NewGeom_SalomeViewer : public ModuleBase_IViewer { @@ -18,6 +39,8 @@ Q_OBJECT public: NewGeom_SalomeViewer(QObject* theParent); + ~NewGeom_SalomeViewer(); + //! Returns AIS_InteractiveContext from current OCCViewer virtual Handle(AIS_InteractiveContext) AISContext() const; @@ -72,9 +95,18 @@ Q_OBJECT void onKeyPress(SUIT_ViewWindow*, QKeyEvent*); void onKeyRelease(SUIT_ViewWindow*, QKeyEvent*); + void onTryCloseView(SUIT_ViewWindow*); + void onDeleteView(SUIT_ViewWindow*); + void onViewCreated(SUIT_ViewWindow*); + void onActivated(SUIT_ViewWindow*); + + void onSelectionChanged(); + private: NewGeom_OCCSelector* mySelector; - + NewGeom_SalomeView* myView; + bool myIsSelectionChanged; }; + #endif diff --git a/src/PartSet/CMakeLists.txt b/src/PartSet/CMakeLists.txt index dae5c3b4f..55370797f 100644 --- a/src/PartSet/CMakeLists.txt +++ b/src/PartSet/CMakeLists.txt @@ -6,30 +6,28 @@ SET(PROJECT_HEADERS PartSet.h PartSet_Constants.h PartSet_EditLine.h - PartSet_Listener.h PartSet_Module.h - PartSet_OperationFeatureCreate.h - PartSet_OperationFeatureEdit.h - PartSet_OperationSketchBase.h - PartSet_OperationSketch.h - PartSet_OperationFeatureBase.h PartSet_Tools.h PartSet_WidgetSketchLabel.h PartSet_Validators.h + PartSet_WidgetPoint2d.h + PartSet_WidgetPoint2dDistance.h + PartSet_WidgetShapeSelector.h + PartSet_OperationSketch.h + PartSet_Filters.h ) SET(PROJECT_SOURCES PartSet_EditLine.cpp - PartSet_Listener.cpp PartSet_Module.cpp - PartSet_OperationFeatureCreate.cpp - PartSet_OperationFeatureEdit.cpp - PartSet_OperationSketchBase.cpp - PartSet_OperationSketch.cpp - PartSet_OperationFeatureBase.cpp PartSet_Tools.cpp PartSet_WidgetSketchLabel.cpp PartSet_Validators.cpp + PartSet_WidgetPoint2d.cpp + PartSet_WidgetPoint2dDistance.cpp + PartSet_WidgetShapeSelector.cpp + PartSet_OperationSketch.cpp + PartSet_Filters.cpp ) SET(PROJECT_RESOURCES @@ -74,6 +72,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/XGUI ${CMAKE_SOURCE_DIR}/src/GeomDataAPI ${CMAKE_SOURCE_DIR}/src/GeomAlgoAPI ${CMAKE_SOURCE_DIR}/src/SketchPlugin + ${CMAKE_SOURCE_DIR}/src/FeaturesPlugin ${CMAKE_SOURCE_DIR}/src/GeomAPI ${CAS_INCLUDE_DIRS} ${SUIT_INCLUDE} diff --git a/src/PartSet/PartSet_Filters.cpp b/src/PartSet/PartSet_Filters.cpp new file mode 100644 index 000000000..04ea88b37 --- /dev/null +++ b/src/PartSet/PartSet_Filters.cpp @@ -0,0 +1,42 @@ +// File: PartSet_Filters.cpp +// Created: 08 Nov 2014 +// Author: Vitaly SMETANNIKOV + +#include "PartSet_Filters.h" + +#include + +#include +#include + +#include +#include + + +IMPLEMENT_STANDARD_HANDLE(PartSet_GlobalFilter, ModuleBase_ShapeDocumentFilter); +IMPLEMENT_STANDARD_RTTIEXT(PartSet_GlobalFilter, ModuleBase_ShapeDocumentFilter); + +Standard_Boolean PartSet_GlobalFilter::IsOk(const Handle(SelectMgr_EntityOwner)& theOwner) const +{ + if (ModuleBase_ShapeDocumentFilter::IsOk(theOwner)) { + if (theOwner->HasSelectable()) { + Handle(AIS_InteractiveObject) aAisObj = + Handle(AIS_InteractiveObject)::DownCast(theOwner->Selectable()); + if (!aAisObj.IsNull()) { + std::shared_ptr aAISObj = AISObjectPtr(new GeomAPI_AISObject()); + aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aAisObj)); + ObjectPtr aObj = myWorkshop->findPresentedObject(aAISObj); + if (aObj) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aObj); + if (aFeature) { + return aFeature->getKind() != FeaturesPlugin_Group::ID(); + } else + return Standard_True; + } else + // This is not object controlled by the filter + return Standard_True; + } + } + } + return Standard_False; +} diff --git a/src/PartSet/PartSet_Filters.h b/src/PartSet/PartSet_Filters.h new file mode 100644 index 000000000..56715069d --- /dev/null +++ b/src/PartSet/PartSet_Filters.h @@ -0,0 +1,26 @@ +// File: PartSet_Filters.h +// Created: 08 Nov 2014 +// Author: Vitaly SMETANNIKOV + +#ifndef PartSet_Filters_H +#define PartSet_Filters_H + +#include + + +/** +* A class which filters groups object in addition to documents (see issue #310) +*/ +DEFINE_STANDARD_HANDLE(PartSet_GlobalFilter, ModuleBase_ShapeDocumentFilter); +class PartSet_GlobalFilter: public ModuleBase_ShapeDocumentFilter +{ +public: + PartSet_GlobalFilter(ModuleBase_IWorkshop* theWorkshop) + : ModuleBase_ShapeDocumentFilter(theWorkshop) {} + + Standard_EXPORT virtual Standard_Boolean IsOk(const Handle(SelectMgr_EntityOwner)& theOwner) const; + + DEFINE_STANDARD_RTTI(PartSet_GlobalFilter) +}; + +#endif \ No newline at end of file diff --git a/src/PartSet/PartSet_Listener.cpp b/src/PartSet/PartSet_Listener.cpp deleted file mode 100644 index d12987ede..000000000 --- a/src/PartSet/PartSet_Listener.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// File: PartSet_Listener.h -// Created: 28 Apr 2014 -// Author: Natalia ERMOLAEVA - -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include - -#ifdef _DEBUG -#include -#endif - -using namespace std; - -PartSet_Listener::PartSet_Listener(PartSet_Module* theModule) - : myModule(theModule) -{ - Events_Loop* aLoop = Events_Loop::loop(); - aLoop->registerListener(this, aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY)); - aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED)); - aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED)); -} - -PartSet_Listener::~PartSet_Listener() -{ -} - -//****************************************************** -void PartSet_Listener::processEvent(const std::shared_ptr& theMessage) -{ - ModuleBase_Operation* anOperation = myModule->xWorkshop()->operationMgr()->currentOperation(); - PartSet_OperationSketchBase* aSketchOp = dynamic_cast(anOperation); - if (!aSketchOp) - return; - - XGUI_Displayer* aDisplayer = myModule->xWorkshop()->displayer(); - QString aType = QString(theMessage->eventID().eventText()); - if (aType == EVENT_OBJECT_CREATED) { - std::shared_ptr aUpdMsg = - std::dynamic_pointer_cast(theMessage); - std::set aFeatures = aUpdMsg->objects(); - - PartSet_OperationSketch* aSketchOp = - dynamic_cast(myModule->xWorkshop()->operationMgr()->currentOperation()); - - std::set::const_iterator anIt = aFeatures.begin(), aLast = aFeatures.end(); - for (; anIt != aLast; anIt++) { - ObjectPtr aObj = (*anIt); - // If current operation is Sketch then there is no active sketching operation - // and possible the object was created by Redo operation - if (aSketchOp) { - XGUI_Displayer* aDisplayer = myModule->xWorkshop()->displayer(); - // Very possible it is not displayed - aDisplayer->display(aObj, false); - } - } - } else if (aType == EVENT_OBJECT_TO_REDISPLAY) { - PartSet_OperationFeatureCreate* aCreationOp = - dynamic_cast - (myModule->xWorkshop()->operationMgr()->currentOperation()); - if (aCreationOp) { - // Deactivate currently creating objects for selection - XGUI_Displayer* aDisplayer = myModule->xWorkshop()->displayer(); - FeaturePtr aFeature = aCreationOp->feature(); - const std::list& aResults = aFeature->results(); - std::shared_ptr aUpdMsg = - std::dynamic_pointer_cast(theMessage); - - std::set aFeatures = aUpdMsg->objects(); - std::set::const_iterator aObjIt, aNoObj = aFeatures.cend(); - std::list::const_iterator anIt = aResults.begin(), aLast = aResults.end(); - for (; anIt != aLast; anIt++) { - aObjIt = aFeatures.find(*anIt); - if (aObjIt != aNoObj) { - aDisplayer->deactivate(*aObjIt); - } - } - } - } else if (aType == EVENT_OBJECT_DELETED) { - std::shared_ptr aDelMsg = - std::dynamic_pointer_cast(theMessage); - std::shared_ptr aDoc = aDelMsg->document(); - - std::set aGroups = aDelMsg->groups(); - std::set::const_iterator anIt = aGroups.begin(), aLast = aGroups.end(); - for (; anIt != aLast; anIt++) { - std::string aGroup = *anIt; - if (aGroup.compare(SketchPlugin_Sketch::ID()) == 0) { // Update only Sketch group - myModule->xWorkshop()->displayer()->eraseDeletedResults(); - myModule->updateCurrentPreview(aGroup); - } - } - } -} diff --git a/src/PartSet/PartSet_Listener.h b/src/PartSet/PartSet_Listener.h deleted file mode 100644 index 8950d2f64..000000000 --- a/src/PartSet/PartSet_Listener.h +++ /dev/null @@ -1,35 +0,0 @@ -// File: PartSet_Listener.h -// Created: 28 Apr 2014 -// Author: Natalia ERMOLAEVA - -#ifndef PartSet_Listener_H -#define PartSet_Listener_H - -#include "PartSet.h" - -#include - -class PartSet_Module; - -/*! - \class PartSet_Listener - * \brief The operation for the sketch feature creation - */ -class PARTSET_EXPORT PartSet_Listener : public Events_Listener -{ - public: - /// Constructor - /// \param theId the feature identifier - /// \param theParent the operation parent - PartSet_Listener(PartSet_Module* theModule); - /// Destructor - virtual ~PartSet_Listener(); - - /// This method is called by loop when the event is started to process. - virtual void processEvent(const std::shared_ptr& theMessage); - - private: - PartSet_Module* myModule; ///< the current module -}; - -#endif diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index 092b0769f..7ecd6033b 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -1,17 +1,17 @@ -#include +#include "PartSet_Module.h" #include -#include -#include -#include -#include #include #include #include +#include +#include +#include #include -#include -#include -#include +#include +#include +#include +#include #include #include @@ -38,24 +38,29 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include -#include -#include #include -//#include -//#include - -#include -#include -#include -#include #include +#include +#include +#include +#include #include #include #include +#include +#include #include #include @@ -64,6 +69,23 @@ #include #endif + +/// Returns list of unique objects by sum of objects from List1 and List2 +QList getSumList(const QList& theList1, + const QList& theList2) +{ + QList aRes; + foreach (ModuleBase_ViewerPrs aPrs, theList1) { + if (!aRes.contains(aPrs.object())) + aRes.append(aPrs.object()); + } + foreach (ModuleBase_ViewerPrs aPrs, theList2) { + if (!aRes.contains(aPrs.object())) + aRes.append(aPrs.object()); + } + return aRes; +} + /*!Create and return new instance of XGUI_Module*/ extern "C" PARTSET_EXPORT ModuleBase_IModule* createModule(ModuleBase_IWorkshop* theWshop) { @@ -71,29 +93,42 @@ extern "C" PARTSET_EXPORT ModuleBase_IModule* createModule(ModuleBase_IWorkshop* } PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop) - : ModuleBase_IModule(theWshop) + : ModuleBase_IModule(theWshop), + myIsDragging(false), myRestartingMode(RM_None), myDragDone(false) { - //myWorkshop = theWshop; - myListener = new PartSet_Listener(this); + //myWorkshop = dynamic_cast(theWshop); + ModuleBase_IViewer* aViewer = aViewer = theWshop->viewer(); + 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(myWorkshop, SIGNAL(operationStarted(ModuleBase_Operation*)), - this, SLOT(onOperationStarted(ModuleBase_Operation*))); + connect(aViewer, SIGNAL(mouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)), + this, SLOT(onMouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*))); - connect(myWorkshop, SIGNAL(operationStopped(ModuleBase_Operation*)), this, - SLOT(onOperationStopped(ModuleBase_Operation*))); + XGUI_ModuleConnector* aConnector = dynamic_cast(theWshop); + XGUI_Workshop* aWorkshop = aConnector->workshop(); - XGUI_Workshop* aXWshop = xWorkshop(); - XGUI_ContextMenuMgr* aContextMenuMgr = aXWshop->contextMenuMgr(); - connect(aContextMenuMgr, SIGNAL(actionTriggered(const QString&, bool)), this, - SLOT(onContextMenuCommand(const QString&, bool))); + XGUI_OperationMgr* anOpMgr = aWorkshop->operationMgr(); + connect(anOpMgr, SIGNAL(keyEnterReleased()), this, SLOT(onEnterReleased())); + connect(aViewer, SIGNAL(keyRelease(ModuleBase_IViewWindow*, QKeyEvent*)), + this, SLOT(onKeyRelease(ModuleBase_IViewWindow*, QKeyEvent*))); } PartSet_Module::~PartSet_Module() { + if (!myDocumentShapeFilter.IsNull()) + myDocumentShapeFilter.Nullify(); + if (!myPlaneFilter.IsNull()) + myPlaneFilter.Nullify(); } -void PartSet_Module::createFeatures() +void PartSet_Module::registerValidators() { //Registering of validators SessionPtr aMgr = ModelAPI_Session::get(); @@ -103,510 +138,528 @@ void PartSet_Module::createFeatures() aFactory->registerValidator("PartSet_PerpendicularValidator", new PartSet_PerpendicularValidator); aFactory->registerValidator("PartSet_ParallelValidator", new PartSet_ParallelValidator); aFactory->registerValidator("PartSet_RadiusValidator", new PartSet_RadiusValidator); - - Config_ModuleReader aXMLReader = Config_ModuleReader(); - aXMLReader.readAll(); - myFeaturesInFiles = aXMLReader.featuresInFiles(); + aFactory->registerValidator("PartSet_DifferentObjects", new PartSet_DifferentObjectsValidator); } -void PartSet_Module::featureCreated(QAction* theFeature) + +void PartSet_Module::onOperationComitted(ModuleBase_Operation* theOperation) { - connect(theFeature, SIGNAL(triggered(bool)), this, SLOT(onFeatureTriggered())); + if (theOperation->isEditOperation()) + return; + /// Restart sketcher operations automatically + FeaturePtr aFeature = theOperation->feature(); + std::shared_ptr aSPFeature = + std::dynamic_pointer_cast(aFeature); + if (aSPFeature && (myRestartingMode == RM_LastFeatureUsed || + myRestartingMode == RM_EmptyFeatureUsed)) { + myLastOperationId = theOperation->id(); + myLastFeature = myRestartingMode == RM_LastFeatureUsed ? theOperation->feature() : FeaturePtr(); + launchOperation(myLastOperationId); + } + breakOperationSequence(); } -std::string PartSet_Module::featureFile(const std::string& theFeatureId) +void PartSet_Module::breakOperationSequence() { - return myFeaturesInFiles[theFeatureId]; + myLastOperationId = ""; + myLastFeature = FeaturePtr(); + myRestartingMode = RM_None; } -/* - * - */ -void PartSet_Module::onFeatureTriggered() +void PartSet_Module::onOperationAborted(ModuleBase_Operation* theOperation) { - QAction* aCmd = dynamic_cast(sender()); - //Do nothing on uncheck - if (aCmd->isCheckable() && !aCmd->isChecked()) - return; - launchOperation(aCmd->data().toString()); + breakOperationSequence(); } - void PartSet_Module::onOperationStarted(ModuleBase_Operation* theOperation) { - XGUI_Workshop* aXWshp = xWorkshop(); - XGUI_Displayer* aDisplayer = aXWshp->displayer(); - PartSet_OperationSketchBase* aPreviewOp = dynamic_cast(theOperation); - if (aPreviewOp) { - XGUI_PropertyPanel* aPropPanel = aXWshp->propertyPanel(); - connect(aPropPanel, SIGNAL(storedPoint2D(ObjectPtr, const std::string&)), this, - SLOT(onStorePoint2D(ObjectPtr, const std::string&)), Qt::UniqueConnection); - - //aDisplayer->deactivateObjectsOutOfContext(); - PartSet_OperationSketch* aSketchOp = dynamic_cast(aPreviewOp); - if (aSketchOp) { - if (aSketchOp->isEditOperation()) { - setSketchingMode(getSketchPlane(aSketchOp->feature())); - } else { - aDisplayer->openLocalContext(); - aDisplayer->activateObjectsOutOfContext(QIntList()); - myPlaneFilter = new StdSelect_FaceFilter(StdSelect_Plane); - aDisplayer->addSelectionFilter(myPlaneFilter); - QIntList aModes = sketchSelectionModes(aPreviewOp->feature()); - aDisplayer->setSelectionModes(aModes); - } + if (theOperation->id().toStdString() == SketchPlugin_Sketch::ID()) { + // Display all sketcher sub-Objects + myCurrentSketch = std::dynamic_pointer_cast(theOperation->feature()); + XGUI_ModuleConnector* aConnector = dynamic_cast(workshop()); + XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); + + 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) { + aDisplayer->display((*aIt), false); + } + aDisplayer->display(aFeature); + } + // Hide sketcher result + std::list aResults = myCurrentSketch->results(); + std::list::const_iterator aIt; + for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { + aDisplayer->erase((*aIt), false); + } + aDisplayer->erase(myCurrentSketch); + + + if (myPlaneFilter.IsNull()) + myPlaneFilter = new ModuleBase_ShapeInPlaneFilter(); + myWorkshop->viewer()->addSelectionFilter(myPlaneFilter); + if (theOperation->isEditOperation()) { + // If it is editing of sketch then it means that plane is already defined + std::shared_ptr aPln = PartSet_Tools::sketchPlane(myCurrentSketch); + myPlaneFilter->setPlane(aPln->impl()); } } + if (myDocumentShapeFilter.IsNull()) + myDocumentShapeFilter = new PartSet_GlobalFilter(myWorkshop); + myWorkshop->viewer()->addSelectionFilter(myDocumentShapeFilter); } void PartSet_Module::onOperationStopped(ModuleBase_Operation* theOperation) { - if (!theOperation) - return; - XGUI_Workshop* aXWshp = xWorkshop(); - XGUI_Displayer* aDisplayer = aXWshp->displayer(); - PartSet_OperationSketchBase* aPreviewOp = dynamic_cast(theOperation); - if (aPreviewOp) { - XGUI_PropertyPanel* aPropPanel = aXWshp->propertyPanel(); - - PartSet_OperationSketch* aSketchOp = dynamic_cast(aPreviewOp); - if (aSketchOp) { - aDisplayer->closeLocalContexts(); - } else { - PartSet_OperationFeatureCreate* aCreationOp = - dynamic_cast(aPreviewOp); - if (aCreationOp) { - // Activate just created object for selection - FeaturePtr aFeature = aCreationOp->feature(); - QIntList aModes = sketchSelectionModes(aFeature); - const std::list& aResults = aFeature->results(); - std::list::const_iterator anIt, aLast = aResults.end(); - for (anIt = aResults.begin(); anIt != aLast; anIt++) { - aDisplayer->activate(*anIt, aModes); - } - aDisplayer->activate(aFeature, aModes); - aDisplayer->clearSelected(); + if (theOperation->id().toStdString() == SketchPlugin_Sketch::ID()) { + DataPtr aData = myCurrentSketch->data(); + if ((!aData) || (!aData->isValid())) { + // The sketch was aborted + myCurrentSketch = CompositeFeaturePtr(); + return; + } + // Hide all sketcher sub-Objects + XGUI_ModuleConnector* aConnector = dynamic_cast(workshop()); + XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); + 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) { + aDisplayer->erase((*aIt), false); } + aDisplayer->erase(aFeature, false); } - }// else { - // Activate results of current feature for selection - //FeaturePtr aFeature = theOperation->feature(); - //XGUI_Displayer* aDisplayer = aXWshp->displayer(); - //std::list aResults = aFeature->results(); - //std::list::const_iterator aIt; - //for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) { - // aDisplayer->activate(*aIt); - //} - //} + // Display sketcher result + std::list aResults = myCurrentSketch->results(); + std::list::const_iterator aIt; + for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { + aDisplayer->display((*aIt), false); + } + aDisplayer->display(myCurrentSketch); + + myCurrentSketch = CompositeFeaturePtr(); + myWorkshop->viewer()->removeSelectionFilter(myPlaneFilter); + } + myWorkshop->viewer()->removeSelectionFilter(myDocumentShapeFilter); } -void PartSet_Module::onContextMenuCommand(const QString& theId, bool isChecked) +void PartSet_Module::onPlaneSelected(const std::shared_ptr& thePln) { - QList aFeatures = workshop()->selection()->selectedObjects(); - if (theId == "EDIT_CMD" && (aFeatures.size() > 0)) { - FeaturePtr aFeature = std::dynamic_pointer_cast(aFeatures.first()); - if (aFeature) - editFeature(aFeature); - } + myPlaneFilter->setPlane(thePln->impl()); } -void PartSet_Module::onMousePressed(QMouseEvent* theEvent) + +void PartSet_Module::propertyPanelDefined(ModuleBase_Operation* theOperation) { - XGUI_Workshop* aXWshp = xWorkshop(); - PartSet_OperationSketchBase* aPreviewOp = - dynamic_cast(workshop()->currentOperation()); - if (aPreviewOp) { - ModuleBase_ISelection* aSelection = workshop()->selection(); - aPreviewOp->mousePressed(theEvent, myWorkshop->viewer(), aSelection); + ModuleBase_IPropertyPanel* aPanel = theOperation->propertyPanel(); + if ((theOperation->id().toStdString() == SketchPlugin_Sketch::ID()) && + (theOperation->isEditOperation())) { + // we have to manually activate the sketch label in edit mode + aPanel->activateWidget(aPanel->modelWidgets().first()); + return; } -} -void PartSet_Module::onMouseReleased(QMouseEvent* theEvent) -{ - PartSet_OperationSketchBase* aPreviewOp = - dynamic_cast(myWorkshop->currentOperation()); - if (aPreviewOp) { - ModuleBase_ISelection* aSelection = workshop()->selection(); - // Initialise operation with preliminary selection - aPreviewOp->mouseReleased(theEvent, myWorkshop->viewer(), aSelection); + // Restart last operation type + if ((theOperation->id() == myLastOperationId) && myLastFeature) { + ModuleBase_ModelWidget* aWgt = aPanel->activeWidget(); + if (theOperation->id().toStdString() == SketchPlugin_Line::ID()) { + // Initialise new line with first point equal to end of previous + PartSet_WidgetPoint2D* aPnt2dWgt = dynamic_cast(aWgt); + if (aPnt2dWgt) { + std::shared_ptr aData = myLastFeature->data(); + std::shared_ptr aPoint = + std::dynamic_pointer_cast(aData->attribute(SketchPlugin_Line::END_ID())); + if (aPoint) { + aPnt2dWgt->setPoint(aPoint->x(), aPoint->y()); + PartSet_Tools::setConstraints(myCurrentSketch, theOperation->feature(), + aWgt->attributeID(), aPoint->x(), aPoint->y()); + theOperation->propertyPanel()->activateNextWidget(aPnt2dWgt); + } + } + } + } else { + // Start editing constraint + if (theOperation->isEditOperation()) { + std::string aId = theOperation->id().toStdString(); + if (sketchOperationIdList().contains(QString(aId.c_str()))) { + if ((aId == SketchPlugin_ConstraintRadius::ID()) || + (aId == SketchPlugin_ConstraintLength::ID()) || + (aId == SketchPlugin_ConstraintDistance::ID())) { + // Find and activate widget for management of point for dimension line position + QList aWidgets = aPanel->modelWidgets(); + foreach (ModuleBase_ModelWidget* aWgt, aWidgets) { + PartSet_WidgetPoint2D* aPntWgt = dynamic_cast(aWgt); + if (aPntWgt) { + aPanel->activateWidget(aPntWgt); + return; + } + } + } + } + } } } -void PartSet_Module::onMouseMoved(QMouseEvent* theEvent) -{ - PartSet_OperationSketchBase* aPreviewOp = - dynamic_cast(myWorkshop->currentOperation()); - if (aPreviewOp) - aPreviewOp->mouseMoved(theEvent, myWorkshop->viewer()); -} -void PartSet_Module::onKeyRelease(QKeyEvent* theEvent) +void PartSet_Module::onSelectionChanged() { - ModuleBase_Operation* anOperation = myWorkshop->currentOperation(); - PartSet_OperationSketchBase* aPreviewOp = dynamic_cast(anOperation); - if (aPreviewOp) { - aPreviewOp->keyReleased(theEvent->key()); + ModuleBase_Operation* aOperation = myWorkshop->currentOperation(); + bool isSketcherOp = false; + // An edit operation is enable only if the current opeation is the sketch operation + if (aOperation && myCurrentSketch) { + if (PartSet_Tools::sketchPlane(myCurrentSketch)) + isSketcherOp = (aOperation->id().toStdString() == SketchPlugin_Sketch::ID()); } -} + if (!isSketcherOp) + return; -void PartSet_Module::onMouseDoubleClick(QMouseEvent* theEvent) -{ - PartSet_OperationSketchBase* aPreviewOp = - dynamic_cast(myWorkshop->currentOperation()); - Handle(V3d_View) aView = myWorkshop->viewer()->activeView(); - if (aPreviewOp && (!aView.IsNull())) { - ModuleBase_ISelection* aSelection = workshop()->selection(); - // Initialise operation with preliminary selection - aPreviewOp->mouseDoubleClick(theEvent, aView, aSelection); + // Editing of constraints can be done on selection + ModuleBase_ISelection* aSelect = myWorkshop->selection(); + QList aSelected = aSelect->getSelected(); + if (aSelected.size() == 1) { + ModuleBase_ViewerPrs aPrs = aSelected.first(); + ObjectPtr aObject = aPrs.object(); + FeaturePtr aFeature = ModelAPI_Feature::feature(aObject); + if (aFeature) { + std::string aId = aFeature->getKind(); + if ((aId == SketchPlugin_ConstraintRadius::ID()) || + (aId == SketchPlugin_ConstraintLength::ID()) || + (aId == SketchPlugin_ConstraintDistance::ID())) { + editFeature(aFeature); + } + } } } -void PartSet_Module::onPlaneSelected(double theX, double theY, double theZ) +void PartSet_Module::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) { - myWorkshop->viewer()->setViewProjection(theX, theY, theZ); -} + if (!(theEvent->buttons() & Qt::LeftButton)) + return; -void PartSet_Module::onSketchLaunched() -{ - xWorkshop()->actionsMgr()->update(); - // Set working plane - ModuleBase_Operation* anOperation = myWorkshop->currentOperation(); - FeaturePtr aSketch = anOperation->feature(); - setSketchingMode(getSketchPlane(aSketch)); -} + ModuleBase_Operation* aOperation = myWorkshop->currentOperation(); + // Use only for sketch operations + if (aOperation && myCurrentSketch) { + if (!PartSet_Tools::sketchPlane(myCurrentSketch)) + return; -void PartSet_Module::onFitAllView() -{ - myWorkshop->viewer()->fitAll(); -} + bool isSketcher = (aOperation->id().toStdString() == SketchPlugin_Sketch::ID()); + bool isSketchOpe = sketchOperationIdList().contains(aOperation->id()); -void PartSet_Module::onRestartOperation(std::string theName, ObjectPtr theObject) -{ - FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); - - std::string aKind = aFeature ? aFeature->getKind() : ""; - ModuleBase_Operation* anOperation = createOperation(theName, aKind); - - PartSet_OperationSketchBase* aSketchOp = dynamic_cast(anOperation); - if (aSketchOp) { - PartSet_OperationFeatureCreate* aCreateOp = dynamic_cast(anOperation); - if (aCreateOp) - aCreateOp->initFeature(aFeature); - else { - anOperation->setFeature(aFeature); + // Avoid non-sketch operations + if ((!isSketchOpe) && (!isSketcher)) + return; + + bool isEditing = aOperation->isEditOperation(); + + // Ignore creation sketch operation + if ((!isSketcher) && (!isEditing)) + return; + + if (theEvent->modifiers()) { + // If user performs multiselection + if (isSketchOpe && (!isSketcher)) + if (!aOperation->commit()) + aOperation->abort(); + return; } - ModuleBase_ISelection* aSelection = workshop()->selection(); - // Initialise operation with preliminary selection - aSketchOp->initSelection(aSelection, myWorkshop->viewer()); - } else if (aFeature) { // In case of edit operation: set the previously created feature to the operation - anOperation->setFeature(aFeature); - ////Deactivate result of current feature in order to avoid its selection - XGUI_Displayer* aDisplayer = xWorkshop()->displayer(); - std::list aResults = aFeature->results(); - std::list::const_iterator aIt; - for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) { - aDisplayer->deactivate(*aIt); + // Remember highlighted objects for editing + ModuleBase_ISelection* aSelect = myWorkshop->selection(); + QList aHighlighted = aSelect->getHighlighted(); + QList aSelected = aSelect->getSelected(); + myEditingFeatures.clear(); + myEditingAttr.clear(); + if ((aHighlighted.size() == 0) && (aSelected.size() == 0)) { + if (isSketchOpe && (!isSketcher)) + // commit previous operation + if (!aOperation->commit()) + aOperation->abort(); + return; + } + + QObjectPtrList aSelObjects = getSumList(aHighlighted, aSelected); + if ((aHighlighted.size() == 1) && (aSelected.size() == 0)) { + // Move by selected shape (vertex). Can be used only for single selection + foreach(ModuleBase_ViewerPrs aPrs, aHighlighted) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aHighlighted.first().object()); + if (aFeature) { + myEditingFeatures.append(aFeature); + TopoDS_Shape aShape = aPrs.shape(); + if (!aShape.IsNull()) { + if (aShape.ShapeType() == TopAbs_VERTEX) { + AttributePtr aAttr = PartSet_Tools::findAttributeBy2dPoint(myEditingFeatures.first(), + aShape, myCurrentSketch); + if (aAttr) + myEditingAttr.append(aAttr); + } + } + } + } + } else { + // Provide multi-selection. Can be used only for features + foreach (ObjectPtr aObj, aSelObjects) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aObj); + if (aFeature && (!myEditingFeatures.contains(aFeature))) + myEditingFeatures.append(aFeature); + } + + } + // If nothing highlighted - return + if (myEditingFeatures.size() == 0) + return; + + if (isSketcher) { + myIsDragging = true; + get2dPoint(theWnd, theEvent, myCurX, myCurY); + myDragDone = false; + myWorkshop->viewer()->enableSelection(false); + launchEditing(); + + } else if (isSketchOpe && isEditing) { + // If selected another object + aOperation->abort(); + + myIsDragging = true; + get2dPoint(theWnd, theEvent, myCurX, myCurY); + myDragDone = false; + myWorkshop->viewer()->enableSelection(false); + + // This is necessary in order to finalize previous operation + QApplication::processEvents(); + launchEditing(); } } - sendOperation(anOperation); - xWorkshop()->actionsMgr()->updateCheckState(); } -void PartSet_Module::onMultiSelectionEnabled(bool theEnabled) -{ - ModuleBase_IViewer* aViewer = myWorkshop->viewer(); - aViewer->enableMultiselection(theEnabled); -} -void PartSet_Module::onStopSelection(const QList& theFeatures, const bool isStop) +void PartSet_Module::get2dPoint(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent, + double& theX, double& theY) { - XGUI_Displayer* aDisplayer = xWorkshop()->displayer(); - //if (!isStop) { - // foreach(ObjectPtr aObject, theFeatures) { - // activateFeature(aObject); - // } - //} - aDisplayer->stopSelection(theFeatures, isStop, false); - - ModuleBase_IViewer* aViewer = myWorkshop->viewer(); - aViewer->enableSelection(!isStop); - - aDisplayer->updateViewer(); + Handle(V3d_View) aView = theWnd->v3dView(); + gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView); + PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, theX, theY); } -void PartSet_Module::onSetSelection(const QList& theFeatures) -{ - XGUI_Displayer* aDisplayer = xWorkshop()->displayer(); - aDisplayer->setSelected(theFeatures, false); - aDisplayer->updateViewer(); -} -void PartSet_Module::setSketchingMode(const gp_Pln& thePln) +void PartSet_Module::launchEditing() { - XGUI_Displayer* aDisplayer = xWorkshop()->displayer(); - if (!myPlaneFilter.IsNull()) { - aDisplayer->removeSelectionFilter(myPlaneFilter); - myPlaneFilter.Nullify(); + if (myEditingFeatures.size() > 0) { + FeaturePtr aFeature = myEditingFeatures.first(); + std::shared_ptr aSPFeature = + std::dynamic_pointer_cast(aFeature); + if (aSPFeature) { + editFeature(aSPFeature); + } } - QIntList aModes; - // Clear standard selection modes - aDisplayer->setSelectionModes(aModes); - aDisplayer->openLocalContext(); - - // Set filter - mySketchFilter = new ModuleBase_ShapeInPlaneFilter(thePln); - aDisplayer->addSelectionFilter(mySketchFilter); - - // Get default selection modes - aModes = sketchSelectionModes(ObjectPtr()); - aDisplayer->activateObjectsOutOfContext(aModes); } -void PartSet_Module::onFeatureConstructed(ObjectPtr theFeature, int theMode) +/// Returns new instance of operation object (used in createOperation for customization) +ModuleBase_Operation* PartSet_Module::getNewOperation(const std::string& theFeatureId) { - bool isDisplay = theMode != PartSet_OperationSketchBase::FM_Hide; - ModuleBase_Operation* aCurOperation = myWorkshop->currentOperation(); - PartSet_OperationSketchBase* aPrevOp = dynamic_cast(aCurOperation); - if (aPrevOp) { - std::list aList = aPrevOp->subFeatures(); - XGUI_Displayer* aDisplayer = xWorkshop()->displayer(); - QIntList aModes = sketchSelectionModes(aPrevOp->feature()); - std::list::iterator aSFIt; - for (aSFIt = aList.begin(); aSFIt != aList.end(); ++aSFIt) { - std::list aResults = (*aSFIt)->results(); - std::list::iterator aIt; - for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { - if (!isDisplay) - aDisplayer->erase((*aIt), false); - } - if (!isDisplay) - aDisplayer->erase((*aSFIt), false); - } - //aDisplayer->deactivateObjectsOutOfContext(); + if (theFeatureId == PartSet_OperationSketch::Type()) { + return new PartSet_OperationSketch(theFeatureId.c_str(), this); } - if (isDisplay) - ModelAPI_EventCreator::get()->sendUpdated( - theFeature, Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)); + return ModuleBase_IModule::getNewOperation(theFeatureId); } -ModuleBase_Operation* PartSet_Module::createOperation(const std::string& theCmdId, - const std::string& theFeatureKind) + +void PartSet_Module::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) { - // create the operation - ModuleBase_Operation* anOperation = 0; - if (theCmdId == PartSet_OperationSketch::Type()) { - anOperation = new PartSet_OperationSketch(theCmdId.c_str(), this); - } else { - ModuleBase_Operation* aCurOperation = myWorkshop->currentOperation(); - CompositeFeaturePtr aSketch; - PartSet_OperationSketchBase* aPrevOp = dynamic_cast(aCurOperation); - if (aPrevOp) { - aSketch = aPrevOp->sketch(); - } - if (PartSet_OperationFeatureCreate::canProcessKind(theCmdId)) { - anOperation = new PartSet_OperationFeatureCreate(theCmdId.c_str(), this, aSketch); - } else if (theCmdId == PartSet_OperationFeatureEdit::Type()) { - anOperation = new PartSet_OperationFeatureEdit(theCmdId.c_str(), this, aSketch); + myWorkshop->viewer()->enableSelection(true); + if (myIsDragging) { + myIsDragging = false; + if (myDragDone) { + myWorkshop->currentOperation()->commit(); + myEditingFeatures.clear(); + myEditingAttr.clear(); } } +} - if (!anOperation) { - anOperation = new ModuleBase_Operation(theCmdId.c_str(), this); - } - // set operation description and list of widgets corresponding to the feature xml definition - std::string aFeatureKind = theFeatureKind.empty() ? theCmdId : theFeatureKind; - - std::string aPluginFileName = featureFile(aFeatureKind); - Config_WidgetReader aWdgReader = Config_WidgetReader(aPluginFileName); - aWdgReader.readAll(); - std::string aXmlCfg = aWdgReader.featureWidgetCfg(aFeatureKind); - std::string aDescription = aWdgReader.featureDescription(aFeatureKind); - - anOperation->getDescription()->setDescription(QString::fromStdString(aDescription)); - anOperation->getDescription()->setXmlRepresentation(QString::fromStdString(aXmlCfg)); - - // connect the operation - PartSet_OperationSketchBase* aPreviewOp = dynamic_cast(anOperation); - if (aPreviewOp) { - connect(aPreviewOp, SIGNAL(featureConstructed(ObjectPtr, int)), this, - SLOT(onFeatureConstructed(ObjectPtr, int))); - connect(aPreviewOp, SIGNAL(restartRequired(std::string, ObjectPtr)), this, - SLOT(onRestartOperation(std::string, ObjectPtr))); - // If manage multi selection the it will be impossible to select more then one - // object under operation Edit -// connect(aPreviewOp, SIGNAL(multiSelectionEnabled(bool)), this, -// SLOT(onMultiSelectionEnabled(bool))); - - connect(aPreviewOp, SIGNAL(stopSelection(const QList&, const bool)), this, - SLOT(onStopSelection(const QList&, const bool))); - connect(aPreviewOp, SIGNAL(setSelection(const QList&)), this, - SLOT(onSetSelection(const QList&))); - - PartSet_OperationSketch* aSketchOp = dynamic_cast(aPreviewOp); - if (aSketchOp) { - connect(aSketchOp, SIGNAL(planeSelected(double, double, double)), this, - SLOT(onPlaneSelected(double, double, double))); - connect(aSketchOp, SIGNAL(fitAllView()), this, SLOT(onFitAllView())); - connect(aSketchOp, SIGNAL(launchSketch()), this, SLOT(onSketchLaunched())); +void PartSet_Module::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) +{ + if (myIsDragging) { + ModuleBase_Operation* aOperation = myWorkshop->currentOperation(); + if (aOperation->id().toStdString() == SketchPlugin_Sketch::ID()) + return; // No edit operation activated + + static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED); + 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 - myCurX; + double dY = aY - myCurY; + + if ((aOperation->id().toStdString() == SketchPlugin_Line::ID()) && + (myEditingAttr.size() == 1) && + myEditingAttr.first()) { + // probably we have prehighlighted point + AttributePtr aAttr = myEditingAttr.first(); + std::string aAttrId = aAttr->id(); + ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); + QList aWidgets = aPanel->modelWidgets(); + // Find corresponded widget to provide dragging + foreach (ModuleBase_ModelWidget* aWgt, aWidgets) { + if (aWgt->attributeID() == aAttrId) { + PartSet_WidgetPoint2D* aWgt2d = dynamic_cast(aWgt); + if (aWgt2d) { + aWgt2d->setPoint(aWgt2d->x() + dX, aWgt2d->y() + dY); + break; + } + } + } + } else { + foreach(FeaturePtr aFeature, myEditingFeatures) { + std::shared_ptr aSketchFeature = + std::dynamic_pointer_cast(aFeature); + if (aSketchFeature) { + aSketchFeature->move(dX, dY); + ModelAPI_EventCreator::get()->sendUpdated(aSketchFeature, anEvent); + } + } + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_MOVED)); + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); } + myDragDone = true; + myCurX = aX; + myCurY = aY; } - - return anOperation; } +void PartSet_Module::onMouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) +{ + ModuleBase_Operation* aOperation = myWorkshop->currentOperation(); + if (aOperation->isEditOperation()) { + std::string aId = aOperation->id().toStdString(); + if ((aId == SketchPlugin_ConstraintLength::ID()) || + (aId == SketchPlugin_ConstraintDistance::ID()) || + (aId == SketchPlugin_ConstraintRadius::ID())) + { + // Activate dimension value editing on double click + ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); + QList aWidgets = aPanel->modelWidgets(); + // Find corresponded widget to activate value editing + foreach (ModuleBase_ModelWidget* aWgt, aWidgets) { + if (aWgt->attributeID() == "ConstraintValue") { + aWgt->focusTo(); + return; + } + } + } + } +} -void PartSet_Module::updateCurrentPreview(const std::string& theCmdId) +void PartSet_Module::onKeyRelease(ModuleBase_IViewWindow* theWnd, QKeyEvent* theEvent) { - ModuleBase_Operation* anOperation = myWorkshop->currentOperation(); - if (!anOperation) - return; - - PartSet_OperationSketchBase* aPreviewOp = dynamic_cast(anOperation); - if (!aPreviewOp) - return; + XGUI_ModuleConnector* aConnector = dynamic_cast(workshop()); + XGUI_OperationMgr* anOpMgr = aConnector->workshop()->operationMgr(); + anOpMgr->onKeyReleased(theEvent); +} - FeaturePtr aFeature = aPreviewOp->feature(); - if (!aFeature || aFeature->getKind() != theCmdId) - return; +void PartSet_Module::onEnterReleased() +{ + myRestartingMode = RM_EmptyFeatureUsed; +} - XGUI_Displayer* aDisplayer = xWorkshop()->displayer(); - // Hide result of sketch - std::list aResults = aFeature->results(); - std::list::const_iterator aIt; - for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) - aDisplayer->erase(*aIt, false); - - std::list aList = aPreviewOp->subFeatures(); - - std::list::const_iterator anIt = aList.begin(), aLast = aList.end(); - for (; anIt != aLast; anIt++) { - std::shared_ptr aSPFeature = std::dynamic_pointer_cast< - SketchPlugin_Feature>(*anIt); - if (!aSPFeature) - continue; - std::list aResults = aSPFeature->results(); - std::list::const_iterator aRIt; - for (aRIt = aResults.cbegin(); aRIt != aResults.cend(); ++aRIt) { - aDisplayer->display((*aRIt), false); - aDisplayer->activate((*aRIt), sketchSelectionModes((*aRIt))); +void PartSet_Module::onNoMoreWidgets() +{ + ModuleBase_Operation* aOperation = myWorkshop->currentOperation(); + if (aOperation) { + /// Restart sketcher operations automatically + FeaturePtr aFeature = aOperation->feature(); + std::shared_ptr aSPFeature = + std::dynamic_pointer_cast(aFeature); + if (aSPFeature) { + if (myRestartingMode != RM_Forbided) + myRestartingMode = RM_LastFeatureUsed; + aOperation->commit(); } - aDisplayer->display(aSPFeature, false); - aDisplayer->activate(aSPFeature, sketchSelectionModes(aSPFeature)); } - aDisplayer->updateViewer(); } -void PartSet_Module::editFeature(FeaturePtr theFeature) +QStringList PartSet_Module::sketchOperationIdList() const { - if (!theFeature) - return; - -// if (theFeature->getKind() == SKETCH_KIND) { - //FeaturePtr aFeature = theFeature; - //if (XGUI_Tools::isModelObject(aFeature)) { - // ObjectPtr aObject = std::dynamic_pointer_cast(aFeature); - // aFeature = aObject->featureRef(); - //} - - //if (aFeature) { - onRestartOperation(theFeature->getKind(), theFeature); - updateCurrentPreview(theFeature->getKind()); - //} -// } + QStringList aIds; + aIds << SketchPlugin_Line::ID().c_str(); + aIds << SketchPlugin_Point::ID().c_str(); + aIds << SketchPlugin_Arc::ID().c_str(); + aIds << SketchPlugin_Circle::ID().c_str(); + aIds << SketchPlugin_ConstraintLength::ID().c_str(); + aIds << SketchPlugin_ConstraintDistance::ID().c_str(); + aIds << SketchPlugin_ConstraintRigid::ID().c_str(); + aIds << SketchPlugin_ConstraintRadius::ID().c_str(); + aIds << SketchPlugin_ConstraintPerpendicular::ID().c_str(); + aIds << SketchPlugin_ConstraintParallel::ID().c_str(); + return aIds; } -void PartSet_Module::onStorePoint2D(ObjectPtr theFeature, const std::string& theAttribute) +void PartSet_Module::onVertexSelected(ObjectPtr theObject, const TopoDS_Shape& theShape) { - FeaturePtr aFeature = std::dynamic_pointer_cast(theFeature); - - PartSet_OperationSketchBase* aPreviewOp = - dynamic_cast(myWorkshop->currentOperation()); - if (!aPreviewOp) - return; - - std::shared_ptr aPoint = std::dynamic_pointer_cast( - aFeature->data()->attribute(theAttribute)); - - PartSet_Tools::setConstraints(aPreviewOp->sketch(), aFeature, theAttribute, aPoint->x(), - aPoint->y()); + ModuleBase_Operation* aOperation = myWorkshop->currentOperation(); + if (aOperation->id().toStdString() == SketchPlugin_Line::ID()) { + /// If last line finished on vertex the lines creation sequence has to be break + ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); + const QList& aWidgets = aPanel->modelWidgets(); + if (aWidgets.last() == aPanel->activeWidget()) { + myRestartingMode = RM_Forbided; + } + } } QWidget* PartSet_Module::createWidgetByType(const std::string& theType, QWidget* theParent, - Config_WidgetAPI* theWidgetApi, + Config_WidgetAPI* theWidgetApi, std::string theParentId, QList& theModelWidgets) { + XGUI_ModuleConnector* aConnector = dynamic_cast(workshop()); + XGUI_Workshop* aWorkshop = aConnector->workshop(); if (theType == "sketch-start-label") { - PartSet_WidgetSketchLabel* aWgt = new PartSet_WidgetSketchLabel(theParent, theWidgetApi, ""); - aWgt->setOperationsMgr(xWorkshop()->operationMgr()); + PartSet_WidgetSketchLabel* aWgt = new PartSet_WidgetSketchLabel(theParent, theWidgetApi, theParentId); + aWgt->setWorkshop(aWorkshop); + connect(aWgt, SIGNAL(planeSelected(const std::shared_ptr&)), + this, SLOT(onPlaneSelected(const std::shared_ptr&))); theModelWidgets.append(aWgt); return aWgt->getControl(); - } else - return 0; -} + } else if (theType == "sketch-2dpoint_selector") { + PartSet_WidgetPoint2D* aWgt = new PartSet_WidgetPoint2D(theParent, theWidgetApi, theParentId); + aWgt->setWorkshop(aWorkshop); + aWgt->setSketch(myCurrentSketch); -XGUI_Workshop* PartSet_Module::xWorkshop() const -{ - XGUI_ModuleConnector* aConnector = dynamic_cast(workshop()); - if (aConnector) { - return aConnector->workshop(); - } - return 0; -} + connect(aWgt, SIGNAL(vertexSelected(ObjectPtr, const TopoDS_Shape&)), + this, SLOT(onVertexSelected(ObjectPtr, const TopoDS_Shape&))); + theModelWidgets.append(aWgt); + return aWgt->getControl(); -QIntList PartSet_Module::sketchSelectionModes(ObjectPtr theFeature) -{ - QIntList aModes; - FeaturePtr aFeature = std::dynamic_pointer_cast(theFeature); - if (aFeature) { - if (aFeature->getKind() == SketchPlugin_Sketch::ID()) { - aModes.append(TopAbs_FACE); - return aModes; - } else if (PartSet_Tools::isConstraintFeature(aFeature->getKind())) { - aModes.append(AIS_DSM_Text); - aModes.append(AIS_DSM_Line); - return aModes; - } - } - aModes.append(AIS_Shape::SelectionMode((TopAbs_ShapeEnum) TopAbs_VERTEX)); - aModes.append(AIS_Shape::SelectionMode((TopAbs_ShapeEnum) TopAbs_EDGE)); - return aModes; -} + } if (theType == "point2ddistance") { + PartSet_WidgetPoint2dDistance* aWgt = new PartSet_WidgetPoint2dDistance(theParent, theWidgetApi, theParentId); + aWgt->setWorkshop(aWorkshop); + aWgt->setSketch(myCurrentSketch); + + theModelWidgets.append(aWgt); + return aWgt->getControl(); + } if (theType == "sketch_shape_selector") { + PartSet_WidgetShapeSelector* aWgt = + new PartSet_WidgetShapeSelector(theParent, workshop(), theWidgetApi, theParentId); + aWgt->setSketcher(myCurrentSketch); -gp_Pln PartSet_Module::getSketchPlane(FeaturePtr theSketch) const -{ - DataPtr aData = theSketch->data(); - std::shared_ptr anOrigin = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Sketch::ORIGIN_ID())); - std::shared_ptr aNorm = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Sketch::NORM_ID())); - gp_Pnt aOrig(anOrigin->x(), anOrigin->y(), anOrigin->z()); - gp_Dir aDir(aNorm->x(), aNorm->y(), aNorm->z()); - return gp_Pln(aOrig, aDir); -} + theModelWidgets.append(aWgt); + return aWgt->getControl(); + } if (theType == "sketch_constraint_shape_selector") { + PartSet_WidgetConstraintShapeSelector* aWgt = + new PartSet_WidgetConstraintShapeSelector(theParent, workshop(), theWidgetApi, theParentId); + aWgt->setSketcher(myCurrentSketch); -void PartSet_Module::onSelectionChanged() -{ - ModuleBase_ISelection* aSelect = myWorkshop->selection(); - QList aSelected = aSelect->getSelected(); - // We need to stop edit operation if selection is cleared - if (aSelected.size() == 0) { - // do not perform commit of the current edit operation here, because - // this functionality is realized inside this operation - /*PartSet_OperationFeatureEdit* anEditOp = - dynamic_cast(myWorkshop->currentOperation()); - if (!anEditOp) - return; - anEditOp->commit();*/ - } else { - PartSet_OperationSketchBase* aSketchOp = - dynamic_cast(myWorkshop->currentOperation()); - if (aSketchOp) { - aSketchOp->selectionChanged(aSelect); - } - } + theModelWidgets.append(aWgt); + return aWgt->getControl(); + + }else + return 0; } + diff --git a/src/PartSet/PartSet_Module.h b/src/PartSet/PartSet_Module.h index b42c1a93d..bf6129997 100644 --- a/src/PartSet/PartSet_Module.h +++ b/src/PartSet/PartSet_Module.h @@ -2,13 +2,17 @@ #define PartSet_Module_H #include "PartSet.h" +#include #include #include -#include #include #include +#include +#include + #include +#include #include #include @@ -17,148 +21,124 @@ #include -class PartSet_Listener; -class ModelAPI_Feature; -class XGUI_ViewerPrs; -class XGUI_Workshop; class ModuleBase_Operation; -class GeomAPI_AISObject; +class ModuleBase_IViewWindow; class PARTSET_EXPORT PartSet_Module : public ModuleBase_IModule { Q_OBJECT - public: +/// Enumeration to specify the restart operation properties. +enum RestartingMode { + RM_None, /// the operation should not be restarted + RM_Forbided, /// the operation should not be restarted after there is no active widget + RM_LastFeatureUsed, /// the operation is restarted and use the previous feature for own initialization + RM_EmptyFeatureUsed /// the operation is restarted and does not use the previous feature +}; + +public: PartSet_Module(ModuleBase_IWorkshop* theWshop); virtual ~PartSet_Module(); - /// Reads description of features from XML file - virtual void createFeatures(); - - /// Called on creation of menu item in desktop - virtual void featureCreated(QAction* theFeature); - - std::string featureFile(const std::string&); - - /// Creates an operation and send it to loop - /// \param theCmdId the operation name - //virtual void launchOperation(const QString& theCmdId); - - /// Updates current operation preview, if it has it. - /// \param theCmdId the operation name - void updateCurrentPreview(const std::string& theCmdId); - /// Creates custom widgets for property panel virtual QWidget* createWidgetByType(const std::string& theType, QWidget* theParent, - Config_WidgetAPI* theWidgetApi, + Config_WidgetAPI* theWidgetApi, std::string theParentId, QList& theModelWidgets); - XGUI_Workshop* xWorkshop() const; - - - /// Returns list of selection modes for the given object for sketch operation - static QIntList sketchSelectionModes(ObjectPtr theFeature); - - public slots: - void onFeatureTriggered(); - /// SLOT, that is called after the operation is started. Connect on the focus activated signal - void onOperationStarted(ModuleBase_Operation* theOperation); - /// SLOT, that is called after the operation is stopped. Switched off the modfications performed - /// by the operation start - void onOperationStopped(ModuleBase_Operation* theOperation); - /// SLOT, that is called afetr the popup menu action clicked. - void onContextMenuCommand(const QString& theId, bool isChecked); - - /// SLOT, to apply to the current viewer the operation - /// \param theX the X projection value - /// \param theY the Y projection value - /// \param theZ the Z projection value - void onPlaneSelected(double theX, double theY, double theZ); - - /// SLOT, to fit all current viewer - void onFitAllView(); - - void onRestartOperation(std::string theName, ObjectPtr theFeature); + /// Call back forlast tuning of property panel before operation performance + virtual void propertyPanelDefined(ModuleBase_Operation* theOperation); - /// SLOT, to switch on/off the multi selection in the viewer - /// \param theEnabled the enabled state - void onMultiSelectionEnabled(bool theEnabled); + QStringList sketchOperationIdList() const; - /// SLOT, to stop or start selection mode for the features - /// \param theFeatures a list of features to be disabled - /// \param theToStop the boolean state whether it it stopped or non stopped - void onStopSelection(const QList& theFeatures, const bool isStop); +public slots: + /// SLOT, that is called by no more widget signal emitted by property panel + /// Set a specific flag to restart the sketcher operation + void onNoMoreWidgets(); - /// SLOT, to set selection - /// \param theFeatures a list of features to be selected - void onSetSelection(const QList& theFeatures); - - /// SLOT, Defines Sketch editing mode - /// \param thePln - plane of current sketch - void setSketchingMode(const gp_Pln& thePln); +protected slots: + /// Called when previous operation is finished + virtual void onOperationComitted(ModuleBase_Operation* theOperation); - /// SLOT, to visualize the feature in another local context mode - /// \param theFeature the feature to be put in another local context mode - /// \param theMode the mode appeared on the feature - void onFeatureConstructed(ObjectPtr theFeature, int theMode); + virtual void onOperationAborted(ModuleBase_Operation* theOperation); - /// Slot which reacts to the point 2d set to the feature. Creates a constraint - /// \param the feature - /// \param the attribute of the feature - void onStorePoint2D(ObjectPtr theFeature, const std::string& theAttribute); + virtual void onOperationStarted(ModuleBase_Operation* theOperation); - /// Called when sketch is launched - void onSketchLaunched(); + virtual void onOperationStopped(ModuleBase_Operation* theOperation); -protected slots: - /// Called on selection changed event + /// Called when previous operation is finished virtual void onSelectionChanged(); /// SLOT, that is called by mouse press in the viewer. - /// The mouse released point is sent to the current operation to be processed. + /// \param theWnd - the window where the event happens /// \param theEvent the mouse event - virtual void onMousePressed(QMouseEvent* theEvent); + void onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); /// SLOT, that is called by mouse release in the viewer. - /// The mouse released point is sent to the current operation to be processed. + /// \param theWnd - the window where the event happens /// \param theEvent the mouse event - virtual void onMouseReleased(QMouseEvent* theEvent); + void onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); /// SLOT, that is called by mouse move in the viewer. - /// The mouse moved point is sent to the current operation to be processed. + /// \param theWnd - the window where the event happens /// \param theEvent the mouse event - virtual void onMouseMoved(QMouseEvent* theEvent); + void onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); - /// SLOT, that is called by the mouse double click in the viewer. + /// SLOT, that is called by mouse double click in the viewer. + /// \param theWnd - the window where the event happens /// \param theEvent the mouse event - virtual void onMouseDoubleClick(QMouseEvent* theEvent); + void onMouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); - /// SLOT, that is called by the key in the viewer is clicked. - /// \param theEvent the mouse event - virtual void onKeyRelease(QKeyEvent* theEvent); + /// SLOT, that is called by key release in the viewer. + /// The mouse moved point is sent to the current operation to be processed. + /// \param theEvent the key event + void onKeyRelease(ModuleBase_IViewWindow* theWnd, QKeyEvent* theEvent); - protected: - /// Creates a new operation - /// \param theCmdId the operation name - /// \param theFeatureKind a kind of feature to get the feature xml description - ModuleBase_Operation* createOperation(const std::string& theCmdId, - const std::string& theFeatureKind = ""); + /// SLOT, that is called by enter key released + /// Set a specific type of restarting the current operation + void onEnterReleased(); + /// Launches the operation from current highlighting + void launchEditing(); protected: - //! Edits the feature - void editFeature(FeaturePtr theFeature); + /// Returns new instance of operation object (used in createOperation for customization) + virtual ModuleBase_Operation* getNewOperation(const std::string& theFeatureId); - gp_Pln getSketchPlane(FeaturePtr theSketch) const; + /// Register validators for this module + virtual void registerValidators(); + + private slots: + void onVertexSelected(ObjectPtr theObject, const TopoDS_Shape& theShape); + + void onPlaneSelected(const std::shared_ptr& thePln); private: - //XGUI_Workshop* myWorkshop; - PartSet_Listener* myListener; + /// Converts mouse position to 2d coordinates. + /// Member myCurrentSketch has to be correctly defined + void get2dPoint(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent, + double& theX, double& theY); + + /// Breaks sequense of automatically resterted operations + void breakOperationSequence(); + + private: + QString myLastOperationId; + FeaturePtr myLastFeature; + + bool myIsDragging; + bool myDragDone; + + // Automatical restarting mode flag + RestartingMode myRestartingMode; - std::map myFeaturesInFiles; + double myCurX, myCurY; + CompositeFeaturePtr myCurrentSketch; + QList myEditingFeatures; + QList myEditingAttr; - Handle(StdSelect_FaceFilter) myPlaneFilter; - Handle(ModuleBase_ShapeInPlaneFilter) mySketchFilter; + Handle(ModuleBase_ShapeInPlaneFilter) myPlaneFilter; + /// A filter which provides selection within a current document or whole PartSet + Handle(PartSet_GlobalFilter) myDocumentShapeFilter; }; #endif diff --git a/src/PartSet/PartSet_Operation.cpp b/src/PartSet/PartSet_Operation.cpp new file mode 100644 index 000000000..efe1c95c7 --- /dev/null +++ b/src/PartSet/PartSet_Operation.cpp @@ -0,0 +1,17 @@ +// File: PartSet_Operation.cpp +// Created: 24 Nov 2014 +// Author: Vitaly SMETANNIKOV + +#include "PartSet_Operation.h" + +#include +#include + +void PartSet_Operation::onSelectionChanged() +{ + if (isEditOperation()) { + ModuleBase_ISelection* aSelection = myWorkshop->selection(); + QList aHighlighted = aSelection->getHighlighted(); + QList aSelected = aSelection->getSelected(); + } +} \ No newline at end of file diff --git a/src/PartSet/PartSet_Operation.h b/src/PartSet/PartSet_Operation.h new file mode 100644 index 000000000..cac4bdd28 --- /dev/null +++ b/src/PartSet/PartSet_Operation.h @@ -0,0 +1,30 @@ +// File: PartSet_Operation.h +// Created: 24 Nov 2014 +// Author: Vitaly SMETANNIKOV + +#ifndef PartSet_Operation_H +#define PartSet_Operation_H + +#include "PartSet.h" + +#include + +class ModuleBase_IWorkshop; + +class PARTSET_EXPORT PartSet_Operation : public ModuleBase_Operation +{ +Q_OBJECT + public: + PartSet_Operation(const QString& theId = "", QObject* theParent = 0) + :ModuleBase_Operation(theId, theParent) {} + + void setWorkshop(ModuleBase_IWorkshop* theWorkshop) { myWorkshop = theWorkshop; } + +public slots: + void onSelectionChanged(); + +private: + ModuleBase_IWorkshop* myWorkshop; +}; + +#endif \ No newline at end of file diff --git a/src/PartSet/PartSet_OperationFeatureBase.cpp b/src/PartSet/PartSet_OperationFeatureBase.cpp deleted file mode 100644 index 65689f2e6..000000000 --- a/src/PartSet/PartSet_OperationFeatureBase.cpp +++ /dev/null @@ -1,126 +0,0 @@ -// File: PartSet_OperationFeatureBase.h -// Created: 20 Apr 2014 -// Author: Natalia ERMOLAEVA - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include "ModuleBase_IPropertyPanel.h" -#include "ModuleBase_ISelection.h" -#include "ModuleBase_IViewer.h" - -#include - -#include -#include - -#ifdef _DEBUG -#include -#include -#endif - -#include - -using namespace std; - -PartSet_OperationFeatureBase::PartSet_OperationFeatureBase(const QString& theId, - QObject* theParent, - CompositeFeaturePtr theFeature) - : PartSet_OperationSketchBase(theId, theParent), - mySketch(theFeature) -{ -} - -PartSet_OperationFeatureBase::~PartSet_OperationFeatureBase() -{ -} - -CompositeFeaturePtr PartSet_OperationFeatureBase::sketch() const -{ - return mySketch; -} - -void PartSet_OperationFeatureBase::mouseReleased(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, - ModuleBase_ISelection* theSelection) -{ - Handle(V3d_View) aView = theViewer->activeView(); - gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView); - double aX = aPoint.X(), anY = aPoint.Y(); - QList aSelected = theSelection->getSelected(); - - if (aSelected.empty()) { - PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY); - } else { - ModuleBase_ViewerPrs aPrs = aSelected.first(); - if (getViewerPoint(aPrs, theViewer, aX, anY)) { - ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget(); - PartSet_Tools::setConstraints(sketch(), feature(), aActiveWgt->attributeID(), aX, anY); - } - const TopoDS_Shape& aShape = aPrs.shape(); - if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_EDGE) { // a line is selected - PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY); - } - } - ObjectPtr aFeature; - if (!aSelected.empty()) { - ModuleBase_ViewerPrs aPrs = aSelected.first(); - aFeature = aPrs.object(); - } else { - aFeature = feature(); // for the widget distance only - } - - bool isApplyed = setWidgetValue(aFeature, aX, anY); - if (isApplyed) { - flushUpdated(); - myPropertyPanel->activateNextWidget(); - } - // the operation can be committed only when there is no an active widget anymore - // if this check is absent, the edit operation for constraint perpendicular is stopped - // after the first object selection in the viewer(there are two objects to be selected) - // the second case is the constraint distance, the edit is stopped after any mouse click - // in the viewer whenever it is applyed or not to the selection control - if (!myPropertyPanel->activeWidget()) - commit(); -} - -bool PartSet_OperationFeatureBase::getViewerPoint(ModuleBase_ViewerPrs thePrs, - ModuleBase_IViewer* theViewer, - double& theX, double& theY) -{ - return PartSet_Tools::hasVertexShape(thePrs, sketch(), theViewer->activeView(), - theX, theY); -} - -/*bool PartSet_OperationFeatureBase::setWidgetValue(ObjectPtr theFeature, double theX, double theY) -{ - ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget(); - if (!aActiveWgt) - return false; - ModuleBase_WidgetValueFeature* aValue = new ModuleBase_WidgetValueFeature(); - aValue->setObject(theFeature); - aValue->setPoint(std::shared_ptr(new GeomAPI_Pnt2d(theX, theY))); - bool isApplyed = aActiveWgt->setValue(aValue); - - delete aValue; - myIsModified = (myIsModified || isApplyed); - return isApplyed; -}*/ diff --git a/src/PartSet/PartSet_OperationFeatureBase.h b/src/PartSet/PartSet_OperationFeatureBase.h deleted file mode 100644 index ee290dd44..000000000 --- a/src/PartSet/PartSet_OperationFeatureBase.h +++ /dev/null @@ -1,63 +0,0 @@ -// File: PartSet_OperationFeatureBase.h -// Created: 20 Apr 2014 -// Author: Natalia ERMOLAEVA - -#ifndef PARTSET_OPERATIONFEATUREBASE_H -#define PARTSET_OPERATIONFEATUREBASE_H - -#include "PartSet.h" - -#include -#include - -#include - -class GeomDataAPI_Point2D; -class QMouseEvent; -class QKeyEvent; - -/*! - \class PartSet_OperationFeatureBase - * \brief The operation for the sketch feature creation - */ -class PARTSET_EXPORT PartSet_OperationFeatureBase : public PartSet_OperationSketchBase -{ -Q_OBJECT - - public: - /// Constructor - /// \param theId the feature identifier - /// \param theParent the operation parent - /// \param theSketch the parent feature - PartSet_OperationFeatureBase(const QString& theId, QObject* theParent, CompositeFeaturePtr theSketch); - /// Destructor - virtual ~PartSet_OperationFeatureBase(); - - /// Returns the operation sketch feature - /// \returns the sketch instance - virtual CompositeFeaturePtr sketch() const; - - /// Gives the current selected objects to be processed by the operation - /// \param theEvent the mouse event - /// \param theView a viewer to have the viewer the eye position - /// \param theSelected the list of selected presentations - /// \param theHighlighted the list of highlighted presentations - virtual void mouseReleased(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, - ModuleBase_ISelection* theSelection); - - protected: - /// Return a widget value point by the selection and the viewer position - /// \param thePrs the presentation - /// \param theViewer a viewer to have the viewer the eye position - /// \param theX the horizontal coordinate - /// \param theY the vertical coordinate - /// \return true if the point exits in the selection - virtual bool getViewerPoint(ModuleBase_ViewerPrs thePrs, - ModuleBase_IViewer* theViewer, - double& theX, double& theY); - - protected: - CompositeFeaturePtr mySketch; ///< the sketch of the feature -}; - -#endif diff --git a/src/PartSet/PartSet_OperationFeatureCreate.cpp b/src/PartSet/PartSet_OperationFeatureCreate.cpp deleted file mode 100644 index 8e18b6754..000000000 --- a/src/PartSet/PartSet_OperationFeatureCreate.cpp +++ /dev/null @@ -1,195 +0,0 @@ -// File: PartSet_OperationFeatureCreate.h -// Created: 20 Apr 2014 -// 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 - -#ifdef _DEBUG -#include -#include -#endif - -#include - -using namespace std; - -PartSet_OperationFeatureCreate::PartSet_OperationFeatureCreate(const QString& theId, - QObject* theParent, - CompositeFeaturePtr theFeature) - : PartSet_OperationFeatureBase(theId, theParent, theFeature) -{ -} - -PartSet_OperationFeatureCreate::~PartSet_OperationFeatureCreate() -{ -} - -bool PartSet_OperationFeatureCreate::canProcessKind(const std::string& theId) -{ - return theId == SketchPlugin_Line::ID() || theId == SketchPlugin_Point::ID() - || theId == SketchPlugin_Circle::ID() || theId == SketchPlugin_Arc::ID() - || theId == SketchPlugin_ConstraintDistance::ID() - || theId == SketchPlugin_ConstraintLength::ID() - || theId == SketchPlugin_ConstraintRadius::ID() - || theId == SketchPlugin_ConstraintParallel::ID() - || theId == SketchPlugin_ConstraintPerpendicular::ID() - || theId == SketchPlugin_ConstraintCoincidence::ID() - || theId == SketchPlugin_ConstraintRigid::ID(); -} - -void PartSet_OperationFeatureCreate::mouseMoved(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer) -{ - double aX, anY; - Handle(V3d_View) aView = theViewer->activeView(); - gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView); - PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY); - setWidgetValue(feature(), aX, anY); - flushUpdated(); -} - -void PartSet_OperationFeatureCreate::keyReleased(const int theKey) -{ - switch (theKey) { - case Qt::Key_Return: - case Qt::Key_Enter: { - // it start a new line creation at a free point - if(isValid()) - restartOperation(feature()->getKind()); - } - break; - default: - break; - } -} - -void PartSet_OperationFeatureCreate::mouseReleased(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, - ModuleBase_ISelection* theSelection) -{ - Handle(V3d_View) aView = theViewer->activeView(); - gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView); - double aX = aPoint.X(), anY = aPoint.Y(); - bool isClosedContour = false; - - QList aSelected = theSelection->getSelected(); - - if (aSelected.empty()) { - PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY); - } else { - ModuleBase_ViewerPrs aPrs = aSelected.first(); - if (getViewerPoint(aPrs, theViewer, aX, anY)) { - ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget(); - PartSet_Tools::setConstraints(sketch(), feature(), aActiveWgt->attributeID(), aX, anY); - isClosedContour = true; - } - const TopoDS_Shape& aShape = aPrs.shape(); - if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_EDGE) { // a line is selected - ObjectPtr aObject = aPrs.object(); - if (sketch()->isSub(aObject)) - PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY); - else { - // we have to create the selected edge for the current sketch - ResultPtr aRes = PartSet_Tools::createFixedObjectByEdge(aPrs, sketch()); - aSelected.first().setFeature(aRes); - } - } - } - ObjectPtr aFeature; - if (!aSelected.empty()) { - ModuleBase_ViewerPrs aPrs = aSelected.first(); - aFeature = aPrs.object(); - } else { - aFeature = feature(); // for the widget distance only - } - - bool isApplyed = setWidgetValue(aFeature, aX, anY); - if (isApplyed) { - flushUpdated(); - myPropertyPanel->activateNextWidget(); - } - - if (!myPropertyPanel->activeWidget()) { - if(commit() && !isClosedContour) { - // if the point creation is finished, the next mouse release should commit the modification - // the next release can happens by double click in the viewer - restartOperation(feature()->getKind(), feature()); - } - } -} - -void PartSet_OperationFeatureCreate::startOperation() -{ - PartSet_OperationSketchBase::startOperation(); - //emit multiSelectionEnabled(false); -} - -void PartSet_OperationFeatureCreate::abortOperation() -{ - emit featureConstructed(feature(), FM_Hide); - PartSet_OperationSketchBase::abortOperation(); -} - -void PartSet_OperationFeatureCreate::stopOperation() -{ - PartSet_OperationSketchBase::stopOperation(); - //emit multiSelectionEnabled(true); -} - -void PartSet_OperationFeatureCreate::afterCommitOperation() -{ - PartSet_OperationSketchBase::afterCommitOperation(); - emit featureConstructed(feature(), FM_Deactivation); -} - -FeaturePtr PartSet_OperationFeatureCreate::createFeature(const bool theFlushMessage, - CompositeFeaturePtr theCompositeFeature) -{ - FeaturePtr aNewFeature = ModuleBase_Operation::createFeature(false, sketch()); - - if (theFlushMessage) - flushCreated(); - return aNewFeature; -} - - -void PartSet_OperationFeatureCreate::onWidgetActivated(ModuleBase_ModelWidget* theWidget) -{ - PartSet_OperationFeatureBase::onWidgetActivated(theWidget); - if (myInitFeature && theWidget) { - ModuleBase_WidgetPoint2D* aWgt = dynamic_cast(theWidget); - if (aWgt && aWgt->initFromPrevious(myInitFeature)) { - myInitFeature = FeaturePtr(); - if (myPropertyPanel) - myPropertyPanel->activateNextWidget(); - } - } -} diff --git a/src/PartSet/PartSet_OperationFeatureCreate.h b/src/PartSet/PartSet_OperationFeatureCreate.h deleted file mode 100644 index 45e29505e..000000000 --- a/src/PartSet/PartSet_OperationFeatureCreate.h +++ /dev/null @@ -1,96 +0,0 @@ -// File: PartSet_OperationFeatureCreate.h -// Created: 20 Apr 2014 -// Author: Natalia ERMOLAEVA - -#ifndef PartSet_OperationFeatureCreate_H -#define PartSet_OperationFeatureCreate_H - -#include "PartSet.h" - -#include -#include - -#include - -class GeomDataAPI_Point2D; -class QMouseEvent; -class QKeyEvent; - -/*! - \class PartSet_OperationFeatureCreate - * \brief The operation for the sketch feature creation - */ -class PARTSET_EXPORT PartSet_OperationFeatureCreate : public PartSet_OperationFeatureBase -{ -Q_OBJECT - - public: - /// Returns true if the feature with the given kind can be created by this operation - /// \param theId the feature kind - /// \return the boolean result - static bool canProcessKind(const std::string& theId); - - /// Constructor - /// \param theId the feature identifier - /// \param theParent the operation parent - /// \param theSketch the parent feature - PartSet_OperationFeatureCreate( - const QString& theId, QObject* theParent, CompositeFeaturePtr theSketch); - /// Destructor - virtual ~PartSet_OperationFeatureCreate(); - - /// Gives the current mouse point in the viewer - /// \param thePoint a point clicked in the viewer - /// \param theEvent the mouse event - virtual void mouseMoved(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer); - - /// Gives the current selected objects to be processed by the operation - /// \param theEvent the mouse event - /// \param theView a viewer to have the viewer the eye position - /// \param theSelected the list of selected presentations - /// \param theHighlighted the list of highlighted presentations - virtual void mouseReleased(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, - ModuleBase_ISelection* theSelection); - /// Processes the key pressed in the view - /// \param theKey a key value - virtual void keyReleased(const int theKey); - - /// Initializes the operation with previously created feature. It is used in sequental operations - void initFeature(FeaturePtr theFeature) { myInitFeature = theFeature; } - - public slots: - /// Slots which listen the mode widget activation - /// \param theWidget the model widget - virtual void onWidgetActivated(ModuleBase_ModelWidget* theWidget); - - protected: - /// \brief Virtual method called when operation is started - /// Virtual method called when operation started (see start() method for more description) - /// After the parent operation body perform, set sketch feature to the created line feature - virtual void startOperation(); - - /// Virtual method called when operation aborted (see abort() method for more description) - /// Before the feature is aborted, it should be hidden from the viewer - virtual void abortOperation(); - - /// Virtual method called when operation stopped - committed or aborted. - /// Restore the multi selection state - virtual void stopOperation(); - - /// Virtual method called after operation committed (see commit() method for more description) - virtual void afterCommitOperation(); - - /// Creates an operation new feature - /// In addition to the default realization it appends the created line feature to - /// the sketch feature - /// \param theFlushMessage the flag whether the create message should be flushed - /// \returns the created feature - virtual FeaturePtr createFeature(const bool theFlushMessage = true, - CompositeFeaturePtr theCompositeFeature = CompositeFeaturePtr()); - -protected: - /// Feature of previous operation (for sequintal operations) - FeaturePtr myInitFeature; -}; - -#endif diff --git a/src/PartSet/PartSet_OperationFeatureEdit.cpp b/src/PartSet/PartSet_OperationFeatureEdit.cpp deleted file mode 100644 index d44dfa3d7..000000000 --- a/src/PartSet/PartSet_OperationFeatureEdit.cpp +++ /dev/null @@ -1,521 +0,0 @@ -// File: PartSet_OperationFeatureEdit.h -// Created: 05 May 2014 -// Author: Natalia ERMOLAEVA - -#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 - -using namespace std; - -PartSet_OperationFeatureEdit::PartSet_OperationFeatureEdit(const QString& theId, - QObject* theParent, - CompositeFeaturePtr theFeature) - : PartSet_OperationFeatureBase(theId, theParent, theFeature), - myIsBlockedSelection(false), myIsBlockedByDoubleClick(false) -{ - myIsEditing = true; -} - -PartSet_OperationFeatureEdit::~PartSet_OperationFeatureEdit() -{ -} - -void PartSet_OperationFeatureEdit::initSelection(ModuleBase_ISelection* theSelection, - ModuleBase_IViewer* theViewer) -{ - // the method of the parent should is useless here because it processes the given - // selection in different way - //PartSet_OperationFeatureBase::initSelection(theSelection, theViewer); - - QList aSelected = theSelection->getSelected(); - QList aHighlighted = theSelection->getHighlighted(); - - // there is a bug in OCC, where the highlighted objects are repeated and should be - // filtered on the unique state here - QList anUniqueHighlighted; - foreach (ModuleBase_ViewerPrs aPrs, aHighlighted) { - if (!PartSet_Tools::isContainPresentation(anUniqueHighlighted, aPrs)) - anUniqueHighlighted.append(aPrs); - } - fillFeature2Attribute(anUniqueHighlighted, theViewer, myHighlightedFeature2Attribute); - - foreach (ModuleBase_ViewerPrs aPrs, anUniqueHighlighted) { - if (!PartSet_Tools::isContainPresentation(aSelected, aPrs)) - aSelected.append(aPrs); - } - fillFeature2Attribute(aSelected, theViewer, myAllFeature2Attribute); -} - -void PartSet_OperationFeatureEdit::fillFeature2Attribute( - const QList& thePresentations, - ModuleBase_IViewer* theViewer, - std::map >& theFeature2Attribute) -{ - // 1. find all features with skipping features with selected vertex shapes - theFeature2Attribute.clear(); - // firstly, collect the features without local selection - double aX, anY; - foreach (ModuleBase_ViewerPrs aPrs, thePresentations) { - if (getViewerPoint(aPrs, theViewer, aX, anY)) - continue; - else { - ObjectPtr aObject = aPrs.object(); - if (!aObject) - continue; - FeaturePtr aFeature = ModelAPI_Feature::feature(aObject); - if (aFeature && theFeature2Attribute.find(aFeature) == theFeature2Attribute.end()) { - std::list aList; - // using an empty list as a sign, that this feature should be moved itself - theFeature2Attribute[aFeature] = aList; - } - } - } - // 2. collect the features with a local selection on them. - // if the list already has this feature, the local selection is skipped - // that means that if the selection contains a feature and a feature with local selected point, - // the edit is performed for a full feature - foreach (ModuleBase_ViewerPrs aPrs, thePresentations) { - if (getViewerPoint(aPrs, theViewer, aX, anY)) { - ObjectPtr aObject = aPrs.object(); - if (!aObject) - continue; - FeaturePtr aFeature = ModelAPI_Feature::feature(aObject); - if (!aFeature) - continue; - - // append the attribute of the vertex if it is found on the current feature - std::shared_ptr aPoint2D = PartSet_Tools::getFeaturePoint( - aFeature, aX, anY); - std::string anAttribute = aFeature->data()->id(aPoint2D); - std::list aList; - if (theFeature2Attribute.find(aFeature) != theFeature2Attribute.end()) - aList = theFeature2Attribute[aFeature]; - - aList.push_back(anAttribute); - theFeature2Attribute[aFeature] = aList; - } - } -} - -void PartSet_OperationFeatureEdit::mousePressed(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, ModuleBase_ISelection* theSelection) -{ - ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget(); - if(aActiveWgt && aActiveWgt->isViewerSelector()) { - // Almost do nothing, all stuff in on PartSet_OperationFeatureBase::mouseReleased - PartSet_OperationFeatureBase::mousePressed(theEvent, theViewer, theSelection); - // the current point should be cleared because it is saved from the previous move and - // should be reinitialized after the start moving. It is important for example for the lenght - // constraint where the first widget is a viewer selector. - myCurPoint.clear(); - } - else { - // commit always until the selection restore is realized (for feature and local selection) - // TODO: check whether the selection is changed and restart the operation only if it is modified - commit(); - emitFeaturesDeactivation(); - // find nearest feature and restart the operation for it - Handle(V3d_View) aView = theViewer->activeView(); - QList aSelected = theSelection->getSelected(); - QList aHighlighted = theSelection->getHighlighted(); - - ObjectPtr aFeature = PartSet_Tools::nearestFeature(theEvent->pos(), aView, sketch(), - aSelected, aHighlighted); - if (aFeature) { - restartOperation(PartSet_OperationFeatureEdit::Type(), aFeature); - } - } - // the next code is commented because the new attempt to commit/restart operation implementation: - //QList aSelected = theSelection->getSelected(); - //QList aHighlighted = theSelection->getHighlighted(); - //bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier); - //if (aHasShift && !aHighlighted.empty()) { - // foreach (ModuleBase_ViewerPrs aPrs, aHighlighted) { - // aSelected.append(aPrs); - // } - //} - //ObjectPtr aObject; - ///*if (!aSelected.empty()) { - // aObject = aSelected.first().object(); - //} else { - // if (!aHighlighted.empty()) - // aObject = aHighlighted.first().object(); - //}*/ - //// the priority to a highlighted object in order to edit it, even if the selected object is - //// the feature of this operation. Otherwise, the highlighting is ignored and the selected - //// object is moved - //if (!aHighlighted.empty()) { - // aObject = aHighlighted.front().object(); - //} - //if (!aObject && !aSelected.empty()) // changed for a constrain - // aObject = aSelected.front().object(); - - //FeaturePtr aFeature = ModelAPI_Feature::feature(aObject); - //if (!aFeature || aFeature != feature() || (aSelected.size() > 1)) { - // if (commit()) { - // theViewer->enableSelection(true); - // emit featureConstructed(feature(), FM_Deactivation); - - // // If we have selection and prehilighting with shift pressed - // // Then we have to select all these objects and restart as multi edit operfation - // //bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier); - // //if (aHasShift && !theHighlighted.empty()) { - // // QList aSelected; - // // std::list::const_iterator aIt; - // // for (aIt = theSelected.cbegin(); aIt != theSelected.cend(); ++aIt) - // // aSelected.append((*aIt).object()); - - // // for (aIt = theHighlighted.cbegin(); aIt != theHighlighted.cend(); ++aIt) { - // // if (!aSelected.contains((*aIt).object())) - // // aSelected.append((*aIt).object()); - // // } - // // emit setSelection(aSelected); - // //} else - // if (aFeature) { - // std::string anOperationType = PartSet_OperationFeatureEdit::Type(); - // restartOperation(anOperationType, aFeature); - // } - // //} - // } - //} -} - -void PartSet_OperationFeatureEdit::mouseMoved(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer) -{ - if (!(theEvent->buttons() & Qt::LeftButton)) - return; - Handle(V3d_View) aView = theViewer->activeView(); - gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView); - - theViewer->enableSelection(false); - - //blockSelection(true); - if (myCurPoint.myIsInitialized) { - double aCurX, aCurY; - PartSet_Tools::convertTo2D(myCurPoint.myPoint, sketch(), aView, aCurX, aCurY); - - double aX, anY; - PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY); - - double aDeltaX = aX - aCurX; - double aDeltaY = anY - aCurY; - - // the next code is commented because it is obsolete by the multi edit operation realization here - //if (myIsMultiOperation) { - // std::map>::iterator aFeatIter = myFeature2Attribute.begin(); - // while (aFeatIter != myFeature2Attribute.end()) { - // FeaturePtr aFeature = aFeatIter->first; - // std::list anAttributes = aFeatIter->second; - // // perform edit for the feature - // if (anAttributes.empty()) { - // std::shared_ptr aSketchFeature = - // std::dynamic_pointer_cast(aFeature); - // if (aSketchFeature) { - // aSketchFeature->move(aDeltaX, aDeltaY); - // } - // } - // // perform edit for the feature's attribute - // else { - // std::list::const_iterator anAttrIter = anAttributes.begin(), - // anAttrEnd = anAttributes.end(); - // for (; anAttrIter != anAttrEnd; anAttrIter++) { - // std::shared_ptr aPointAttr = std::dynamic_pointer_cast< - // GeomDataAPI_Point2D>(aFeature->data()->attribute(*anAttrIter)); - // if (aPointAttr) { - // aPointAttr->move(aDeltaX, aDeltaY); - // } - // } - // } - // aFeatIter++; - // } - //} - //else { // multieditoperation - - //std::shared_ptr aSketchFeature = std::dynamic_pointer_cast< - // SketchPlugin_Feature>(feature()); - - bool isMoved = false; - bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier); - - // the functionality to move the feature attribute if it exists in the internal map - std::map>::iterator aFeatIter, aFeatLast; - if (aHasShift || myHighlightedFeature2Attribute.empty()) { - aFeatIter = myAllFeature2Attribute.begin(); - aFeatLast = myAllFeature2Attribute.end(); - } - else { - aFeatIter = myHighlightedFeature2Attribute.begin(); - aFeatLast = myHighlightedFeature2Attribute.end(); - } - - while (aFeatIter != aFeatLast) { - FeaturePtr aFeature = aFeatIter->first; - // MPV: added condition because it could be external edge of some object, not sketch - if (aFeature && !sketch()->isSub(aFeature)) { - aFeatIter++; - continue; - } - - std::list anAttributes = aFeatIter->second; - // perform edit for the feature - if (anAttributes.empty()) { - std::shared_ptr aSketchFeature = - std::dynamic_pointer_cast(aFeature); - if (aSketchFeature) { - aSketchFeature->move(aDeltaX, aDeltaY); - isMoved = true; - } - } - // perform edit for the feature's attribute - else { - std::list::const_iterator anAttrIter = anAttributes.begin(), - anAttrEnd = anAttributes.end(); - for (; anAttrIter != anAttrEnd; anAttrIter++) { - std::shared_ptr aPointAttr = std::dynamic_pointer_cast< - GeomDataAPI_Point2D>(aFeature->data()->attribute(*anAttrIter)); - if (aPointAttr) { - aPointAttr->move(aDeltaX, aDeltaY); - isMoved = true; - } - } - } - aFeatIter++; - } - // the next code is commented because it is obsolete by the multi edit operation realization here - // the feature is moved only if there is no a local selection on this feature - //if (!isMoved) { - // // MPV: added condition because it could be external edge of some object, not sketch - // if (aSketchFeature && sketch()->isSub(aSketchFeature)) { - // aSketchFeature->move(aDeltaX, aDeltaY); - // static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY); - // ModelAPI_EventCreator::get()->sendUpdated(feature(), anEvent); - // } - // } - //} // multieditoperation - sendFeatures(aHasShift); - } - - myCurPoint.setPoint(aPoint); -} - -void PartSet_OperationFeatureEdit::mouseReleased( - QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, - ModuleBase_ISelection* theSelection) -{ - // the block is processed in order to do not commit the transaction until the started - // double click functionality is performed. It is reproduced on Linux only - if (myIsBlockedByDoubleClick) - return; - - theViewer->enableSelection(true); - // the next code is commented because it is obsolete by the multi edit operation realization here - //if (myIsMultiOperation) { - // if (commit()) { - // std::map>::iterator aFeatIter = myFeature2Attribute.begin(); - // while (aFeatIter != myFeature2Attribute.end()) { - // FeaturePtr aFeature = aFeatIter->first; - // if (aFeature) { - // emit featureConstructed(aFeature, FM_Deactivation); - // } - // aFeatIter++; - // } - // } - //} - //else { // multieditoperation - ModuleBase_ModelWidget* aActiveWgt = 0; - if (myPropertyPanel) - aActiveWgt = myPropertyPanel->activeWidget(); - if(aActiveWgt && aActiveWgt->isViewerSelector()) { - // Almost do nothing, all stuff in on PartSet_OperationFeatureBase::mouseReleased - PartSet_OperationFeatureBase::mouseReleased(theEvent, theViewer, theSelection); - //}// else { - ////blockSelection(false); - ////} - //} // multieditoperation - } - else { - theViewer->enableSelection(true); - - // commit operation if there is no selected an highlighted objects anymore - Handle(V3d_View) aView = theViewer->activeView(); - QList aSelected = theSelection->getSelected(); - QList aHighlighted = theSelection->getHighlighted(); - - if (aSelected.empty() && aHighlighted.empty()) { - commit(); - emitFeaturesDeactivation(); - } - else if (aSelected.size() == 1) { - /// TODO: OCC bug: 25034 - the highlighted list should be filled not only for AIS_Shape - /// but for other IO, for example constraint dimensions. - /// It is empty and we have to use the process mouse release to start edition operation - /// for these objects - ObjectPtr anObject = aSelected.first().object(); - FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); - if (aFeature && PartSet_Tools::isConstraintFeature(aFeature->getKind()) && - aFeature != feature()) { - restartOperation(PartSet_OperationFeatureEdit::Type(), aFeature); - } - } - } -} - -void PartSet_OperationFeatureEdit::mouseDoubleClick( - QMouseEvent* theEvent, Handle_V3d_View theView, - ModuleBase_ISelection* theSelection) -{ - // TODO the functionality is important only for constraint feature. Should be moved in another place - QList aSelected = theSelection->getSelected(); - // in case when the double click happens on another constraint feature when selection control is active - // we should not perform the double click functionality - // if there is no the viewer selector widget active, the operation is restarted with a correct feature - ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget(); - if(aActiveWgt && aActiveWgt->isViewerSelector()) { - if (!aSelected.empty()) { - if (aSelected.size() == 1) { - /// TODO: OCC bug: 25034 - the highlighted list should be filled not only for AIS_Shape - /// but for other IO, for example constraint dimensions. - /// It is empty and we have to use the process mouse release to start edition operation - /// for these objects - ObjectPtr anObject = aSelected.first().object(); - FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); - if (aFeature && PartSet_Tools::isConstraintFeature(aFeature->getKind()) && - aFeature != feature()) { - return; - } - } - } - } - - myIsBlockedByDoubleClick = true; - if (!aSelected.empty()) { - ModuleBase_ViewerPrs aFeaturePrs = aSelected.first(); - if (!aFeaturePrs.owner().IsNull()) { - Handle(AIS_DimensionOwner) anOwner = Handle(AIS_DimensionOwner)::DownCast( - aFeaturePrs.owner()); - if (!anOwner.IsNull() && anOwner->SelectionMode() == AIS_DSM_Text) { - bool isValid; - double aValue = PartSet_Tools::featureValue(feature(), SketchPlugin_Constraint::VALUE(), - isValid); - if (isValid) { - ModuleBase_WidgetEditor::editFeatureValue(feature(), SketchPlugin_Constraint::VALUE()); - flushUpdated(); - } - } - } - } - myIsBlockedByDoubleClick = false; -} - -void PartSet_OperationFeatureEdit::startOperation() -{ - PartSet_OperationSketchBase::startOperation(); - //emit multiSelectionEnabled(false); - - myCurPoint.clear(); -} - -void PartSet_OperationFeatureEdit::stopOperation() -{ - //emit multiSelectionEnabled(true); - - //blockSelection(false, false); - - myHighlightedFeature2Attribute.clear(); - myAllFeature2Attribute.clear(); -} - -//void PartSet_OperationFeatureEdit::blockSelection(bool isBlocked, const bool isRestoreSelection) -//{ -// if (myIsBlockedSelection == isBlocked) -// return; -// -// myIsBlockedSelection = isBlocked; -// QList aFeatureList; -// aFeatureList.append(feature()); -// -// //if (isBlocked) { -// // emit setSelection(QList()); -// // emit stopSelection(aFeatureList, true); -// //} else { -// // emit stopSelection(aFeatureList, false); -// // if (isRestoreSelection) -// // emit setSelection(aFeatureList); -// //} -//} - -FeaturePtr PartSet_OperationFeatureEdit::createFeature(const bool theFlushMessage, - CompositeFeaturePtr theCompositeFeature) -{ - // do nothing in order to do not create a new feature - return FeaturePtr(); -} - -void PartSet_OperationFeatureEdit::sendFeatures(const bool theIsAllFeatures) -{ - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED); - - std::map>::iterator aFeatIter, aFeatLast; - if (theIsAllFeatures || myHighlightedFeature2Attribute.empty()) { - aFeatIter = myAllFeature2Attribute.begin(); - aFeatLast = myAllFeature2Attribute.end(); - } - else { - aFeatIter = myHighlightedFeature2Attribute.begin(); - aFeatLast = myHighlightedFeature2Attribute.end(); - } - while (aFeatIter != aFeatLast) { - FeaturePtr aFeature = aFeatIter->first; - if (aFeature) { - ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent); - } - aFeatIter++; - } - - Events_Loop::loop()->flush(anEvent); - flushUpdated(); -} - -void PartSet_OperationFeatureEdit::emitFeaturesDeactivation() -{ - std::map>::iterator aFeatIter = myAllFeature2Attribute.begin(); - while (aFeatIter != myAllFeature2Attribute.end()) { - FeaturePtr aFeature = aFeatIter->first; - if (aFeature) { - emit featureConstructed(aFeature, FM_Deactivation); - } - aFeatIter++; - } -} - diff --git a/src/PartSet/PartSet_OperationFeatureEdit.h b/src/PartSet/PartSet_OperationFeatureEdit.h deleted file mode 100644 index 267b494c6..000000000 --- a/src/PartSet/PartSet_OperationFeatureEdit.h +++ /dev/null @@ -1,156 +0,0 @@ -// File: PartSet_OperationFeatureEdit.h -// Created: 05 May 2014 -// Author: Natalia ERMOLAEVA - -#ifndef PartSet_OperationFeatureEdit_H -#define PartSet_OperationFeatureEdit_H - -#include "PartSet.h" - -#include -#include - -class QMouseEvent; -class ModuleBase_ISelection; - -/*! - \class PartSet_OperationFeatureEdit - * \brief The operation for the sketch feature creation - */ -class PARTSET_EXPORT PartSet_OperationFeatureEdit : public PartSet_OperationFeatureBase -{ -Q_OBJECT - /// Struct to define gp point, with the state is the point is initialized - struct Point - { - /// Constructor - Point() - { - myIsInitialized = false; - } - /// Constructor - /// \param thePoint the point - Point(gp_Pnt thePoint) - { - setPoint(thePoint); - } - ~Point() - { - } - - /// clear the initialized flag. - void clear() - { - myIsInitialized = false; - } - /// set the point and switch on the initialized flag - /// \param thePoint the point - void setPoint(const gp_Pnt& thePoint) - { - myIsInitialized = true; - myPoint = thePoint; - } - - bool myIsInitialized; /// the state whether the point is set - gp_Pnt myPoint; /// the point - }; - - public: - /// Returns the operation type key - static std::string Type() - { - return "EditLine"; - } - - public: - /// Constructor - /// \param theId the feature identifier - /// \param theParent the operation parent - /// \param theFeature the parent feature - PartSet_OperationFeatureEdit(const QString& theId, QObject* theParent, CompositeFeaturePtr theFeature); - /// Destructor - virtual ~PartSet_OperationFeatureEdit(); - - - /// Initialisation of operation with preliminary selection - /// \param theSelected the list of selected presentations - /// \param theHighlighted the list of highlighted presentations - /// \param theViewer a viewer to have the viewer the eye position - virtual void initSelection(ModuleBase_ISelection* theSelection, - ModuleBase_IViewer* theViewer); - - /// Processes the mouse pressed in the point - /// \param theEvent the mouse event - /// \param theView a viewer to have the viewer the eye position - /// \param theSelected the list of selected presentations - /// \param theHighlighted the list of highlighted presentations - virtual void mousePressed(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, ModuleBase_ISelection* theSelection); - - /// Gives the current mouse point in the viewer - /// \param theEvent the mouse event - /// \param theView a viewer to have the viewer the eye position - virtual void mouseMoved(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer); - /// Gives the current selected objects to be processed by the operation - /// \param thePoint a point clicked in the viewer - /// \param theEvent the mouse event - /// \param theSelected the list of selected presentations - /// \param theHighlighted the list of highlighted presentations - virtual void mouseReleased(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, - ModuleBase_ISelection* theSelection); - - /// Processes the mouse double click in the point - /// \param theEvent the mouse event - /// \param theView a viewer to have the viewer the eye position - /// \param theSelected the list of selected presentations - /// \param theHighlighted the list of highlighted presentations - virtual void mouseDoubleClick(QMouseEvent* theEvent, Handle_V3d_View theView, - ModuleBase_ISelection* theSelection); - - protected: - /// \brief Virtual method called when operation is started - /// Virtual method called when operation started (see start() method for more description) - /// Switch off the multi selection state - virtual void startOperation(); - - /// Virtual method called when operation stopped - committed or aborted. - /// Restore the multi selection state - virtual void stopOperation(); - - /// Creates an operation new feature - /// Returns NULL feature. This is an operation of edition, not creation. - /// \param theFlushMessage the flag whether the create message should be flushed - /// \returns the created feature - virtual FeaturePtr createFeature(const bool theFlushMessage = true, - CompositeFeaturePtr theCompositeFeature = CompositeFeaturePtr()); - - protected: - void fillFeature2Attribute(const QList& thePresentations, - ModuleBase_IViewer* theViewer, - std::map >& theFeature2Attribute); - - /// Emits a signal about the selection blocking. Emits a signal to change the selection. - /// If the block is true, the signal clear selection, otherwise if restore selection flag allows, - /// the internal operation features are to be selected - /// \param isBlocked the state whether the operation is blocked or unblocked - /// \param isRestoreSelection the state whether the selected objects should be reselected - //void blockSelection(bool isBlocked, const bool isRestoreSelection = true); - - /// Sends the features - /// \param theIsAllFeatures a boolean value whether all features should be send or only the highlighted ones - void sendFeatures(const bool theIsAllFeatures); - - /// Sends signal about the current features are to be deactivated - void emitFeaturesDeactivation(); - - private: - // the next map should be removed when selection is processed in the move function - std::map > myHighlightedFeature2Attribute; /// a map of a feature to attributes - std::map > myAllFeature2Attribute; /// a map of a feature to attributes - - Point myCurPoint; ///< the current 3D point clicked or moved - bool myIsBlockedSelection; ///< the state of the last state of selection blocked signal - bool myIsBlockedByDoubleClick; ///< the block value by double click is processed to avoid - ///< the mouse button release processing before the double click is finished -}; - -#endif diff --git a/src/PartSet/PartSet_OperationSketch.cpp b/src/PartSet/PartSet_OperationSketch.cpp index 5d9454d7a..fdf2ff672 100644 --- a/src/PartSet/PartSet_OperationSketch.cpp +++ b/src/PartSet/PartSet_OperationSketch.cpp @@ -3,8 +3,6 @@ // Author: Natalia ERMOLAEVA #include - -#include #include #include @@ -25,13 +23,6 @@ #include #include -#include -#include -#include -#include -#include -#include - #ifdef _DEBUG #include #endif @@ -41,7 +32,7 @@ using namespace std; PartSet_OperationSketch::PartSet_OperationSketch(const QString& theId, QObject* theParent) - : PartSet_OperationSketchBase(theId, theParent) + : ModuleBase_Operation(theId, theParent) { } @@ -49,244 +40,15 @@ PartSet_OperationSketch::~PartSet_OperationSketch() { } -CompositeFeaturePtr PartSet_OperationSketch::sketch() const -{ - return std::dynamic_pointer_cast(feature()); -} - -void PartSet_OperationSketch::mousePressed(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, ModuleBase_ISelection* theSelection) -{ - if (hasSketchPlane()) { - // if shift button is pressed and there are some already selected objects, the operation should - // not be started. We just want to combine some selected objects. - bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier); - QList aSelected = theSelection->getSelected(); - QList aHighlighted = theSelection->getHighlighted(); - // commented: the next code is commented because the nearestFeature check the highlighting - // and selection inside - //if (aHasShift && (aSelected.size() > 0)) { - // foreach(ModuleBase_ViewerPrs aPrs, aHighlighted) - // aSelected.append(aPrs); - //} - //if (aHasShift && aSelected.size() > 0) - // return; - - // there should be a start of operation, which uses the pre-highlighted objects, - // the selected ones are collected here and are processed by a mouse move - //if (aHighlighted.size() == 1) { - //if (aSelected.size() > 0) { - // ObjectPtr aFeature = aSelected.first().object(); - // if (aFeature) { - // commented: end - Handle(V3d_View) aView = theViewer->activeView(); - ObjectPtr aFeature = PartSet_Tools::nearestFeature(theEvent->pos(), aView, feature(), - aSelected, aHighlighted); - if (aFeature) - restartOperation(PartSet_OperationFeatureEdit::Type(), aFeature); - //} - //} - //else - // myFeatures = aHighlighted; - //else - //myFeatures = aSelected; - } -} - - -void PartSet_OperationSketch::selectionChanged(ModuleBase_ISelection* theSelection) -{ - if (hasSketchPlane()) - return; - - QList aSelected = theSelection->getSelected(); - if (!aSelected.empty()) { - ModuleBase_ViewerPrs aPrs = aSelected.first(); - // We have to select a plane before any operation - TopoDS_Shape aShape = aPrs.shape(); - if (!aShape.IsNull()) { - std::shared_ptr aDir = setSketchPlane(aShape); - flushUpdated(); - emit featureConstructed(feature(), FM_Hide); - // If selection is not a sketcher presentation then it has to be stored as - // External shape - if (feature() != aPrs.object()) { - //std::shared_ptr aSketch = - // std::dynamic_pointer_cast(feature()); - DataPtr aData = feature()->data(); - AttributeSelectionPtr aSelAttr = - std::dynamic_pointer_cast - (aData->attribute(SketchPlugin_Feature::EXTERNAL_ID())); - if (aSelAttr) { - ResultPtr aRes = std::dynamic_pointer_cast(aPrs.object()); - if (aRes) { - GeomShapePtr aShapePtr(new GeomAPI_Shape()); - aShapePtr->setImpl(new TopoDS_Shape(aShape)); - aSelAttr->setValue(aRes, aShapePtr); - } - } - } else { - // Turn viewer to the plane - emit planeSelected(aDir->x(), aDir->y(), aDir->z()); - } - emit updatePropPanel(); - emit launchSketch(); - } - } -} - - -void PartSet_OperationSketch::mouseReleased(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, - ModuleBase_ISelection* theSelection) -{ - QList aSelected = theSelection->getSelected(); - if (hasSketchPlane()) { - /// TODO: OCC bug: 25034 - the highlighted list should be filled not only for AIS_Shape - /// but for other IO, for example constraint dimensions. - /// It is empty and we have to use the process mouse release to start edition operation - /// for these objects - if (aSelected.size() == 1) { - ObjectPtr aObject = aSelected.first().object(); - if (aObject) { - restartOperation(PartSet_OperationFeatureEdit::Type(), aObject); - } - } - } -} - -void PartSet_OperationSketch::mouseMoved(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer) -{ - if (!hasSketchPlane() || !(theEvent->buttons() & Qt::LeftButton) || myFeatures.empty()) - return; - - // myFeatures are not filled in the previous realization, so, this code is just commented - // because has no effect - /*if (myFeatures.size() != 1) { - Handle(V3d_View) aView = theViewer->activeView(); - ObjectPtr aFeature = PartSet_Tools::nearestFeature(theEvent->pos(), aView, feature(), - myFeatures); - if (aFeature) - restartOperation(PartSet_OperationFeatureEdit::Type(), aFeature); - }*/ -} - -std::list PartSet_OperationSketch::subFeatures() const -{ - std::list aFeaList; - FeaturePtr aFeature = feature(); - if (!aFeature) - return aFeaList; - - std::shared_ptr aData = aFeature->data(); - if (!aData->isValid()) - return std::list(); - std::shared_ptr aRefList = std::dynamic_pointer_cast< - ModelAPI_AttributeRefList>(aData->attribute(SketchPlugin_Sketch::FEATURES_ID())); - - std::list aList = aRefList->list(); - std::list::iterator aIt; - for (aIt = aList.begin(); aIt != aList.end(); ++aIt) { - FeaturePtr aFeature = std::dynamic_pointer_cast(*aIt); - if (aFeature) - aFeaList.push_back(aFeature); - } - return aFeaList; -} - -void PartSet_OperationSketch::stopOperation() -{ - PartSet_OperationSketchBase::stopOperation(); - emit featureConstructed(feature(), FM_Hide); -} - -void PartSet_OperationSketch::afterCommitOperation() -{ - FeaturePtr aFeature = feature(); - std::list aResults = aFeature->results(); - std::list::const_iterator aIt; - Events_ID anEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TOSHOW); - for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) { - ModelAPI_EventCreator::get()->sendUpdated(*aIt, anEvent); - } - Events_Loop::loop()->flush(anEvent); -} - bool PartSet_OperationSketch::isNestedOperationsEnabled() const { - return hasSketchPlane(); -} - -void PartSet_OperationSketch::startOperation() -{ - PartSet_OperationSketchBase::startOperation(); - if (!isEditOperation()) - emit fitAllView(); -} - -bool PartSet_OperationSketch::hasSketchPlane() const -{ - bool aHasPlane = false; - + bool aHasSketchPlane = false; if (feature()) { std::shared_ptr aData = feature()->data(); AttributeDoublePtr anAttr; std::shared_ptr aNormal = std::dynamic_pointer_cast( aData->attribute(SketchPlugin_Sketch::NORM_ID())); - aHasPlane = aNormal && !(aNormal->x() == 0 && aNormal->y() == 0 && aNormal->z() == 0); + aHasSketchPlane = aNormal && !(aNormal->x() == 0 && aNormal->y() == 0 && aNormal->z() == 0); } - return aHasPlane; -} - -std::shared_ptr PartSet_OperationSketch::setSketchPlane(const TopoDS_Shape& theShape) -{ - if (theShape.IsNull()) - return std::shared_ptr(); - - // get selected shape - std::shared_ptr aGShape(new GeomAPI_Shape); - aGShape->setImpl(new TopoDS_Shape(theShape)); - - // get plane parameters - std::shared_ptr aPlane = GeomAlgoAPI_FaceBuilder::plane(aGShape); - - // set plane parameters to feature - std::shared_ptr aData = feature()->data(); - double anA, aB, aC, aD; - aPlane->coefficients(anA, aB, aC, aD); - - // calculate attributes of the sketch - std::shared_ptr aNormDir(new GeomAPI_Dir(anA, aB, aC)); - std::shared_ptr aCoords = aNormDir->xyz(); - std::shared_ptr aZero(new GeomAPI_XYZ(0, 0, 0)); - aCoords = aCoords->multiplied(-aD * aCoords->distance(aZero)); - std::shared_ptr anOrigPnt(new GeomAPI_Pnt(aCoords)); - // X axis is preferable to be dirX on the sketch - const double tol = Precision::Confusion(); - bool isX = fabs(anA - 1.0) < tol && fabs(aB) < tol && fabs(aC) < tol; - std::shared_ptr aTempDir( - isX ? new GeomAPI_Dir(0, 1, 0) : new GeomAPI_Dir(1, 0, 0)); - std::shared_ptr aYDir(new GeomAPI_Dir(aNormDir->cross(aTempDir))); - std::shared_ptr aXDir(new GeomAPI_Dir(aYDir->cross(aNormDir))); - - std::shared_ptr anOrigin = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Sketch::ORIGIN_ID())); - anOrigin->setValue(anOrigPnt); - std::shared_ptr aNormal = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Sketch::NORM_ID())); - aNormal->setValue(aNormDir); - std::shared_ptr aDirX = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Sketch::DIRX_ID())); - aDirX->setValue(aXDir); - std::shared_ptr aDirY = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Sketch::DIRY_ID())); - aDirY->setValue(aYDir); - std::shared_ptr aDir = aPlane->direction(); - return aDir; + return aHasSketchPlane; } - - -bool PartSet_OperationSketch::isGranted(ModuleBase_Operation* theOperation) const -{ - PartSet_OperationSketchBase* aPreviewOp = dynamic_cast(theOperation); - return aPreviewOp != NULL; -} - diff --git a/src/PartSet/PartSet_OperationSketch.h b/src/PartSet/PartSet_OperationSketch.h index 1a770e16b..f16a41835 100644 --- a/src/PartSet/PartSet_OperationSketch.h +++ b/src/PartSet/PartSet_OperationSketch.h @@ -7,22 +7,17 @@ #include "PartSet.h" -#include - +#include #include -#include -#include - -class Handle_AIS_InteractiveObject; - /*! \class PartSet_OperationSketch * \brief The operation for the sketch feature creation */ -class PARTSET_EXPORT PartSet_OperationSketch : public PartSet_OperationSketchBase +class PARTSET_EXPORT PartSet_OperationSketch : public ModuleBase_Operation { Q_OBJECT + public: /// Returns the operation type key static std::string Type() @@ -30,7 +25,6 @@ Q_OBJECT return SketchPlugin_Sketch::ID(); } - public: /// Constructor /// \param theId the feature identifier /// \param theParent the operation parent @@ -38,89 +32,12 @@ Q_OBJECT /// Destructor virtual ~PartSet_OperationSketch(); - /// Returns True if the given operation is a Sketcher operation - virtual bool isGranted(ModuleBase_Operation* theOperation) const; - - - /// Returns the operation sketch feature - /// \returns the sketch instance - virtual CompositeFeaturePtr sketch() const; - - /// Processes the mouse pressed in the point - /// \param theEvent the mouse event - /// \param theView a viewer to have the viewer the eye position - /// \param theSelected the list of selected presentations - /// \param theHighlighted the list of highlighted presentations - virtual void mousePressed(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, ModuleBase_ISelection* theSelection); - - /// Processes the mouse release in the point - /// \param theEvent the mouse event - /// \param theView a viewer to have the viewer the eye position - /// \param theSelected the list of selected presentations - /// \param theHighlighted the list of highlighted presentations - virtual void mouseReleased(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, - ModuleBase_ISelection* theSelection); - - /// Gives the current mouse point in the viewer - /// \param thePoint a point clicked in the viewer - /// \param theEvent the mouse event - virtual void mouseMoved(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer); - - /// Returns the list of the nested features - /// \return the list of subfeatures - virtual std::list subFeatures() const; - - /// Virtual method called when operation stopped - committed or aborted. - /// Emits a signal to hide the preview of the operation - virtual void stopOperation(); - /// Returns whether the nested operations are enabled. /// The state can depend on the operation current state. /// It returns true after the sketch plane is choosen. /// \return enabled state virtual bool isNestedOperationsEnabled() const; - /// Returns whether the sketch plane is set - /// \return the boolean value whether the sketch is set - bool hasSketchPlane() const; - - /// Set the plane to the current sketch - /// \param theShape the shape - /// \return selected direction - std::shared_ptr setSketchPlane(const TopoDS_Shape& theShape); - - /// Called on selection changed when the operation is active - virtual void selectionChanged(ModuleBase_ISelection* theSelection); - - /// If operation needs to redisplay its result during operation - /// then this method has to return True - virtual bool hasPreview() const { return false; } - -signals: - /// signal about the sketch plane is selected - /// \param theX the value in the X direction of the plane - /// \param theX the value in the Y direction value of the plane - /// \param theX the value in the Z direction of the plane - void planeSelected(double theX, double theY, double theZ); - // signal about the viewer fit all perform - void fitAllView(); - - /// Signal to define sketch mode - void launchSketch(); - - /// Signal to update property panel - void updatePropPanel(); - - protected: - /// Virtual method called when operation started (see start() method for more description) - /// Default impl calls corresponding slot and commits immediately. - virtual void startOperation(); - - /// Virtual method called after operation committed (see commit() method for more description) - virtual void afterCommitOperation(); - - private: - QList myFeatures; ///< the features to apply the edit operation }; #endif diff --git a/src/PartSet/PartSet_OperationSketchBase.cpp b/src/PartSet/PartSet_OperationSketchBase.cpp deleted file mode 100644 index 310658e9b..000000000 --- a/src/PartSet/PartSet_OperationSketchBase.cpp +++ /dev/null @@ -1,98 +0,0 @@ -// File: PartSet_OperationSketchBase.cpp -// Created: 20 Apr 2014 -// Author: Natalia ERMOLAEVA - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#ifdef _DEBUG -#include -#endif - -using namespace std; - -PartSet_OperationSketchBase::PartSet_OperationSketchBase(const QString& theId, QObject* theParent) - : ModuleBase_Operation(theId, theParent) -{ -} - -PartSet_OperationSketchBase::~PartSet_OperationSketchBase() -{ -} - -std::shared_ptr PartSet_OperationSketchBase::preview(FeaturePtr theFeature) -{ - std::shared_ptr aFeature = std::dynamic_pointer_cast< - SketchPlugin_Feature>(theFeature); - if (aFeature) { - ResultPtr aRes = aFeature->firstResult(); - ResultBodyPtr aBody = std::dynamic_pointer_cast(aRes); - if (aBody) - return aBody->shape(); - } - return std::shared_ptr(); -} - -std::list PartSet_OperationSketchBase::subFeatures() const -{ - return std::list(); -} - -FeaturePtr PartSet_OperationSketchBase::createFeature(const bool theFlushMessage) -{ - ModuleBase_Operation::createFeature(theFlushMessage); - if (myFeature) - emit featureConstructed(myFeature, FM_Activation); - return myFeature; -} - -void PartSet_OperationSketchBase::mousePressed(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, ModuleBase_ISelection* theSelection) -{ -} -void PartSet_OperationSketchBase::mouseReleased( - QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, - ModuleBase_ISelection* theSelection) -{ -} -void PartSet_OperationSketchBase::mouseMoved(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer) -{ -} -void PartSet_OperationSketchBase::mouseDoubleClick( - QMouseEvent* theEvent, Handle_V3d_View theView, - ModuleBase_ISelection* theSelection) -{ -} - -void PartSet_OperationSketchBase::selectionChanged(ModuleBase_ISelection* theSelection) -{ -} - -void PartSet_OperationSketchBase::restartOperation(const std::string& theType, ObjectPtr theFeature) -{ - FeaturePtr aFeature = ModelAPI_Feature::feature(theFeature); - if (aFeature) { - QStringList aNested = this->nestedFeatures(); - if (!aNested.isEmpty()) { - if (!aNested.contains(QString(aFeature->getKind().c_str()))) - return; - } - } - emit restartRequired(theType, theFeature); -} - - diff --git a/src/PartSet/PartSet_OperationSketchBase.h b/src/PartSet/PartSet_OperationSketchBase.h deleted file mode 100644 index dacfb8fd7..000000000 --- a/src/PartSet/PartSet_OperationSketchBase.h +++ /dev/null @@ -1,148 +0,0 @@ -// File: PartSet_OperationSketchBase.h -// Created: 20 Apr 2014 -// Author: Natalia ERMOLAEVA - -#ifndef PartSet_OperationSketchBase_H -#define PartSet_OperationSketchBase_H - -#include "PartSet.h" - -#include -#include -#include - -#include -#include - -#include -#include - -#include - -#include - -#include - -class Handle_V3d_View; -class QMouseEvent; -class GeomAPI_Shape; -class ModuleBase_ViewerPrs; -class ModuleBase_ISelection; -class ModuleBase_IViewer; - -/*! - \class PartSet_OperationSketchBase - * \brief The base operation for the sketch features. - * Base class for all sketch operations. It provides an access to the feature preview - */ -class PARTSET_EXPORT PartSet_OperationSketchBase : public ModuleBase_Operation -{ -Q_OBJECT - public: - enum FeatureActionMode - { - FM_Activation, - FM_Deactivation, - FM_Hide - }; - - public: - /// Constructor - /// \param theId an feature index - /// \param theParent the object parent - PartSet_OperationSketchBase(const QString& theId, QObject* theParent); - /// Destructor - virtual ~PartSet_OperationSketchBase(); - - /// Returns the feature preview shape - /// \param theFeature the feature object to obtain the preview - static std::shared_ptr preview(FeaturePtr theFeature); - - /// Returns the list of the nested features - /// \return the list of subfeatures - virtual std::list subFeatures() const; - - /// Returns the operation sketch feature - /// \returns the sketch instance - virtual CompositeFeaturePtr sketch() const = 0; - - /// Processes the mouse pressed in the point - /// \param theEvent the mouse event - /// \param theView a viewer to have the viewer the eye position - /// \param theSelected the list of selected presentations - /// \param theHighlighted the list of highlighted presentations - virtual void mousePressed(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, ModuleBase_ISelection* theSelection); - - /// Processes the mouse release in the point - /// \param theEvent the mouse event - /// \param theView a viewer to have the viewer the eye position - /// \param theSelected the list of selected presentations - /// \param theHighlighted the list of highlighted presentations - virtual void mouseReleased(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, - ModuleBase_ISelection* theSelection); - - /// Processes the mouse move in the point - /// \param theEvent the mouse event - /// \param theView a viewer to have the viewer the eye position - virtual void mouseMoved(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer); - - /// Processes the mouse double click in the point - /// \param theEvent the mouse event - /// \param theView a viewer to have the viewer the eye position - /// \param theSelected the list of selected presentations - /// \param theHighlighted the list of highlighted presentations - virtual void mouseDoubleClick(QMouseEvent* theEvent, Handle_V3d_View theView, - ModuleBase_ISelection* theSelection); - - - /// Called on selection changed when the operation is active - virtual void selectionChanged(ModuleBase_ISelection* theSelection); - - /// Emits a signal about the operation start. This signal has an information about the feature. - /// If the provided feature is empty, the current operation feature is used. - /// \param theType a type of an operation started - /// theFeature the operation argument - void restartOperation(const std::string& theType, ObjectPtr theFeature = ObjectPtr()); - - /// If operation needs to redisplay its result during operation - /// then this method has to return True - virtual bool hasPreview() const { return true; } - -signals: - /// signal about the request to launch operation - /// theName the operation name - /// theFeature the operation argument - void restartRequired(std::string theName, ObjectPtr theFeature); - - /// Signal about the feature construing is finished - /// \param theFeature the result feature - /// \param theMode the mode of the feature modification - void featureConstructed(ObjectPtr theFeature, int theMode); - - /// Signal about the features should be selected - /// \param theSelected the list of selected presentations - void featureSelected(const std::list& theSelected); - - /// signal to enable/disable multi selection in the viewer - /// \param theEnabled the boolean state - //void multiSelectionEnabled(bool theEnabled); - - /// signal to enable/disable selection in the viewer - /// \param theFeatures a list of features to be disabled - /// \param theToStop the boolean state whether it it stopped or non stopped - void stopSelection(const QList& theFeatures, const bool theToStop); - - /// signal to set selection in the viewer - /// \param theFeatures a list of features to be disabled - void setSelection(const QList& theFeatures); - - protected: - /// Creates an operation new feature - /// In addition to the default realization it appends the created line feature to - /// the sketch feature - /// \param theFlushMessage the flag whether the create message should be flushed - /// \returns the created feature - virtual FeaturePtr createFeature(const bool theFlushMessage = true); -}; - -#endif diff --git a/src/PartSet/PartSet_Tools.cpp b/src/PartSet/PartSet_Tools.cpp index c97b6c68f..f6e8ae84f 100644 --- a/src/PartSet/PartSet_Tools.cpp +++ b/src/PartSet/PartSet_Tools.cpp @@ -126,12 +126,8 @@ Handle(V3d_View) theView, theY = aVec.X() * anY->x() + aVec.Y() * anY->y() + aVec.Z() * anY->z(); } -void PartSet_Tools::convertTo3D(const double theX, const double theY, FeaturePtr theSketch, - gp_Pnt& thePoint) +std::shared_ptr PartSet_Tools::convertTo3D(const double theX, const double theY, FeaturePtr theSketch) { - if (!theSketch) - return; - std::shared_ptr aData = theSketch->data(); std::shared_ptr aC = std::dynamic_pointer_cast( @@ -141,11 +137,10 @@ void PartSet_Tools::convertTo3D(const double theX, const double theY, FeaturePtr std::shared_ptr aY = std::dynamic_pointer_cast( aData->attribute(SketchPlugin_Sketch::DIRY_ID())); - std::shared_ptr aSum = aC->pnt()->xyz()->added(aX->dir()->xyz()->multiplied(theX)) - ->added(aY->dir()->xyz()->multiplied(theY)); + std::shared_ptr aPnt2d = + std::shared_ptr(new GeomAPI_Pnt2d(theX, theY)); - std::shared_ptr aPoint = std::shared_ptr(new GeomAPI_Pnt(aSum)); - thePoint = gp_Pnt(aPoint->x(), aPoint->y(), aPoint->z()); + return aPnt2d->to3D(aC->pnt(), aX->dir(), aY->dir()); } ObjectPtr PartSet_Tools::nearestFeature(QPoint thePoint, Handle_V3d_View theView, @@ -352,19 +347,27 @@ void PartSet_Tools::setConstraints(CompositeFeaturePtr theSketch, FeaturePtr the std::shared_ptr PartSet_Tools::sketchPlane(CompositeFeaturePtr theSketch) { std::shared_ptr aPlane; - double aA, aB, aC, aD; std::shared_ptr aData = theSketch->data(); std::shared_ptr anOrigin = std::dynamic_pointer_cast( aData->attribute(SketchPlugin_Sketch::ORIGIN_ID())); std::shared_ptr aNormal = std::dynamic_pointer_cast( aData->attribute(SketchPlugin_Sketch::NORM_ID())); - aA = aNormal->x(); - aB = aNormal->y(); - aC = aNormal->z(); - aD = 0; - - aPlane = std::shared_ptr(new GeomAPI_Pln(aA, aB, aC, aD)); + if (aNormal && anOrigin) { + double adX = aNormal->x(); + double adY = aNormal->y(); + double adZ = aNormal->z(); + + if ( (adX != 0) || (adY != 0) || (adZ != 0) ) { // Plane is valid + double aX = anOrigin->x(); + double aY = anOrigin->y(); + double aZ = anOrigin->z(); + gp_Pln aPln(gp_Pnt(aX, aY, aZ), gp_Dir(adX, adY, adZ)); + double aA, aB, aC, aD; + aPln.Coefficients(aA, aB, aC, aD); + aPlane = std::shared_ptr(new GeomAPI_Pln(aA, aB, aC, aD)); + } + } return aPlane; } @@ -393,15 +396,16 @@ bool PartSet_Tools::isConstraintFeature(const std::string& theKind) || theKind == SketchPlugin_ConstraintRigid::ID(); } -ResultPtr PartSet_Tools::createFixedObjectByEdge(const ModuleBase_ViewerPrs& thePrs, CompositeFeaturePtr theSketch) +ResultPtr PartSet_Tools::createFixedObjectByEdge(const TopoDS_Shape& theShape, + const ObjectPtr& theObject, + CompositeFeaturePtr theSketch) { - TopoDS_Shape aShape = thePrs.shape(); - if (aShape.ShapeType() != TopAbs_EDGE) + if (theShape.ShapeType() != TopAbs_EDGE) return ResultPtr(); // Check that we already have such external edge std::shared_ptr aInEdge = std::shared_ptr(new GeomAPI_Edge()); - aInEdge->setImpl(new TopoDS_Shape(aShape)); + aInEdge->setImpl(new TopoDS_Shape(theShape)); ResultPtr aResult = findExternalEdge(theSketch, aInEdge); if (aResult) return aResult; @@ -411,35 +415,15 @@ ResultPtr PartSet_Tools::createFixedObjectByEdge(const ModuleBase_ViewerPrs& the Handle(V3d_View) aNullView; FeaturePtr aMyFeature; - Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(aShape), aStart, aEnd); + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(theShape), aStart, aEnd); GeomAdaptor_Curve aAdaptor(aCurve); if (aAdaptor.GetType() == GeomAbs_Line) { // Create line aMyFeature = theSketch->addFeature(SketchPlugin_Line::ID()); - - //DataPtr aData = myFeature->data(); - //std::shared_ptr anEndAttr = - // std::dynamic_pointer_cast(aData->attribute(SketchPlugin_Line::END_ID())); - - //double aX, aY; - //gp_Pnt Pnt1 = aAdaptor.Value(aStart); - //convertTo2D(Pnt1, theSketch, aNullView, aX, aY); - //setFeaturePoint(myFeature, aX, aY, SketchPlugin_Line::START_ID()); - - //gp_Pnt Pnt2 = aAdaptor.Value(aEnd); - //convertTo2D(Pnt2, theSketch, aNullView, aX, aY); - //setFeaturePoint(myFeature, aX, aY, SketchPlugin_Line::END_ID()); } else if (aAdaptor.GetType() == GeomAbs_Circle) { if (aAdaptor.IsClosed()) { // Create circle aMyFeature = theSketch->addFeature(SketchPlugin_Circle::ID()); - //gp_Circ aCirc = aAdaptor.Circle(); - //gp_Pnt aCenter = aCirc.Location(); - - //double aX, aY; - //convertTo2D(aCenter, theSketch, aNullView, aX, aY); - //setFeaturePoint(myFeature, aX, aY, SketchPlugin_Circle::CENTER_ID()); - //setFeatureValue(myFeature, aCirc.Radius(), SketchPlugin_Circle::RADIUS_ID()); } else { // Create arc aMyFeature = theSketch->addFeature(SketchPlugin_Arc::ID()); @@ -451,10 +435,10 @@ ResultPtr PartSet_Tools::createFixedObjectByEdge(const ModuleBase_ViewerPrs& the std::dynamic_pointer_cast (aData->attribute(SketchPlugin_Feature::EXTERNAL_ID())); - ResultPtr aRes = std::dynamic_pointer_cast(thePrs.object()); + ResultPtr aRes = std::dynamic_pointer_cast(theObject); if (anAttr && aRes) { std::shared_ptr anEdge(new GeomAPI_Shape); - anEdge->setImpl(new TopoDS_Shape(aShape)); + anEdge->setImpl(new TopoDS_Shape(theShape)); anAttr->setValue(aRes, anEdge); @@ -527,3 +511,39 @@ bool PartSet_Tools::hasVertexShape(const ModuleBase_ViewerPrs& thePrs, FeaturePt return aHasVertex; } + +AttributePtr PartSet_Tools::findAttributeBy2dPoint(ObjectPtr theObj, + const TopoDS_Shape theShape, + FeaturePtr theSketch) +{ + + AttributePtr anAttribute; + FeaturePtr aFeature = ModelAPI_Feature::feature(theObj); + if (aFeature) { + if (theShape.ShapeType() == TopAbs_VERTEX) { + const TopoDS_Vertex& aVertex = TopoDS::Vertex(theShape); + if (!aVertex.IsNull()) { + gp_Pnt aPoint = BRep_Tool::Pnt(aVertex); + std::shared_ptr aValue = std::shared_ptr( + new GeomAPI_Pnt(aPoint.X(), aPoint.Y(), aPoint.Z())); + + // find the given point in the feature attributes + std::list anAttiributes = + aFeature->data()->attributes(GeomDataAPI_Point2D::type()); + std::list::const_iterator anIt = anAttiributes.begin(), + aLast = anAttiributes.end(); + for (; anIt != aLast && !anAttribute; anIt++) { + std::shared_ptr aCurPoint = + std::dynamic_pointer_cast(*anIt); + + std::shared_ptr aPnt = convertTo3D(aCurPoint->x(), aCurPoint->y(), theSketch); + if (aPnt && (aPnt->distance(aValue) < Precision::Confusion())) { + anAttribute = aCurPoint; + break; + } + } + } + } + } + return anAttribute; +} diff --git a/src/PartSet/PartSet_Tools.h b/src/PartSet/PartSet_Tools.h index 5dda6eafb..bceef165a 100644 --- a/src/PartSet/PartSet_Tools.h +++ b/src/PartSet/PartSet_Tools.h @@ -14,6 +14,10 @@ #include #include +#include +#include + +#include #include @@ -35,6 +39,7 @@ class PARTSET_EXPORT PartSet_Tools /// Converts the 2D screen point to the 3D point on the view according to the point of view /// \param thePoint a screen point /// \param theView a 3D view + // Transferred to ModuleBase static gp_Pnt convertClickToPoint(QPoint thePoint, Handle_V3d_View theView); /// \brief Converts the 3D point to the projected coodinates on the sketch plane. @@ -43,7 +48,7 @@ class PARTSET_EXPORT PartSet_Tools /// \param theX the X coordinate /// \param theY the Y coordinate static void convertTo2D(const gp_Pnt& thePoint, FeaturePtr theSketch, - Handle(V3d_View) theView, + Handle(V3d_View) theView, double& theX, double& theY); /// \brief Converts the 2D projected coodinates on the sketch plane to the 3D point. @@ -51,8 +56,7 @@ class PARTSET_EXPORT PartSet_Tools /// \param theY the Y coordinate /// \param theSketch the sketch feature /// \param thePoint the 3D point in the viewer - static void convertTo3D(const double theX, const double theY, FeaturePtr theSketch, - gp_Pnt& thePoint); + static std::shared_ptr convertTo3D(const double theX, const double theY, FeaturePtr theSketch); /// Returns an object that is under the mouse point. Firstly it checks the highlighting, /// if it exists, the first object is returned. Secondly, there is an iteration on @@ -137,7 +141,9 @@ class PARTSET_EXPORT PartSet_Tools /// Created line will have fixed constraint /// \param theEdge - an edge /// \return - result of created feature - static ResultPtr createFixedObjectByEdge(const ModuleBase_ViewerPrs& thePrs, CompositeFeaturePtr theSketch); + static ResultPtr createFixedObjectByEdge(const TopoDS_Shape& theShape, + const ObjectPtr& theObject, + CompositeFeaturePtr theSketch); /// Checks whether the list of selected presentations contains the given one /// \param theSelected a list of presentations @@ -160,6 +166,16 @@ class PARTSET_EXPORT PartSet_Tools /// \param theY the output vertical coordinate of the point static bool hasVertexShape(const ModuleBase_ViewerPrs& thePrs, FeaturePtr theSketch, Handle_V3d_View theView, double& theX, double& theY); + + + /** + * Find attribute of object which corresponds to the given shape + * \param theObj - an object + * \param theShape - a Shape + * \param theSketch - a Sketch to get a plane of converting to 2d + */ + static AttributePtr findAttributeBy2dPoint(ObjectPtr theObj, const TopoDS_Shape theShape, FeaturePtr theSketch); + protected: /// Returns an object that is under the mouse point. Firstly it checks the highlighting, /// if it exists, the first object is returned. Secondly, there is an iteration on diff --git a/src/PartSet/PartSet_Validators.cpp b/src/PartSet/PartSet_Validators.cpp index 7a976bda3..31fd4c048 100644 --- a/src/PartSet/PartSet_Validators.cpp +++ b/src/PartSet/PartSet_Validators.cpp @@ -11,6 +11,10 @@ #include #include +#include +#include +#include + #include int shapesNbPoints(const ModuleBase_ISelection* theSelection) @@ -92,3 +96,69 @@ bool PartSet_RadiusValidator::isValid(const ModuleBase_ISelection* theSelection) return (aCount > 0) && (aCount < 2); } + + +bool PartSet_DifferentObjectsValidator::isValid(const FeaturePtr& theFeature, + const std::list& theArguments, + const ObjectPtr& theObject) const +{ + // Check RefAttr attributes + std::list > anAttrs = + theFeature->data()->attributes(ModelAPI_AttributeRefAttr::type()); + if (anAttrs.size() > 0) { + std::list >::iterator anAttr = anAttrs.begin(); + for(; anAttr != anAttrs.end(); anAttr++) { + if (*anAttr) { + std::shared_ptr aRef = + std::dynamic_pointer_cast(*anAttr); + // check the object is already presented + if (aRef->isObject() && aRef->object() == theObject) + return false; + } + } + } + // Check selection attributes + anAttrs = theFeature->data()->attributes(ModelAPI_AttributeSelection::type()); + if (anAttrs.size() > 0) { + std::list >::iterator anAttr = anAttrs.begin(); + for(; anAttr != anAttrs.end(); anAttr++) { + if (*anAttr) { + std::shared_ptr aRef = + std::dynamic_pointer_cast(*anAttr); + // check the object is already presented + if (aRef->isInitialized() && aRef->context() == theObject) + return false; + } + } + } + // Check selection attributes + anAttrs = theFeature->data()->attributes(ModelAPI_AttributeReference::type()); + if (anAttrs.size() > 0) { + std::list >::iterator anAttr = anAttrs.begin(); + for(; anAttr != anAttrs.end(); anAttr++) { + if (*anAttr) { + std::shared_ptr aRef = + std::dynamic_pointer_cast(*anAttr); + // check the object is already presented + if (aRef->isInitialized() && aRef->value() == theObject) + return false; + } + } + } + return true; +} + +bool PartSet_DifferentObjectsValidator::isValid(const FeaturePtr& theFeature, + const std::list& theArguments, + const AttributePtr& theAttribute) const +{ + // not implemented + return true; +} + +bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute, + const std::list& theArguments) const +{ + // not implemented + return true; +} \ No newline at end of file diff --git a/src/PartSet/PartSet_Validators.h b/src/PartSet/PartSet_Validators.h index 02f7d21e6..33deefd50 100644 --- a/src/PartSet/PartSet_Validators.h +++ b/src/PartSet/PartSet_Validators.h @@ -9,6 +9,7 @@ #include #include +#include /* * Selector validators @@ -49,4 +50,18 @@ class PartSet_RadiusValidator : public ModuleBase_SelectionValidator PARTSET_EXPORT virtual bool isValid(const ModuleBase_ISelection* theSelection) const; }; +class PartSet_DifferentObjectsValidator : public ModelAPI_RefAttrValidator +{ + public: + virtual bool isValid(const FeaturePtr& theFeature, const std::list& theArguments, + const ObjectPtr& theObject) const; + //! Returns true if the attribute is good for the feature attribute + virtual bool isValid(const FeaturePtr& theFeature, const std::list& theArguments, + const AttributePtr& theAttribute) const; + + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments) const; +}; + + #endif diff --git a/src/PartSet/PartSet_WidgetPoint2d.cpp b/src/PartSet/PartSet_WidgetPoint2d.cpp new file mode 100644 index 000000000..75f60a992 --- /dev/null +++ b/src/PartSet/PartSet_WidgetPoint2d.cpp @@ -0,0 +1,276 @@ +// File: PartSet_WidgetPoint2D.cpp +// Created: 25 Apr 2014 +// Author: Natalia ERMOLAEVA + +#include "PartSet_WidgetPoint2d.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 + +PartSet_WidgetPoint2D::PartSet_WidgetPoint2D(QWidget* theParent, + const Config_WidgetAPI* theData, + const std::string& theParentId) + : ModuleBase_ModelWidget(theParent, theData, theParentId) +{ + //myOptionParam = theData->getProperty(PREVIOUS_FEATURE_PARAM); + QString aPageName = QString::fromStdString(theData->getProperty(CONTAINER_PAGE_NAME)); + myGroupBox = new QGroupBox(aPageName, theParent); + myGroupBox->setFlat(false); + + QGridLayout* aGroupLay = new QGridLayout(myGroupBox); + ModuleBase_Tools::adjustMargins(aGroupLay); + aGroupLay->setColumnStretch(1, 1); + { + QLabel* aLabel = new QLabel(myGroupBox); + aLabel->setText("X"); + aLabel->setPixmap(QPixmap(":pictures/x_point.png")); + aGroupLay->addWidget(aLabel, 0, 0); + + myXSpin = new ModuleBase_DoubleSpinBox(myGroupBox); + myXSpin->setMinimum(-DBL_MAX); + myXSpin->setMaximum(DBL_MAX); + myXSpin->setToolTip("X"); + aGroupLay->addWidget(myXSpin, 0, 1); + + connect(myXSpin, SIGNAL(valueChanged(double)), this, SIGNAL(valuesChanged())); + } + { + QLabel* aLabel = new QLabel(myGroupBox); + aLabel->setText("Y"); + aLabel->setPixmap(QPixmap(":pictures/y_point.png")); + aGroupLay->addWidget(aLabel, 1, 0); + + myYSpin = new ModuleBase_DoubleSpinBox(myGroupBox); + myYSpin->setMinimum(-DBL_MAX); + myYSpin->setMaximum(DBL_MAX); + myYSpin->setToolTip("X"); + aGroupLay->addWidget(myYSpin, 1, 1); + + connect(myYSpin, SIGNAL(valueChanged(double)), this, SIGNAL(valuesChanged())); + } +} + +PartSet_WidgetPoint2D::~PartSet_WidgetPoint2D() +{ +} + +bool PartSet_WidgetPoint2D::setSelection(ModuleBase_ViewerPrs theValue) +{ + Handle(V3d_View) aView = myWorkshop->viewer()->activeView(); + bool isDone = false; + TopoDS_Shape aShape = theValue.shape(); + double aX, aY; + if (getPoint2d(aView, aShape, aX, aY)) { + setPoint(aX, aY); + isDone = true; + } + return isDone; +} + +void PartSet_WidgetPoint2D::setPoint(double theX, double theY) +{ + + bool isBlocked = this->blockSignals(true); + myXSpin->setValue(theX); + myYSpin->setValue(theY); + this->blockSignals(isBlocked); + + emit valuesChanged(); +} + +bool PartSet_WidgetPoint2D::storeValue() const +{ + std::shared_ptr aData = myFeature->data(); + std::shared_ptr aPoint = std::dynamic_pointer_cast( + aData->attribute(attributeID())); + + PartSet_WidgetPoint2D* that = (PartSet_WidgetPoint2D*) this; + bool isBlocked = that->blockSignals(true); + bool isImmutable = aPoint->setImmutable(true); +#ifdef _DEBUG + std::string _attr_name = myAttributeID; + double _X = myXSpin->value(); + double _Y = myYSpin->value(); +#endif + aPoint->setValue(myXSpin->value(), myYSpin->value()); + updateObject(myFeature); + aPoint->setImmutable(isImmutable); + that->blockSignals(isBlocked); + + return true; +} + +bool PartSet_WidgetPoint2D::restoreValue() +{ + std::shared_ptr aData = myFeature->data(); + std::shared_ptr aPoint = std::dynamic_pointer_cast( + aData->attribute(attributeID())); + +#ifdef _DEBUG + std::string _attr_name = myAttributeID; + double _X = aPoint->x(); + double _Y = aPoint->y(); +#endif + bool isBlocked = this->blockSignals(true); + myXSpin->setValue(aPoint->x()); + myYSpin->setValue(aPoint->y()); + this->blockSignals(isBlocked); + return true; +} + +QWidget* PartSet_WidgetPoint2D::getControl() const +{ + return myGroupBox; +} + +QList PartSet_WidgetPoint2D::getControls() const +{ + QList aControls; + aControls.append(myXSpin); + aControls.append(myYSpin); + return aControls; +} + +//bool PartSet_WidgetPoint2D::initFromPrevious(ObjectPtr theObject) +//{ +// if (myOptionParam.length() == 0) +// return false; +// std::shared_ptr aData = theObject->data(); +// std::shared_ptr aPoint = std::dynamic_pointer_cast( +// aData->attribute(myOptionParam)); +// if (aPoint) { +// bool isBlocked = this->blockSignals(true); +// myXSpin->setValue(aPoint->x()); +// myYSpin->setValue(aPoint->y()); +// this->blockSignals(isBlocked); +// +// emit valuesChanged(); +// emit storedPoint2D(theObject, myOptionParam); +// return true; +// } +// return false; +//} + +void PartSet_WidgetPoint2D::activate() +{ + XGUI_ViewerProxy* aViewer = myWorkshop->viewer(); + connect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)), + this, SLOT(onMouseMove(ModuleBase_IViewWindow*, QMouseEvent*))); + connect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)), + this, SLOT(onMouseRelease(ModuleBase_IViewWindow*, QMouseEvent*))); + + QIntList aModes; + aModes << TopAbs_VERTEX; + myWorkshop->moduleConnector()->activateSubShapesSelection(aModes); +} + +void PartSet_WidgetPoint2D::deactivate() +{ + ModuleBase_IViewer* aViewer = myWorkshop->viewer(); + disconnect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)), + this, SLOT(onMouseMove(ModuleBase_IViewWindow*, QMouseEvent*))); + disconnect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)), + this, SLOT(onMouseRelease(ModuleBase_IViewWindow*, QMouseEvent*))); + myWorkshop->moduleConnector()->deactivateSubShapesSelection(); +} + +bool PartSet_WidgetPoint2D::getPoint2d(const Handle(V3d_View)& theView, + const TopoDS_Shape& theShape, + double& theX, double& theY) const +{ + if (!theShape.IsNull()) { + if (theShape.ShapeType() == TopAbs_VERTEX) { + const TopoDS_Vertex& aVertex = TopoDS::Vertex(theShape); + if (!aVertex.IsNull()) { + // A case when point is taken from existing vertex + gp_Pnt aPoint = BRep_Tool::Pnt(aVertex); + PartSet_Tools::convertTo2D(aPoint, mySketch, theView, theX, theY); + return true; + } + } + } + return false; +} + + +void PartSet_WidgetPoint2D::onMouseRelease(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) +{ + XGUI_Selection* aSelection = myWorkshop->selector()->selection(); + NCollection_List aShapes; + std::list aObjects; + aSelection->selectedShapes(aShapes, aObjects); + if (aShapes.Extent() > 0) { + TopoDS_Shape aShape = aShapes.First(); + double aX, aY; + if (getPoint2d(theWnd->v3dView(), aShape, aX, aY)) { + setPoint(aX, aY); + + PartSet_Tools::setConstraints(mySketch, feature(), attributeID(),aX, aY); + emit vertexSelected(aObjects.front(), aShape); + emit focusOutWidget(this); + return; + } + } + // A case when point is taken from mouse event + gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWnd->v3dView()); + double aX, anY; + PartSet_Tools::convertTo2D(aPoint, mySketch, theWnd->v3dView(), aX, anY); + setPoint(aX, anY); + + emit focusOutWidget(this); +} + + +void PartSet_WidgetPoint2D::onMouseMove(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) +{ + gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWnd->v3dView()); + + double aX, anY; + PartSet_Tools::convertTo2D(aPoint, mySketch, theWnd->v3dView(), aX, anY); + setPoint(aX, anY); +} + +double PartSet_WidgetPoint2D::x() const +{ + return myXSpin->value(); +} + +double PartSet_WidgetPoint2D::y() const +{ + return myYSpin->value(); +} + diff --git a/src/PartSet/PartSet_WidgetPoint2d.h b/src/PartSet/PartSet_WidgetPoint2d.h new file mode 100644 index 000000000..4971997a8 --- /dev/null +++ b/src/PartSet/PartSet_WidgetPoint2d.h @@ -0,0 +1,114 @@ +// File: PartSet_WidgetPoint2d.h +// Created: 25 Apr 2014 +// Author: Natalia ERMOLAEVA + +#ifndef PartSet_WidgetPoint2D_H +#define PartSet_WidgetPoint2D_H + +#include "PartSet.h" +#include +#include + +#include + +#include +#include + +class ModelAPI_Feature; +class ModuleBase_IWorkshop; +class ModuleBase_DoubleSpinBox; +class ModuleBase_IViewWindow; +class GeomAPI_Pnt2d; +class XGUI_Workshop; + +class QGroupBox; +class QMouseEvent; + +/**\class PartSet_WidgetPoint2D + * \ingroup GUI + * \brief Custom widget. An abstract class to be redefined to fill with some GUI controls + */ +class PARTSET_EXPORT PartSet_WidgetPoint2D : public ModuleBase_ModelWidget +{ +Q_OBJECT + public: + /// Constructor + /// \theParent the parent object + /// \theParent the parent object + /// \theData the widget configuation. The attribute of the model widget is obtained from + PartSet_WidgetPoint2D(QWidget* theParent, const Config_WidgetAPI* theData, + const std::string& theParentId); + /// Destructor + virtual ~PartSet_WidgetPoint2D(); + + /// Set the given wrapped value to the current widget + /// This value should be processed in the widget according to the needs + /// \param theValue the wrapped widget value + virtual bool setSelection(ModuleBase_ViewerPrs theValue); + + /// Saves the internal parameters to the given feature + /// \param theObject a model feature to be changed + virtual bool storeValue() const; + + virtual bool restoreValue(); + + /// Returns the internal parent wiget control, that can be shown anywhere + /// \returns the widget + QWidget* getControl() const; + + /// Returns list of widget controls + /// \return a control list + virtual QList getControls() const; + + //bool initFromPrevious(ObjectPtr theObject); + + /// The methiod called when widget is activated + virtual void activate(); + + /// The methiod called when widget is deactivated + virtual void deactivate(); + + XGUI_Workshop* workshop() const { return myWorkshop; } + + void setWorkshop(XGUI_Workshop* theWork) { myWorkshop = theWork; } + + /// \returns the sketch instance + CompositeFeaturePtr sketch() const { return mySketch; } + void setSketch(CompositeFeaturePtr theSketch) { mySketch = theSketch; } + + /// Fill the widget values by given point + /// \param thePoint the point + void setPoint(double theX, double theY); + + /// Returns coordinate X currently defined in the control + double x() const; + + /// Returns coordinate Y currently defined in the control + double y() const; + +signals: + /// Signal about selection of an existing vertex from an object + /// \param theObject - the selected object + /// \param theShape - the selected shape + void vertexSelected(ObjectPtr theObject, const TopoDS_Shape& theShape); + +protected slots: + void onMouseRelease(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); + void onMouseMove(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); + + private: + bool getPoint2d(const Handle(V3d_View)& theView, const TopoDS_Shape& theShape, + double& theX, double& theY) const; + + XGUI_Workshop* myWorkshop; + + QGroupBox* myGroupBox; ///< the parent group box for all intenal widgets + ModuleBase_DoubleSpinBox* myXSpin; ///< the spin box for the X coordinate + ModuleBase_DoubleSpinBox* myYSpin; ///< the spin box for the Y coordinate + + //std::string myOptionParam; /// Parameter name which has to be taken from previous feature + + CompositeFeaturePtr mySketch; +}; + +#endif diff --git a/src/PartSet/PartSet_WidgetPoint2dDistance.cpp b/src/PartSet/PartSet_WidgetPoint2dDistance.cpp new file mode 100644 index 000000000..9fdbc3f27 --- /dev/null +++ b/src/PartSet/PartSet_WidgetPoint2dDistance.cpp @@ -0,0 +1,113 @@ +// File: PartSet_WidgetPoint2dDistance.h +// Created: 23 June 2014 +// Author: Vitaly Smetannikov + +#include "PartSet_WidgetPoint2dDistance.h" +#include "PartSet_Tools.h" + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include + +PartSet_WidgetPoint2dDistance::PartSet_WidgetPoint2dDistance(QWidget* theParent, + const Config_WidgetAPI* theData, + const std::string& theParentId) + : ModuleBase_WidgetDoubleValue(theParent, theData, theParentId) +{ + myFirstPntName = theData->getProperty("first_point"); +} + +PartSet_WidgetPoint2dDistance::~PartSet_WidgetPoint2dDistance() +{ +} + +//bool PartSet_WidgetPoint2dDistance::setValue(ModuleBase_WidgetValue* theValue) +//{ +// bool isDone = false; +// +// if (theValue) { +// ModuleBase_WidgetValueFeature* aFeatureValue = +// dynamic_cast(theValue); +// if (aFeatureValue) { +// std::shared_ptr aPnt = aFeatureValue->point(); +// ObjectPtr aObject = aFeatureValue->object(); +// FeaturePtr aFeature = std::dynamic_pointer_cast(aObject); +// if (aFeature && aPnt) { +// setPoint(aFeature, aPnt); +// isDone = true; +// } +// } +// } +// return isDone; +//} + +void PartSet_WidgetPoint2dDistance::setPoint(FeaturePtr theFeature, + const std::shared_ptr& thePnt) +{ + std::shared_ptr aData = theFeature->data(); + std::shared_ptr aPoint = std::dynamic_pointer_cast( + aData->attribute(myFirstPntName)); + if (!aPoint) + return; + + double aRadius = thePnt->distance(aPoint->pnt()); + AttributeDoublePtr aReal = aData->real(attributeID()); + if (aReal && (aReal->value() != aRadius)) { + aReal->setValue(aRadius); + mySpinBox->setValue(aRadius); + } +} + +void PartSet_WidgetPoint2dDistance::activate() +{ + XGUI_ViewerProxy* aViewer = myWorkshop->viewer(); + connect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)), + this, SLOT(onMouseMove(ModuleBase_IViewWindow*, QMouseEvent*))); + connect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)), + this, SLOT(onMouseRelease(ModuleBase_IViewWindow*, QMouseEvent*))); +} + +void PartSet_WidgetPoint2dDistance::deactivate() +{ + ModuleBase_IViewer* aViewer = myWorkshop->viewer(); + disconnect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)), + this, SLOT(onMouseMove(ModuleBase_IViewWindow*, QMouseEvent*))); + disconnect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)), + this, SLOT(onMouseRelease(ModuleBase_IViewWindow*, QMouseEvent*))); +} + +void PartSet_WidgetPoint2dDistance::onMouseRelease(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) +{ + gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWnd->v3dView()); + + double aX, aY; + PartSet_Tools::convertTo2D(aPoint, mySketch, theWnd->v3dView(), aX, aY); + + std::shared_ptr aPnt = std::shared_ptr(new GeomAPI_Pnt2d(aX, aY)); + setPoint(feature(), aPnt); + emit focusOutWidget(this); +} + +void PartSet_WidgetPoint2dDistance::onMouseMove(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) +{ + gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWnd->v3dView()); + + double aX, aY; + PartSet_Tools::convertTo2D(aPoint, mySketch, theWnd->v3dView(), aX, aY); + + std::shared_ptr aPnt = std::shared_ptr(new GeomAPI_Pnt2d(aX, aY)); + setPoint(feature(), aPnt); +} + + diff --git a/src/PartSet/PartSet_WidgetPoint2dDistance.h b/src/PartSet/PartSet_WidgetPoint2dDistance.h new file mode 100644 index 000000000..84d962a06 --- /dev/null +++ b/src/PartSet/PartSet_WidgetPoint2dDistance.h @@ -0,0 +1,64 @@ +// File: PartSet_WidgetPoint2dDistance.h +// Created: 23 June 2014 +// Author: Vitaly Smetannikov + +#ifndef PartSet_WidgetPoint2dDistance_H +#define PartSet_WidgetPoint2dDistance_H + +#include "PartSet.h" +#include + +#include + +class GeomAPI_Pnt2d; +class XGUI_Workshop; +class ModuleBase_IViewWindow; +class QMouseEvent; + +class PARTSET_EXPORT PartSet_WidgetPoint2dDistance : public ModuleBase_WidgetDoubleValue +{ +Q_OBJECT + public: + /// Constructor + /// \theParent the parent object + /// \theData the widget configuation. The attribute of the model widget is obtained from + PartSet_WidgetPoint2dDistance(QWidget* theParent, const Config_WidgetAPI* theData, + const std::string& theParentId); + + virtual ~PartSet_WidgetPoint2dDistance(); + + /// The methiod called when widget is activated + virtual void activate(); + + /// The methiod called when widget is deactivated + virtual void deactivate(); + + /// Set the given wrapped value to the current widget + /// This value should be processed in the widget according to the needs + /// \param theValue the wrapped widget value + //virtual bool setValue(ModuleBase_WidgetValue* theValue); + + XGUI_Workshop* workshop() const { return myWorkshop; } + + void setWorkshop(XGUI_Workshop* theWork) { myWorkshop = theWork; } + + /// \returns the sketch instance + CompositeFeaturePtr sketch() const { return mySketch; } + void setSketch(CompositeFeaturePtr theSketch) { mySketch = theSketch; } + + protected slots: + void onMouseRelease(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); + void onMouseMove(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); + +protected: + /// Set the second point which defines a value in the widget as a distance with a first point defined by feature + void setPoint(FeaturePtr theFeature, const std::shared_ptr& thePnt); + + private: + XGUI_Workshop* myWorkshop; + std::string myFirstPntName; + + CompositeFeaturePtr mySketch; +}; + +#endif diff --git a/src/PartSet/PartSet_WidgetShapeSelector.cpp b/src/PartSet/PartSet_WidgetShapeSelector.cpp new file mode 100644 index 000000000..9e391c62e --- /dev/null +++ b/src/PartSet/PartSet_WidgetShapeSelector.cpp @@ -0,0 +1,59 @@ +// File: PartSet_WidgetShapeSelector.cpp +// Created: 27 Nov 2014 +// Author: Vitaly Smetannikov + +#include "PartSet_WidgetShapeSelector.h" + +#include +#include +#include + + +bool PartSet_WidgetShapeSelector::storeValue() const +{ + if (!mySelectedObject) + return false; + + FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(mySelectedObject); + if (aSelectedFeature == myFeature) // In order to avoid selection of the same object + return false; + + DataPtr aData = myFeature->data(); + if (myUseSubShapes && myShape) { + AttributePtr aAttr = aData->attribute(attributeID()); + AttributeRefAttrPtr aRefAttr = + std::dynamic_pointer_cast(aAttr); + if (aRefAttr) { + TopoDS_Shape aShape = myShape->impl(); + AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(mySelectedObject, aShape, mySketch); + if (mySelectedObject) + aRefAttr->setObject(mySelectedObject); + if (aPntAttr) + aRefAttr->setAttr(aPntAttr); + + updateObject(myFeature); + return true; + } + } + return ModuleBase_WidgetShapeSelector::storeValue(); +} + +//********************************************* +bool PartSet_WidgetConstraintShapeSelector::storeValue() const +{ + FeaturePtr aFeature = ModelAPI_Feature::feature(mySelectedObject); + if (aFeature) { + std::shared_ptr aSPFeature = + std::dynamic_pointer_cast(aFeature); + if ((!aSPFeature) && (!myShape->isNull())) { + ObjectPtr aObj = PartSet_Tools::createFixedObjectByEdge(myShape->impl(), + mySelectedObject, mySketch); + if (aObj) { + PartSet_WidgetConstraintShapeSelector* that = (PartSet_WidgetConstraintShapeSelector*) this; + that->mySelectedObject = aObj; + } + } + } + return ModuleBase_WidgetShapeSelector::storeValue(); +} + diff --git a/src/PartSet/PartSet_WidgetShapeSelector.h b/src/PartSet/PartSet_WidgetShapeSelector.h new file mode 100644 index 000000000..fabbea2ae --- /dev/null +++ b/src/PartSet/PartSet_WidgetShapeSelector.h @@ -0,0 +1,56 @@ +// File: PartSet_WidgetShapeSelector.h +// Created: 27 Nov 2014 +// Author: Vitaly Smetannikov + + +#ifndef PartSet_WidgetShapeSelector_H +#define PartSet_WidgetShapeSelector_H + +#include "PartSet.h" + +#include + +#include + +class PARTSET_EXPORT PartSet_WidgetShapeSelector: public ModuleBase_WidgetShapeSelector +{ +Q_OBJECT + public: + PartSet_WidgetShapeSelector(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop, + const Config_WidgetAPI* theData, const std::string& theParentId) + : ModuleBase_WidgetShapeSelector(theParent, theWorkshop, theData, theParentId) {} + + virtual ~PartSet_WidgetShapeSelector() {} + + /// Saves the internal parameters to the given feature + virtual bool storeValue() const; + + void setSketcher(CompositeFeaturePtr theSketch) { mySketch = theSketch; } + CompositeFeaturePtr sketch() const { return mySketch; } + +private: + CompositeFeaturePtr mySketch; +}; + + +class PARTSET_EXPORT PartSet_WidgetConstraintShapeSelector: public ModuleBase_WidgetShapeSelector +{ +Q_OBJECT + public: + PartSet_WidgetConstraintShapeSelector(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop, + const Config_WidgetAPI* theData, const std::string& theParentId) + : ModuleBase_WidgetShapeSelector(theParent, theWorkshop, theData, theParentId) {} + + virtual ~PartSet_WidgetConstraintShapeSelector() {} + + /// Saves the internal parameters to the given feature + virtual bool storeValue() const; + + void setSketcher(CompositeFeaturePtr theSketch) { mySketch = theSketch; } + CompositeFeaturePtr sketch() const { return mySketch; } + +private: + CompositeFeaturePtr mySketch; +}; + +#endif \ No newline at end of file diff --git a/src/PartSet/PartSet_WidgetSketchLabel.cpp b/src/PartSet/PartSet_WidgetSketchLabel.cpp index b6f18fb7f..46f641e00 100644 --- a/src/PartSet/PartSet_WidgetSketchLabel.cpp +++ b/src/PartSet/PartSet_WidgetSketchLabel.cpp @@ -3,19 +3,45 @@ // Author: Vitaly SMETANNIKOV #include "PartSet_WidgetSketchLabel.h" -#include "PartSet_OperationSketch.h" +#include "PartSet_Tools.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 PLANE_SIZE "200" +#define SKETCH_WIDTH "4" + + PartSet_WidgetSketchLabel::PartSet_WidgetSketchLabel(QWidget* theParent, const Config_WidgetAPI* theData, const std::string& theParentId) - : ModuleBase_ModelWidget(theParent, theData, theParentId) + : ModuleBase_ModelWidget(theParent, theData, theParentId), myPreviewDisplayed(false) { myText = QString::fromStdString(theData->getProperty("title")); myLabel = new QLabel("", theParent); @@ -25,6 +51,11 @@ PartSet_WidgetSketchLabel::PartSet_WidgetSketchLabel(QWidget* theParent, myLabel->setIndent(5); } +PartSet_WidgetSketchLabel::~PartSet_WidgetSketchLabel() +{ + erasePreviewPlanes(); +} + QList PartSet_WidgetSketchLabel::getControls() const { return QList(); @@ -35,30 +66,222 @@ QWidget* PartSet_WidgetSketchLabel::getControl() const return myLabel; } -void PartSet_WidgetSketchLabel::setOperationsMgr(XGUI_OperationMgr* theMgr) +void PartSet_WidgetSketchLabel::onPlaneSelected() { - ModuleBase_Operation* aOperation = theMgr->currentOperation(); - if (aOperation->inherits("PartSet_OperationSketch")) { - PartSet_OperationSketch* aSketchOpe = static_cast(aOperation); - updateLabel(aSketchOpe); - connect(aSketchOpe, SIGNAL(updatePropPanel()), this, - SLOT(onPlaneSelected())); + XGUI_Selection* aSelection = myWorkshop->selector()->selection(); + QList aSelected = aSelection->getSelected(); + if (!aSelected.empty()) { + ModuleBase_ViewerPrs aPrs = aSelected.first(); + TopoDS_Shape aShape = aPrs.shape(); + if (!aShape.IsNull()) { + std::shared_ptr aDir = setSketchPlane(aShape); + if (aDir) { + erasePreviewPlanes(); + + if (aPrs.object() && (feature() != aPrs.object())) { + DataPtr aData = feature()->data(); + AttributeSelectionPtr aSelAttr = + std::dynamic_pointer_cast + (aData->attribute(SketchPlugin_Feature::EXTERNAL_ID())); + if (aSelAttr) { + ResultPtr aRes = std::dynamic_pointer_cast(aPrs.object()); + if (aRes) { + GeomShapePtr aShapePtr(new GeomAPI_Shape()); + aShapePtr->setImpl(new TopoDS_Shape(aShape)); + aSelAttr->setValue(aRes, aShapePtr); + } + } + } else + myWorkshop->viewer()->setViewProjection(aDir->x(), aDir->y(), aDir->z()); + + // Clear text in the label + myLabel->setText(""); + myLabel->setToolTip(""); + disconnect(myWorkshop->selector(), SIGNAL(selectionChanged()), + this, SLOT(onPlaneSelected())); + + // Clear selection mode and define sketching mode + XGUI_Displayer* aDisp = myWorkshop->displayer(); + aDisp->removeSelectionFilter(myFaceFilter); + aDisp->closeLocalContexts(); + emit planeSelected(plane()); + setSketchingMode(); + + // Update sketcher actions + XGUI_ActionsMgr* anActMgr = myWorkshop->actionsMgr(); + anActMgr->update(); + } + } } } -void PartSet_WidgetSketchLabel::onPlaneSelected() +std::shared_ptr PartSet_WidgetSketchLabel::plane() const { - PartSet_OperationSketch* aSketchOpe = static_cast(sender()); - updateLabel(aSketchOpe); + CompositeFeaturePtr aSketch = std::dynamic_pointer_cast(myFeature); + return PartSet_Tools::sketchPlane(aSketch); + } -void PartSet_WidgetSketchLabel::updateLabel(PartSet_OperationSketch* theSketchOpe) +void PartSet_WidgetSketchLabel::activate() { - if (theSketchOpe->hasSketchPlane()) { - myLabel->setText(""); - myLabel->setToolTip(""); + std::shared_ptr aPlane = plane(); + if (aPlane) { + setSketchingMode(); } else { + // We have to select a plane before any operation + showPreviewPlanes(); + + XGUI_Displayer* aDisp = myWorkshop->displayer(); + aDisp->openLocalContext(); + aDisp->activateObjects(QIntList()); + if (myFaceFilter.IsNull()) + myFaceFilter = new StdSelect_FaceFilter(StdSelect_Plane); + aDisp->addSelectionFilter(myFaceFilter); + QIntList aModes; + aModes << TopAbs_FACE; + aDisp->activateObjects(aModes); + myLabel->setText(myText); myLabel->setToolTip(myTooltip); + + connect(myWorkshop->selector(), SIGNAL(selectionChanged()), this, SLOT(onPlaneSelected())); + aDisp->updateViewer(); + } +} + +void PartSet_WidgetSketchLabel::deactivate() +{ + + XGUI_Displayer* aDisp = myWorkshop->displayer(); + aDisp->removeSelectionFilter(myFaceFilter); + //aDisp->removeSelectionFilter(mySketchFilter); + aDisp->closeLocalContexts(); + erasePreviewPlanes(); +} + +void PartSet_WidgetSketchLabel::erasePreviewPlanes() +{ + if (myPreviewDisplayed) { + XGUI_Displayer* aDisp = myWorkshop->displayer(); + aDisp->eraseAIS(myYZPlane, false); + aDisp->eraseAIS(myXZPlane, false); + aDisp->eraseAIS(myXYPlane, false); + myPreviewDisplayed = false; } } + +void PartSet_WidgetSketchLabel::showPreviewPlanes() +{ + if (myPreviewDisplayed) + return; + + if (!myYZPlane) { // If planes are not created + // Create Preview + std::shared_ptr anOrigin(new GeomAPI_Pnt(0, 0, 0)); + std::shared_ptr aYZDir(new GeomAPI_Dir(1, 0, 0)); + std::shared_ptr aXZDir(new GeomAPI_Dir(0, 1, 0)); + std::shared_ptr aXYDir(new GeomAPI_Dir(0, 0, 1)); + + int aR[] = {255, 0, 0}; + int aG[] = {0, 255, 0}; + int aB[] = {0, 0, 255}; + + myYZPlane = createPreviewPlane(anOrigin, aYZDir, aR); + myXZPlane = createPreviewPlane(anOrigin, aXZDir, aG); + myXYPlane = createPreviewPlane(anOrigin, aXYDir, aB); + } + XGUI_Displayer* aDisp = myWorkshop->displayer(); + aDisp->displayAIS(myYZPlane, false); + aDisp->displayAIS(myXZPlane, false); + aDisp->displayAIS(myXYPlane, false); + myPreviewDisplayed = true; +} + + +AISObjectPtr PartSet_WidgetSketchLabel::createPreviewPlane(std::shared_ptr theOrigin, + std::shared_ptr theNorm, + const int theRGB[3]) +{ + double aSize = Config_PropManager::integer("Sketch planes", "Size of planes", PLANE_SIZE); + std::shared_ptr aFace = GeomAlgoAPI_FaceBuilder::square(theOrigin, theNorm, aSize); + AISObjectPtr aAIS = AISObjectPtr(new GeomAPI_AISObject()); + aAIS->createShape(aFace); + aAIS->setWidth(Config_PropManager::integer("Sketch planes", "planes_thickness", SKETCH_WIDTH)); + aAIS->setColor(theRGB[0], theRGB[1], theRGB[2]); + return aAIS; +} + + +std::shared_ptr PartSet_WidgetSketchLabel::setSketchPlane(const TopoDS_Shape& theShape) +{ + if (theShape.IsNull()) + return std::shared_ptr(); + + // get selected shape + std::shared_ptr aGShape(new GeomAPI_Shape); + aGShape->setImpl(new TopoDS_Shape(theShape)); + + // get plane parameters + std::shared_ptr aPlane = GeomAlgoAPI_FaceBuilder::plane(aGShape); + + // set plane parameters to feature + std::shared_ptr aData = feature()->data(); + double anA, aB, aC, aD; + aPlane->coefficients(anA, aB, aC, aD); + + // calculate attributes of the sketch + std::shared_ptr aNormDir(new GeomAPI_Dir(anA, aB, aC)); + std::shared_ptr aCoords = aNormDir->xyz(); + std::shared_ptr aZero(new GeomAPI_XYZ(0, 0, 0)); + aCoords = aCoords->multiplied(-aD * aCoords->distance(aZero)); + std::shared_ptr anOrigPnt(new GeomAPI_Pnt(aCoords)); + // X axis is preferable to be dirX on the sketch + const double tol = Precision::Confusion(); + bool isX = fabs(anA - 1.0) < tol && fabs(aB) < tol && fabs(aC) < tol; + std::shared_ptr aTempDir( + isX ? new GeomAPI_Dir(0, 1, 0) : new GeomAPI_Dir(1, 0, 0)); + std::shared_ptr aYDir(new GeomAPI_Dir(aNormDir->cross(aTempDir))); + std::shared_ptr aXDir(new GeomAPI_Dir(aYDir->cross(aNormDir))); + + std::shared_ptr anOrigin = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Sketch::ORIGIN_ID())); + anOrigin->setValue(anOrigPnt); + std::shared_ptr aNormal = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Sketch::NORM_ID())); + aNormal->setValue(aNormDir); + std::shared_ptr aDirX = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Sketch::DIRX_ID())); + aDirX->setValue(aXDir); + std::shared_ptr aDirY = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Sketch::DIRY_ID())); + aDirY->setValue(aYDir); + std::shared_ptr aDir = aPlane->direction(); + return aDir; +} + + +void PartSet_WidgetSketchLabel::setSketchingMode() +{ + XGUI_Displayer* aDisp = myWorkshop->displayer(); + QIntList aModes; + // Clear standard selection modes if they are defined + aDisp->activateObjects(aModes); + aDisp->openLocalContext(); + + // Set filter + std::shared_ptr aPlane = plane(); + double aA, aB, aC, aD; + aPlane->coefficients(aA, aB, aC, aD); + gp_Pln aPln(aA, aB, aC, aD); + // No selection of external objects + //mySketchFilter = new ModuleBase_ShapeInPlaneFilter(aPln); + //aDisp->addSelectionFilter(mySketchFilter); + + // Get default selection modes + aModes.append(AIS_DSM_Text); + aModes.append(AIS_DSM_Line); + aModes.append(AIS_Shape::SelectionMode((TopAbs_ShapeEnum) TopAbs_VERTEX)); + aModes.append(AIS_Shape::SelectionMode((TopAbs_ShapeEnum) TopAbs_EDGE)); + + aDisp->activateObjects(aModes); +} diff --git a/src/PartSet/PartSet_WidgetSketchLabel.h b/src/PartSet/PartSet_WidgetSketchLabel.h index 5ad06d65d..5d4ad6f52 100644 --- a/src/PartSet/PartSet_WidgetSketchLabel.h +++ b/src/PartSet/PartSet_WidgetSketchLabel.h @@ -8,10 +8,19 @@ #include "PartSet.h" #include +#include + +#include +#include +#include + +#include +#include class QLabel; class XGUI_OperationMgr; -class PartSet_OperationSketch; +class XGUI_Workshop; +//class PartSet_OperationSketch; class PARTSET_EXPORT PartSet_WidgetSketchLabel : public ModuleBase_ModelWidget { @@ -20,9 +29,7 @@ Q_OBJECT PartSet_WidgetSketchLabel(QWidget* theParent, const Config_WidgetAPI* theData, const std::string& theParentId); - virtual ~PartSet_WidgetSketchLabel() - { - } + virtual ~PartSet_WidgetSketchLabel(); /// Saves the internal parameters to the given feature /// \param theFeature a model feature to be changed @@ -42,17 +49,49 @@ Q_OBJECT QWidget* getControl() const; - void setOperationsMgr(XGUI_OperationMgr* theMgr); + /// The methiod called when widget is activated + virtual void activate(); + + /// The methiod called when widget is deactivated + virtual void deactivate(); + + XGUI_Workshop* workshop() const { return myWorkshop; } + + void setWorkshop(XGUI_Workshop* theWork) { myWorkshop = theWork; } + + std::shared_ptr plane() const; + +signals: + void planeSelected(const std::shared_ptr& thePln); private slots: void onPlaneSelected(); private: - void updateLabel(PartSet_OperationSketch* theSketchOpe); + AISObjectPtr createPreviewPlane(std::shared_ptr theOrigin, + std::shared_ptr theNorm, + const int theRGB[3]); + + std::shared_ptr setSketchPlane(const TopoDS_Shape& theShape); + + void erasePreviewPlanes(); + void showPreviewPlanes(); + + void setSketchingMode(); QLabel* myLabel; QString myText; QString myTooltip; + + XGUI_Workshop* myWorkshop; + + AISObjectPtr myYZPlane; + AISObjectPtr myXZPlane; + AISObjectPtr myXYPlane; + bool myPreviewDisplayed; + + Handle(StdSelect_FaceFilter) myFaceFilter; + //Handle(ModuleBase_ShapeInPlaneFilter) mySketchFilter; }; #endif diff --git a/src/PartSet/PartSet_icons.qrc b/src/PartSet/PartSet_icons.qrc index d0985d40c..b0bffcc5a 100644 --- a/src/PartSet/PartSet_icons.qrc +++ b/src/PartSet/PartSet_icons.qrc @@ -27,5 +27,6 @@ icons/radius_constr.png icons/shape_group.png icons/fixed.png + icons/placement.png diff --git a/src/PartSet/icons/placement.png b/src/PartSet/icons/placement.png new file mode 100644 index 000000000..906a1ad49 Binary files /dev/null and b/src/PartSet/icons/placement.png differ diff --git a/src/PartSetPlugin/CMakeLists.txt b/src/PartSetPlugin/CMakeLists.txt index e115ab9db..1f249f9b6 100644 --- a/src/PartSetPlugin/CMakeLists.txt +++ b/src/PartSetPlugin/CMakeLists.txt @@ -15,8 +15,12 @@ SET(PROJECT_SOURCES PartSetPlugin_Remove.cpp ) +SET(XML_RESOURCES + plugin-PartSet.xml +) + ADD_DEFINITIONS(-DPARTSETPLUGIN_EXPORTS) -ADD_LIBRARY(PartSetPlugin MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS}) +ADD_LIBRARY(PartSetPlugin MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${XML_RESOURCES}) TARGET_LINK_LIBRARIES(PartSetPlugin ${PROJECT_LIBRARIES} ModelAPI) INCLUDE_DIRECTORIES( @@ -24,9 +28,5 @@ INCLUDE_DIRECTORIES( ../GeomAPI ) -SET(XML_RESOURCES - plugin-PartSet.xml -) - INSTALL(TARGETS PartSetPlugin DESTINATION plugins) INSTALL(FILES ${XML_RESOURCES} DESTINATION plugins) diff --git a/src/PartSetPlugin/plugin-PartSet.xml b/src/PartSetPlugin/plugin-PartSet.xml index 4a846cc42..db6893e50 100644 --- a/src/PartSetPlugin/plugin-PartSet.xml +++ b/src/PartSetPlugin/plugin-PartSet.xml @@ -2,8 +2,15 @@ - - + + diff --git a/src/SketchPlugin/SketchPlugin_Arc.cpp b/src/SketchPlugin/SketchPlugin_Arc.cpp index 9f717bd70..0ae869322 100644 --- a/src/SketchPlugin/SketchPlugin_Arc.cpp +++ b/src/SketchPlugin/SketchPlugin_Arc.cpp @@ -23,6 +23,8 @@ const double tolerance = 1e-7; SketchPlugin_Arc::SketchPlugin_Arc() : SketchPlugin_Feature() { + myStartUpdate = false; + myEndUpdate = false; } void SketchPlugin_Arc::initAttributes() @@ -42,10 +44,10 @@ void SketchPlugin_Arc::execute() if (aSketch && isFeatureValid()) { // compute a circle point in 3D view std::shared_ptr aCenterAttr = std::dynamic_pointer_cast< - GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::CENTER_ID())); + GeomDataAPI_Point2D>(data()->attribute(CENTER_ID())); // compute the arc start point std::shared_ptr aStartAttr = std::dynamic_pointer_cast< - GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::START_ID())); + GeomDataAPI_Point2D>(data()->attribute(START_ID())); std::shared_ptr aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y())); // make a visible point @@ -59,30 +61,29 @@ void SketchPlugin_Arc::execute() // make a visible circle std::shared_ptr aNDir = std::dynamic_pointer_cast( aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID())); - bool aHasPlane = aNDir && !(aNDir->x() == 0 && aNDir->y() == 0 && aNDir->z() == 0); - if (aHasPlane) { - std::shared_ptr aNormal = aNDir->dir(); - std::shared_ptr aStartPoint(aSketch->to3D(aStartAttr->x(), aStartAttr->y())); - - // compute and change the arc end point - std::shared_ptr anEndAttr = std::dynamic_pointer_cast< - GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::END_ID())); - std::shared_ptr aCircleForArc( - new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt())); - std::shared_ptr aProjection = aCircleForArc->project(anEndAttr->pnt()); - if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance) - anEndAttr->setValue(aProjection); - std::shared_ptr aEndPoint(aSketch->to3D(anEndAttr->x(), anEndAttr->y())); - - std::shared_ptr aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircleArc( - aCenter, aStartPoint, aEndPoint, aNormal); - if (aCircleShape) { - std::shared_ptr aConstr2 = document()->createConstruction( - data(), 1); - aConstr2->setShape(aCircleShape); - aConstr2->setIsInHistory(false); - setResult(aConstr2, 1); - } + std::shared_ptr aNormal = aNDir->dir(); + std::shared_ptr aStartPoint(aSketch->to3D(aStartAttr->x(), aStartAttr->y())); + + // compute and change the arc end point + std::shared_ptr anEndAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(END_ID())); + /* must be automatically done in attributeChanged + std::shared_ptr aCircleForArc( + new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt())); + std::shared_ptr aProjection = aCircleForArc->project(anEndAttr->pnt()); + if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance) + anEndAttr->setValue(aProjection); + */ + std::shared_ptr aEndPoint(aSketch->to3D(anEndAttr->x(), anEndAttr->y())); + + std::shared_ptr aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircleArc( + aCenter, aStartPoint, aEndPoint, aNormal); + if (aCircleShape) { + std::shared_ptr aConstr2 = document()->createConstruction( + data(), 1); + aConstr2->setShape(aCircleShape); + aConstr2->setIsInHistory(false); + setResult(aConstr2, 1); } } } @@ -95,7 +96,7 @@ AISObjectPtr SketchPlugin_Arc::getAISObject(AISObjectPtr thePrevious) if (!isFeatureValid()) { // compute a circle point in 3D view std::shared_ptr aCenterAttr = std::dynamic_pointer_cast< - GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::CENTER_ID())); + GeomDataAPI_Point2D>(data()->attribute(CENTER_ID())); if (aCenterAttr->isInitialized()) { std::shared_ptr aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y())); @@ -146,6 +147,8 @@ void SketchPlugin_Arc::move(double theDeltaX, double theDeltaY) aData->attribute(SketchPlugin_Arc::CENTER_ID())); aPoint1->move(theDeltaX, theDeltaY); + myStartUpdate = true; + myEndUpdate = true; std::shared_ptr aPoint2 = std::dynamic_pointer_cast( aData->attribute(SketchPlugin_Arc::START_ID())); aPoint2->move(theDeltaX, theDeltaY); @@ -153,6 +156,8 @@ void SketchPlugin_Arc::move(double theDeltaX, double theDeltaY) std::shared_ptr aPoint3 = std::dynamic_pointer_cast( aData->attribute(SketchPlugin_Arc::END_ID())); aPoint3->move(theDeltaX, theDeltaY); + myStartUpdate = false; + myEndUpdate = false; } double SketchPlugin_Arc::distanceToPoint(const std::shared_ptr& thePoint) @@ -194,3 +199,40 @@ bool SketchPlugin_Arc::isFeatureValid() return aCenterAttr->isInitialized() && aStartAttr->isInitialized() && anEndAttr->isInitialized(); } + +void SketchPlugin_Arc::attributeChanged(const std::string& theID) +{ + std::shared_ptr aCenterAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(CENTER_ID())); + if (!aCenterAttr->isInitialized()) + return; + std::shared_ptr aStartAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(START_ID())); + if (!aStartAttr->isInitialized()) + return; + std::shared_ptr anEndAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(END_ID())); + if (!anEndAttr->isInitialized()) + return; + + // update the points in accordance to the changed point changes + if (theID == END_ID() && !myEndUpdate) { + myEndUpdate = true; + // compute and change the arc end point + std::shared_ptr aCircleForArc( + new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt())); + std::shared_ptr aProjection = aCircleForArc->project(anEndAttr->pnt()); + if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance) + anEndAttr->setValue(aProjection); + myEndUpdate = false; + } else if (theID == START_ID() && !myStartUpdate) { + myStartUpdate = true; + // compute and change the arc end point + std::shared_ptr aCircleForArc( + new GeomAPI_Circ2d(aCenterAttr->pnt(), anEndAttr->pnt())); + std::shared_ptr aProjection = aCircleForArc->project(aStartAttr->pnt()); + if (aProjection && aStartAttr->pnt()->distance(aProjection) > tolerance) + aStartAttr->setValue(aProjection); + myStartUpdate = false; + } +} diff --git a/src/SketchPlugin/SketchPlugin_Arc.h b/src/SketchPlugin/SketchPlugin_Arc.h index 3958adbd7..e03da285a 100644 --- a/src/SketchPlugin/SketchPlugin_Arc.h +++ b/src/SketchPlugin/SketchPlugin_Arc.h @@ -19,6 +19,10 @@ */ class SketchPlugin_Arc : public SketchPlugin_Feature, public GeomAPI_IPresentable { + /// to avoid cyclic dependencies in automatic updates: they mean that + /// update is performed right now and automatic updates are not needed + bool myStartUpdate, myEndUpdate; + public: /// Arc feature kind inline static const std::string& ID() @@ -62,6 +66,10 @@ class SketchPlugin_Arc : public SketchPlugin_Feature, public GeomAPI_IPresentabl /// Request for initialization of data model of the feature: adding all attributes SKETCHPLUGIN_EXPORT virtual void initAttributes(); + /// Called on change of any argument-attribute of this object + /// \param theID identifier of changed attribute + SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + /// Returns the AIS preview virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious); diff --git a/src/SketchPlugin/SketchPlugin_Circle.cpp b/src/SketchPlugin/SketchPlugin_Circle.cpp index 209f9744a..eeb77874d 100644 --- a/src/SketchPlugin/SketchPlugin_Circle.cpp +++ b/src/SketchPlugin/SketchPlugin_Circle.cpp @@ -100,18 +100,17 @@ bool SketchPlugin_Circle::isFixed() { return data()->selection(EXTERNAL_ID())->context(); } -void SketchPlugin_Circle::attributeChanged() { - static bool myIsUpdated = false; // to avoid infinitive cycle on attrubtes change - std::shared_ptr aSelection = data()->selection(EXTERNAL_ID())->value(); - // update arguments due to the selection value - if (aSelection && !aSelection->isNull() && aSelection->isEdge() && !myIsUpdated) { - myIsUpdated = true; - std::shared_ptr anEdge( new GeomAPI_Edge(aSelection)); - std::shared_ptr aCirc = anEdge->circle(); - std::shared_ptr aCenterAttr = - std::dynamic_pointer_cast(attribute(CENTER_ID())); - aCenterAttr->setValue(sketch()->to2D(aCirc->center())); - real(RADIUS_ID())->setValue(aCirc->radius()); - myIsUpdated = false; +void SketchPlugin_Circle::attributeChanged(const std::string& theID) { + if (theID == EXTERNAL_ID()) { + std::shared_ptr aSelection = data()->selection(EXTERNAL_ID())->value(); + // update arguments due to the selection value + if (aSelection && !aSelection->isNull() && aSelection->isEdge()) { + std::shared_ptr anEdge( new GeomAPI_Edge(aSelection)); + std::shared_ptr aCirc = anEdge->circle(); + std::shared_ptr aCenterAttr = + std::dynamic_pointer_cast(attribute(CENTER_ID())); + aCenterAttr->setValue(sketch()->to2D(aCirc->center())); + real(RADIUS_ID())->setValue(aCirc->radius()); + } } } diff --git a/src/SketchPlugin/SketchPlugin_Circle.h b/src/SketchPlugin/SketchPlugin_Circle.h index 8ceef34eb..08263db8c 100644 --- a/src/SketchPlugin/SketchPlugin_Circle.h +++ b/src/SketchPlugin/SketchPlugin_Circle.h @@ -77,7 +77,7 @@ class SketchPlugin_Circle : public SketchPlugin_Feature //, public GeomAPI_IPre virtual double distanceToPoint(const std::shared_ptr& thePoint); /// Called on change of any argument-attribute of this object - SKETCHPLUGIN_EXPORT virtual void attributeChanged(); + SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); /// Use plugin manager for features creation SketchPlugin_Circle(); diff --git a/src/SketchPlugin/SketchPlugin_ConstraintDistance.cpp b/src/SketchPlugin/SketchPlugin_ConstraintDistance.cpp index 611d85a0f..092d3c74c 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintDistance.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintDistance.cpp @@ -101,12 +101,12 @@ AISObjectPtr SketchPlugin_ConstraintDistance::getAISObject(AISObjectPtr thePrevi // value calculation std::shared_ptr aValueAttr = std::dynamic_pointer_cast< ModelAPI_AttributeDouble>(aData->attribute(SketchPlugin_Constraint::VALUE())); - double aValue = aValueAttr->value(); + double aValue = 0; // Issue #196: checking the positivity of the distance constraint // there is a validator for a distance constraint, that the value should be positive // in case if an invalid value is set, the current distance value is shown - if (aValue <= 0) - aValue = calculateCurrentDistance(); + if (aValueAttr->isInitialized()) + aValue = aValueAttr->value(); AISObjectPtr anAIS = thePrevious; if (!anAIS) @@ -162,6 +162,20 @@ double SketchPlugin_ConstraintDistance::calculateCurrentDistance() const return aDistance; } +void SketchPlugin_ConstraintDistance::attributeChanged(const std::string& theID) { + if (theID == SketchPlugin_Constraint::ENTITY_A() || + theID == SketchPlugin_Constraint::ENTITY_B()) + { + std::shared_ptr aValueAttr = std::dynamic_pointer_cast< + ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE())); + if (!aValueAttr->isInitialized()) { // only if it is not initialized, try to compute the current value + double aDistance = calculateCurrentDistance(); + if (aDistance > 0) { // set as value the length of updated references + aValueAttr->setValue(aDistance); + } + } + } +} //************************************************************************************* std::shared_ptr getFeaturePoint(DataPtr theData, diff --git a/src/SketchPlugin/SketchPlugin_ConstraintDistance.h b/src/SketchPlugin/SketchPlugin_ConstraintDistance.h index 8ac80c313..ef58b2453 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintDistance.h +++ b/src/SketchPlugin/SketchPlugin_ConstraintDistance.h @@ -56,6 +56,10 @@ class SketchPlugin_ConstraintDistance : public SketchPlugin_ConstraintBase /// \param theDeltaY the delta for Y coordinate is moved SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY); + /// Called on change of any argument-attribute of this object + /// \param theID identifier of changed attribute + SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + /// Returns the current distance between the feature attributes double calculateCurrentDistance() const; diff --git a/src/SketchPlugin/SketchPlugin_ConstraintLength.cpp b/src/SketchPlugin/SketchPlugin_ConstraintLength.cpp index 5b3d0f05f..b5431fddf 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintLength.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintLength.cpp @@ -43,40 +43,49 @@ void SketchPlugin_ConstraintLength::execute() double aLenght = aPoint1->pnt()->distance(aPoint2->pnt()); - std::shared_ptr aValueAttr = std::dynamic_pointer_cast< - ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE())); - if(!aValueAttr->isInitialized()) { - aValueAttr->setValue(aLenght); - } + //std::shared_ptr aValueAttr = std::dynamic_pointer_cast< + // ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE())); + //if(!aValueAttr->isInitialized()) { + // aValueAttr->setValue(aLenght); + //} } } -AISObjectPtr SketchPlugin_ConstraintLength::getAISObject(AISObjectPtr thePrevious) +bool SketchPlugin_ConstraintLength::getPoints( + std::shared_ptr& thePoint1, std::shared_ptr& thePoint2, + std::shared_ptr& theStartPoint, + std::shared_ptr& theEndPoint) { if (!sketch()) - return thePrevious; - + return false; std::shared_ptr aPlane = sketch()->plane(); - std::shared_ptr anAttr = std::dynamic_pointer_cast< ModelAPI_AttributeRefAttr>(data()->attribute(SketchPlugin_Constraint::ENTITY_A())); if (!anAttr) - return thePrevious; + return false; FeaturePtr aFeature = ModelAPI_Feature::feature(anAttr->object()); if (!aFeature || aFeature->getKind() != SketchPlugin_Line::ID()) - return thePrevious; - - std::shared_ptr aFlyOutAttr = std::dynamic_pointer_cast< - GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT())); - + return false; DataPtr aData = aFeature->data(); - std::shared_ptr aStartPoint = std::dynamic_pointer_cast< + theStartPoint = std::dynamic_pointer_cast< GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Line::START_ID())); - std::shared_ptr anEndPoint = std::dynamic_pointer_cast< + theEndPoint = std::dynamic_pointer_cast< GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Line::END_ID())); + thePoint1 = sketch()->to3D(theStartPoint->x(), theStartPoint->y()); + thePoint2 = sketch()->to3D(theEndPoint->x(), theEndPoint->y()); + return true; +} - std::shared_ptr aPoint1 = sketch()->to3D(aStartPoint->x(), aStartPoint->y()); - std::shared_ptr aPoint2 = sketch()->to3D(anEndPoint->x(), anEndPoint->y()); +AISObjectPtr SketchPlugin_ConstraintLength::getAISObject(AISObjectPtr thePrevious) +{ + std::shared_ptr aPoint1, aPoint2; + std::shared_ptr aStartPoint, anEndPoint; + if (!getPoints(aPoint1, aPoint2, aStartPoint, anEndPoint)) + return thePrevious; // not possible to show length because points are not defined + + std::shared_ptr aPlane = sketch()->plane(); + std::shared_ptr aFlyOutAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT())); std::shared_ptr aFlyoutPnt = std::shared_ptr(); if (aFlyOutAttr->isInitialized()) { aFlyoutPnt = sketch()->to3D(aFlyOutAttr->x(), aFlyOutAttr->y()); @@ -89,9 +98,16 @@ AISObjectPtr SketchPlugin_ConstraintLength::getAISObject(AISObjectPtr thePreviou aFlyoutPnt = sketch()->to3D(aFPnt->x(), aFPnt->y()); } // value calculation + // TODO: has to be calculated on definition of reference object + double aDistance = aPoint1->distance(aPoint2); std::shared_ptr aValueAttr = std::dynamic_pointer_cast< ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE())); - double aValue = aValueAttr->value(); + double aValue = aDistance; + if (aValueAttr->isInitialized()) + aValue = aValueAttr->value(); + else + aValueAttr->setValue(aValue); + // End TODO AISObjectPtr anAIS = thePrevious; if (!anAIS) @@ -99,7 +115,8 @@ AISObjectPtr SketchPlugin_ConstraintLength::getAISObject(AISObjectPtr thePreviou anAIS->createDistance(aPoint1, aPoint2, aFlyoutPnt, aPlane, aValue); // Set color from preferences - std::vector aRGB = Config_PropManager::color("Visualization", "length_color", LENGTH_COLOR); + std::vector aRGB = + Config_PropManager::color("Visualization", "length_color", LENGTH_COLOR); anAIS->setColor(aRGB[0], aRGB[1], aRGB[2]); return anAIS; } @@ -115,3 +132,18 @@ void SketchPlugin_ConstraintLength::move(double theDeltaX, double theDeltaY) aPoint->move(theDeltaX, theDeltaY); } +void SketchPlugin_ConstraintLength::attributeChanged(const std::string& theID) { + if (theID == SketchPlugin_Constraint::ENTITY_A()) + { + std::shared_ptr aValueAttr = std::dynamic_pointer_cast< + ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE())); + if (!aValueAttr->isInitialized()) { // only if it is not initialized, try to compute the current value + std::shared_ptr aPoint1, aPoint2; + std::shared_ptr aStartPoint, anEndPoint; + if (getPoints(aPoint1, aPoint2, aStartPoint, anEndPoint)) { + double aLength = aPoint1->distance(aPoint2); + aValueAttr->setValue(aLength); + } + } + } +} diff --git a/src/SketchPlugin/SketchPlugin_ConstraintLength.h b/src/SketchPlugin/SketchPlugin_ConstraintLength.h index 5f3ae9aae..9cdd7e153 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintLength.h +++ b/src/SketchPlugin/SketchPlugin_ConstraintLength.h @@ -10,6 +10,8 @@ #include #include +class GeomDataAPI_Point2D; + #define LENGTH_COLOR "#ff00ff" /** \class SketchPlugin_ConstraintLength @@ -50,8 +52,19 @@ class SketchPlugin_ConstraintLength : public SketchPlugin_ConstraintBase /// \param theDeltaY the delta for Y coordinate is moved SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY); + /// Called on change of any argument-attribute of this object + /// \param theID identifier of changed attribute + SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + /// \brief Use plugin manager for features creation SketchPlugin_ConstraintLength(); + +private: + // retrns the points-base of length, returns false if it is not possible + bool getPoints( + std::shared_ptr& thePoint1, std::shared_ptr& thePoint2, + std::shared_ptr& theStartPoint, + std::shared_ptr& theEndPoint); }; #endif diff --git a/src/SketchPlugin/SketchPlugin_ConstraintRadius.cpp b/src/SketchPlugin/SketchPlugin_ConstraintRadius.cpp index 8da7b3606..77fff3184 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintRadius.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintRadius.cpp @@ -53,47 +53,66 @@ void SketchPlugin_ConstraintRadius::execute() if (aCenterAttr && aStartAttr) aRadius = aCenterAttr->pnt()->distance(aStartAttr->pnt()); } - std::shared_ptr aValueAttr = std::dynamic_pointer_cast< - ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE())); - if(!aValueAttr->isInitialized()) { - aValueAttr->setValue(aRadius); - } + //std::shared_ptr aValueAttr = std::dynamic_pointer_cast< + // ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE())); + //if(!aValueAttr->isInitialized()) { + // aValueAttr->setValue(aRadius); + //} } } -AISObjectPtr SketchPlugin_ConstraintRadius::getAISObject(AISObjectPtr thePrevious) +double SketchPlugin_ConstraintRadius::circleRadius(std::shared_ptr& theCirc) { + static const double kErrorResult = -1.; if (!sketch()) - return thePrevious; + return kErrorResult; std::shared_ptr aData = data(); std::shared_ptr anAttr = std::dynamic_pointer_cast< ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_A())); if (!anAttr) - return thePrevious; - FeaturePtr aFeature = ModelAPI_Feature::feature(anAttr->object()); - std::string aKind = aFeature ? aFeature->getKind() : ""; + return kErrorResult; + theCirc = ModelAPI_Feature::feature(anAttr->object()); + std::string aKind = theCirc ? theCirc->getKind() : ""; if (aKind != SketchPlugin_Circle::ID() && aKind != SketchPlugin_Arc::ID()) - return thePrevious; + return kErrorResult; + + DataPtr aCircData = theCirc->data(); + std::shared_ptr aCenterAttr; + if (aKind == SketchPlugin_Circle::ID()) { + AttributeDoublePtr aCircRadius = std::dynamic_pointer_cast( + aCircData->attribute(SketchPlugin_Circle::RADIUS_ID())); + return aCircRadius->value(); + } else { + aCenterAttr = std::dynamic_pointer_cast( + aCircData->attribute(SketchPlugin_Arc::CENTER_ID())); + std::shared_ptr aStartAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(aCircData->attribute(SketchPlugin_Arc::START_ID())); + return aCenterAttr->pnt()->distance(aStartAttr->pnt()); + } + return kErrorResult; +} + +AISObjectPtr SketchPlugin_ConstraintRadius::getAISObject(AISObjectPtr thePrevious) +{ + std::shared_ptr aCyrcFeature; + double aRadius = circleRadius(aCyrcFeature); + if (aRadius < 0) + return thePrevious; // can not create a good presentation // Flyout point std::shared_ptr aFlyoutAttr = std::dynamic_pointer_cast< - GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT())); + GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT())); std::shared_ptr aFlyoutPnt; if (aFlyoutAttr->isInitialized()) { aFlyoutPnt = sketch()->to3D(aFlyoutAttr->x(), aFlyoutAttr->y()); } // Prepare a circle - aData = aFeature->data(); std::shared_ptr aCenterAttr; - double aRadius; - if (aKind == SketchPlugin_Circle::ID()) { + if (aCyrcFeature->getKind() == SketchPlugin_Circle::ID()) { // circle aCenterAttr = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Circle::CENTER_ID())); - AttributeDoublePtr aCircRadius = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Circle::RADIUS_ID())); - aRadius = aCircRadius->value(); + aCyrcFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID())); if (!aFlyoutPnt) { double aShift = aRadius * 1.1; std::shared_ptr aPnt = aCenterAttr->pnt(); @@ -102,15 +121,12 @@ AISObjectPtr SketchPlugin_ConstraintRadius::getAISObject(AISObjectPtr thePreviou aFlyoutAttr->setValue(aFPnt); aFlyoutPnt = sketch()->to3D(aFPnt->x(), aFPnt->y()); } - } else if (aKind == SketchPlugin_Arc::ID()) { + } else { // arc aCenterAttr = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Arc::CENTER_ID())); - std::shared_ptr aStartAttr = std::dynamic_pointer_cast< - GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Arc::START_ID())); - aRadius = aCenterAttr->pnt()->distance(aStartAttr->pnt()); + aCyrcFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID())); if (!aFlyoutPnt) { std::shared_ptr aStartAttr = std::dynamic_pointer_cast< - GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Arc::START_ID())); + GeomDataAPI_Point2D>(aCyrcFeature->data()->attribute(SketchPlugin_Arc::START_ID())); aFlyoutAttr->setValue(aStartAttr->pnt()); aFlyoutPnt = sketch()->to3D(aStartAttr->pnt()->x(), aStartAttr->pnt()->y()); } @@ -124,15 +140,13 @@ AISObjectPtr SketchPlugin_ConstraintRadius::getAISObject(AISObjectPtr thePreviou // Value std::shared_ptr aValueAttr = std::dynamic_pointer_cast< - ModelAPI_AttributeDouble>(aData->attribute(SketchPlugin_Constraint::VALUE())); - double aValue = aRadius; - if (aValueAttr && aValueAttr->isInitialized()) - aValue = aValueAttr->value(); - + ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE())); + if (aValueAttr->isInitialized()) + aRadius = aValueAttr->value(); AISObjectPtr anAIS = thePrevious; if (!anAIS) anAIS = AISObjectPtr(new GeomAPI_AISObject); - anAIS->createRadius(aCircle, aFlyoutPnt, aValue); + anAIS->createRadius(aCircle, aFlyoutPnt, aRadius); // Set color from preferences std::vector aRGB = Config_PropManager::color("Visualization", "radius_color", RADIUS_COLOR); @@ -177,3 +191,17 @@ void SketchPlugin_ConstraintRadius::move(double theDeltaX, double theDeltaY) aFlyoutAttr->setValue(aFlyout->x(), aFlyout->y()); } + +void SketchPlugin_ConstraintRadius::attributeChanged(const std::string& theID) { + if (theID == SketchPlugin_Constraint::ENTITY_A()) { + std::shared_ptr aValueAttr = std::dynamic_pointer_cast< + ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE())); + if (!aValueAttr->isInitialized()) { // only if it is not initialized, try to compute the current value + std::shared_ptr aCyrcFeature; + double aRadius = circleRadius(aCyrcFeature); + if (aRadius > 0) { // set as value the radius of updated reference to another circle + aValueAttr->setValue(aRadius); + } + } + } +} diff --git a/src/SketchPlugin/SketchPlugin_ConstraintRadius.h b/src/SketchPlugin/SketchPlugin_ConstraintRadius.h index 96e295e1b..7aa5ec6fb 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintRadius.h +++ b/src/SketchPlugin/SketchPlugin_ConstraintRadius.h @@ -49,8 +49,17 @@ class SketchPlugin_ConstraintRadius : public SketchPlugin_ConstraintBase /// \param theDeltaY the delta for Y coordinate is moved SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY); + /// Called on change of any argument-attribute of this object + /// \param theID identifier of changed attribute + SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + /// \brief Use plugin manager for features creation SketchPlugin_ConstraintRadius(); + +private: + /// Checks and gets the radius of referenced circle (or arc) otherwise returns -1. + /// \param theCircData the found referenced circle returned by this method + double circleRadius(std::shared_ptr& theCirc); }; #endif diff --git a/src/SketchPlugin/SketchPlugin_Line.cpp b/src/SketchPlugin/SketchPlugin_Line.cpp index 2cba979ce..83ee21659 100644 --- a/src/SketchPlugin/SketchPlugin_Line.cpp +++ b/src/SketchPlugin/SketchPlugin_Line.cpp @@ -99,19 +99,18 @@ bool SketchPlugin_Line::isFixed() { return data()->selection(EXTERNAL_ID())->context(); } -void SketchPlugin_Line::attributeChanged() { - static bool myIsUpdated = false; // to avoid infinitive cycle on attrubtes change - std::shared_ptr aSelection = data()->selection(EXTERNAL_ID())->value(); - // update arguments due to the selection value - if (aSelection && !aSelection->isNull() && aSelection->isEdge() && !myIsUpdated) { - myIsUpdated = true; - std::shared_ptr anEdge( new GeomAPI_Edge(aSelection)); - std::shared_ptr aStartAttr = - std::dynamic_pointer_cast(attribute(START_ID())); - aStartAttr->setValue(sketch()->to2D(anEdge->firstPoint())); - std::shared_ptr anEndAttr = - std::dynamic_pointer_cast(attribute(END_ID())); - anEndAttr->setValue(sketch()->to2D(anEdge->lastPoint())); - myIsUpdated = false; +void SketchPlugin_Line::attributeChanged(const std::string& theID) { + if (theID == EXTERNAL_ID()) { + std::shared_ptr aSelection = data()->selection(EXTERNAL_ID())->value(); + // update arguments due to the selection value + if (aSelection && !aSelection->isNull() && aSelection->isEdge()) { + std::shared_ptr anEdge( new GeomAPI_Edge(aSelection)); + std::shared_ptr aStartAttr = + std::dynamic_pointer_cast(attribute(START_ID())); + aStartAttr->setValue(sketch()->to2D(anEdge->firstPoint())); + std::shared_ptr anEndAttr = + std::dynamic_pointer_cast(attribute(END_ID())); + anEndAttr->setValue(sketch()->to2D(anEdge->lastPoint())); + } } } diff --git a/src/SketchPlugin/SketchPlugin_Line.h b/src/SketchPlugin/SketchPlugin_Line.h index a9e3e606c..850d17e4a 100644 --- a/src/SketchPlugin/SketchPlugin_Line.h +++ b/src/SketchPlugin/SketchPlugin_Line.h @@ -68,7 +68,7 @@ class SketchPlugin_Line : public SketchPlugin_Feature virtual double distanceToPoint(const std::shared_ptr& thePoint); /// Called on change of any argument-attribute of this object - SKETCHPLUGIN_EXPORT virtual void attributeChanged(); + SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); /// Use plugin manager for features creation SketchPlugin_Line(); diff --git a/src/SketchPlugin/SketchPlugin_Sketch.cpp b/src/SketchPlugin/SketchPlugin_Sketch.cpp index 4902305a8..1793ff16a 100644 --- a/src/SketchPlugin/SketchPlugin_Sketch.cpp +++ b/src/SketchPlugin/SketchPlugin_Sketch.cpp @@ -215,45 +215,45 @@ std::shared_ptr SketchPlugin_Sketch::plane() return std::shared_ptr(new GeomAPI_Pln(anOrigin->pnt(), aNorm->dir())); } -void addPlane(double theX, double theY, double theZ, - std::list >& theShapes) -{ - std::shared_ptr anOrigin(new GeomAPI_Pnt(0, 0, 0)); - std::shared_ptr aNormal(new GeomAPI_Dir(theX, theY, theZ)); - double aSize = Config_PropManager::integer("Sketch planes", "Size of planes", PLANE_SIZE); - std::shared_ptr aFace = GeomAlgoAPI_FaceBuilder::square(anOrigin, aNormal, - aSize); - theShapes.push_back(aFace); -} - -AISObjectPtr SketchPlugin_Sketch::getAISObject(AISObjectPtr thePrevious) -{ - std::shared_ptr aNorm = std::dynamic_pointer_cast( - data()->attribute(SketchPlugin_Sketch::NORM_ID())); - - if (!aNorm || (aNorm->x() == 0 && aNorm->y() == 0 && aNorm->z() == 0)) { - AISObjectPtr aAIS = thePrevious; - if (!aAIS) { - std::list > aFaces; - - addPlane(1, 0, 0, aFaces); // YZ plane - addPlane(0, 1, 0, aFaces); // XZ plane - addPlane(0, 0, 1, aFaces); // XY plane - std::shared_ptr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aFaces); - aAIS = AISObjectPtr(new GeomAPI_AISObject()); - aAIS->createShape(aCompound); - - std::vector aRGB = Config_PropManager::color("Sketch planes", "planes_color", - SKETCH_PLANE_COLOR); - aAIS->setColor(aRGB[0], aRGB[1], aRGB[2]); - - aAIS->setWidth(Config_PropManager::integer("Sketch planes", "planes_thickness", - SKETCH_WIDTH)); - } - return aAIS; - } - return AISObjectPtr(); -} +//void addPlane(double theX, double theY, double theZ, +// std::list >& theShapes) +//{ +// std::shared_ptr anOrigin(new GeomAPI_Pnt(0, 0, 0)); +// std::shared_ptr aNormal(new GeomAPI_Dir(theX, theY, theZ)); +// double aSize = Config_PropManager::integer("Sketch planes", "Size of planes", PLANE_SIZE); +// std::shared_ptr aFace = GeomAlgoAPI_FaceBuilder::square(anOrigin, aNormal, +// aSize); +// theShapes.push_back(aFace); +//} + +//AISObjectPtr SketchPlugin_Sketch::getAISObject(AISObjectPtr thePrevious) +//{ +// std::shared_ptr aNorm = std::dynamic_pointer_cast( +// data()->attribute(SketchPlugin_Sketch::NORM_ID())); +// +// if (!aNorm || (aNorm->x() == 0 && aNorm->y() == 0 && aNorm->z() == 0)) { +// AISObjectPtr aAIS = thePrevious; +// if (!aAIS) { +// std::list > aFaces; +// +// addPlane(1, 0, 0, aFaces); // YZ plane +// addPlane(0, 1, 0, aFaces); // XZ plane +// addPlane(0, 0, 1, aFaces); // XY plane +// std::shared_ptr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aFaces); +// aAIS = AISObjectPtr(new GeomAPI_AISObject()); +// aAIS->createShape(aCompound); +// +// std::vector aRGB = Config_PropManager::color("Sketch planes", "planes_color", +// SKETCH_PLANE_COLOR); +// aAIS->setColor(aRGB[0], aRGB[1], aRGB[2]); +// +// aAIS->setWidth(Config_PropManager::integer("Sketch planes", "planes_thickness", +// SKETCH_WIDTH)); +// } +// return aAIS; +// } +// return AISObjectPtr(); +//} void SketchPlugin_Sketch::erase() { @@ -271,66 +271,46 @@ void SketchPlugin_Sketch::erase() ModelAPI_CompositeFeature::erase(); } -void SketchPlugin_Sketch::attributeChanged() { - static bool kIsUpdated = false; // to avoid infinitive cycle on attrubtes change - static bool kIsAttrChanged = false; - std::shared_ptr aSelection = - data()->selection(SketchPlugin_Feature::EXTERNAL_ID())->value(); - if (aSelection && !kIsUpdated) { // update arguments due to the selection value - kIsUpdated = true; - // update the sketch plane - std::shared_ptr aPlane = GeomAlgoAPI_FaceBuilder::plane(aSelection); - if (aPlane) { - double anA, aB, aC, aD; - aPlane->coefficients(anA, aB, aC, aD); - - // calculate attributes of the sketch - std::shared_ptr aNormDir(new GeomAPI_Dir(anA, aB, aC)); - std::shared_ptr aCoords = aNormDir->xyz(); - std::shared_ptr aZero(new GeomAPI_XYZ(0, 0, 0)); - aCoords = aCoords->multiplied(-aD * aCoords->distance(aZero)); - std::shared_ptr anOrigPnt(new GeomAPI_Pnt(aCoords)); - // X axis is preferable to be dirX on the sketch - static const double tol = 1.e-7; - bool isX = fabs(anA - 1.0) < tol && fabs(aB) < tol && fabs(aC) < tol; - std::shared_ptr aTempDir( - isX ? new GeomAPI_Dir(0, 1, 0) : new GeomAPI_Dir(1, 0, 0)); - std::shared_ptr aYDir(new GeomAPI_Dir(aNormDir->cross(aTempDir))); - std::shared_ptr aXDir(new GeomAPI_Dir(aYDir->cross(aNormDir))); - - kIsAttrChanged = false; // track the attributes were really changed during the plane update - std::shared_ptr anOrigin = std::dynamic_pointer_cast - (data()->attribute(SketchPlugin_Sketch::ORIGIN_ID())); - anOrigin->setValue(anOrigPnt); - std::shared_ptr aNormal = std::dynamic_pointer_cast( - data()->attribute(SketchPlugin_Sketch::NORM_ID())); - aNormal->setValue(aNormDir); - std::shared_ptr aDirX = std::dynamic_pointer_cast( - data()->attribute(SketchPlugin_Sketch::DIRX_ID())); - aDirX->setValue(aXDir); - std::shared_ptr aDirY = std::dynamic_pointer_cast( - data()->attribute(SketchPlugin_Sketch::DIRY_ID())); - aDirY->setValue(aYDir); - std::shared_ptr aDir = aPlane->direction(); - - if (kIsAttrChanged) { - /* now it is in updater - // the plane was changed, so reexecute sub-elements to update shapes (located in new plane) - ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators(); - list aSubs = data()->reflist(SketchPlugin_Sketch::FEATURES_ID())->list(); - for(list::iterator aSubIt = aSubs.begin(); aSubIt != aSubs.end(); aSubIt++) { - std::shared_ptr aFeature = - std::dynamic_pointer_cast(*aSubIt); - if (aFeature && aFactory->validate(aFeature)) { - aFeature->execute(); - } - } - */ - kIsAttrChanged = false; +void SketchPlugin_Sketch::attributeChanged(const std::string& theID) { + if (theID == SketchPlugin_Feature::EXTERNAL_ID()) { + std::shared_ptr aSelection = + data()->selection(SketchPlugin_Feature::EXTERNAL_ID())->value(); + if (aSelection) { // update arguments due to the selection value + // update the sketch plane + std::shared_ptr aPlane = GeomAlgoAPI_FaceBuilder::plane(aSelection); + if (aPlane) { + double anA, aB, aC, aD; + aPlane->coefficients(anA, aB, aC, aD); + + // calculate attributes of the sketch + std::shared_ptr aNormDir(new GeomAPI_Dir(anA, aB, aC)); + std::shared_ptr aCoords = aNormDir->xyz(); + std::shared_ptr aZero(new GeomAPI_XYZ(0, 0, 0)); + aCoords = aCoords->multiplied(-aD * aCoords->distance(aZero)); + std::shared_ptr anOrigPnt(new GeomAPI_Pnt(aCoords)); + // X axis is preferable to be dirX on the sketch + static const double tol = 1.e-7; + bool isX = fabs(anA - 1.0) < tol && fabs(aB) < tol && fabs(aC) < tol; + std::shared_ptr aTempDir( + isX ? new GeomAPI_Dir(0, 1, 0) : new GeomAPI_Dir(1, 0, 0)); + std::shared_ptr aYDir(new GeomAPI_Dir(aNormDir->cross(aTempDir))); + std::shared_ptr aXDir(new GeomAPI_Dir(aYDir->cross(aNormDir))); + + // update position of the sketch + std::shared_ptr anOrigin = std::dynamic_pointer_cast + (data()->attribute(SketchPlugin_Sketch::ORIGIN_ID())); + anOrigin->setValue(anOrigPnt); + std::shared_ptr aNormal = std::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Sketch::NORM_ID())); + aNormal->setValue(aNormDir); + std::shared_ptr aDirX = std::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Sketch::DIRX_ID())); + aDirX->setValue(aXDir); + std::shared_ptr aDirY = std::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Sketch::DIRY_ID())); + aDirY->setValue(aYDir); + std::shared_ptr aDir = aPlane->direction(); } } - kIsUpdated = false; - } else if (kIsUpdated) { // other attributes are updated during the selection comupation - kIsAttrChanged = true; } } diff --git a/src/SketchPlugin/SketchPlugin_Sketch.h b/src/SketchPlugin/SketchPlugin_Sketch.h index c4802d483..0b4abaa44 100644 --- a/src/SketchPlugin/SketchPlugin_Sketch.h +++ b/src/SketchPlugin/SketchPlugin_Sketch.h @@ -25,7 +25,7 @@ * \ingroup DataModel * \brief Feature for creation of the new part in PartSet. */ -class SketchPlugin_Sketch : public ModelAPI_CompositeFeature, public GeomAPI_IPresentable +class SketchPlugin_Sketch : public ModelAPI_CompositeFeature//, public GeomAPI_IPresentable { public: /// Sketch feature kind @@ -109,7 +109,7 @@ class SketchPlugin_Sketch : public ModelAPI_CompositeFeature, public GeomAPI_IPr /// Returns the basis plane for the sketch std::shared_ptr plane(); - virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious); + //virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious); /// removes also all sub-sketch elements SKETCHPLUGIN_EXPORT virtual void erase(); @@ -135,7 +135,7 @@ class SketchPlugin_Sketch : public ModelAPI_CompositeFeature, public GeomAPI_IPr /// Returns the point projected into the sketch plane std::shared_ptr to2D(const std::shared_ptr& thePnt); - SKETCHPLUGIN_EXPORT virtual void attributeChanged(); + SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); protected: /// Creates a plane and append it to the list /// \param theX the X normal value diff --git a/src/SketchPlugin/Test/TestConstraintRadius.py b/src/SketchPlugin/Test/TestConstraintRadius.py index afe60ba4f..cc71a412f 100644 --- a/src/SketchPlugin/Test/TestConstraintRadius.py +++ b/src/SketchPlugin/Test/TestConstraintRadius.py @@ -107,12 +107,13 @@ assert (anArcPrevEndPointX == 50.) assert (anArcPrevEndPointY == 0.) # Move one point of the arc aSession.startOperation() -anArcStartPoint.setValue(0., 60) +anArcStartPoint.setValue(0, 60) aSession.finishOperation() assert (anArcCentr.x() == 10.) assert (anArcCentr.y() == 10.) -assert (anArcEndPoint.x() != anArcPrevEndPointX) -assert (anArcEndPoint.y() != anArcPrevEndPointY) +# MPV: it just projects back to the circle the moved start point +#assert (anArcEndPoint.x() != anArcPrevEndPointX) +#assert (anArcEndPoint.y() != anArcPrevEndPointY) #========================================================================= # 4. Move the centr or the point of the arc # 5. Check radius is the same diff --git a/src/SketchPlugin/Test/TestSketchArcCircle.py b/src/SketchPlugin/Test/TestSketchArcCircle.py index 8ce7a3186..c59725e21 100644 --- a/src/SketchPlugin/Test/TestSketchArcCircle.py +++ b/src/SketchPlugin/Test/TestSketchArcCircle.py @@ -86,31 +86,33 @@ assert (anArcEndPoint.y() == 0.0) # 1. Move whole arc # 2. Change the start point #========================================================================= -aSession.startOperation() -deltaX, deltaY = 5., 10. -anArcCentr.setValue(anArcCentr.x() + deltaX, anArcCentr.y() + deltaY) -anArcStartPoint.setValue( - anArcStartPoint.x() + deltaX, anArcStartPoint.y() + deltaY) -anArcEndPoint.setValue(anArcEndPoint.x() + deltaX, anArcEndPoint.y() + deltaY) -aSession.finishOperation() -assert (anArcCentr.x() == 15) -assert (anArcCentr.y() == 20) -assert (anArcStartPoint.x() == 5) -assert (anArcStartPoint.y() == 60) -assert (anArcEndPoint.x() == 55) -assert (anArcEndPoint.y() == 10) -# Change the start point -aSession.startOperation() -anArcStartPoint.setValue(anArcStartPoint.x() + deltaX, anArcStartPoint.y()) -aPrevEndPointX = anArcEndPoint.x() -aPrevEndPointY = anArcEndPoint.y() -aSession.finishOperation() -assert (anArcCentr.x() == 15) -assert (anArcCentr.y() == 20) -assert (anArcStartPoint.x() == 10) -assert (anArcStartPoint.y() == 60) -assert (anArcEndPoint.x() != aPrevEndPointX) -assert (anArcEndPoint.y() != aPrevEndPointY) + +# MPV: movement now is done little bit in different way, just move points causes changing them +# back t okeep the radius unchanged (projection back to the initial circle) +#aSession.startOperation() +#deltaX, deltaY = 5., 10. +#anArcCentr.setValue(anArcCentr.x() + deltaX, anArcCentr.y() + deltaY) +#anArcStartPoint.setValue( +# anArcStartPoint.x() + deltaX, anArcStartPoint.y() + deltaY) +#anArcEndPoint.setValue(anArcEndPoint.x() + deltaX, anArcEndPoint.y() + deltaY) +#aSession.finishOperation() +#assert (anArcCentr.y() == 20) +#assert (anArcStartPoint.x() == 5) +#assert (anArcStartPoint.y() == 60) +#assert (anArcEndPoint.x() == 55) +#assert (anArcEndPoint.y() == 10) +## Change the start point +#aSession.startOperation() +#anArcStartPoint.setValue(anArcStartPoint.x() + deltaX, anArcStartPoint.y()) +#aPrevEndPointX = anArcEndPoint.x() +#aPrevEndPointY = anArcEndPoint.y() +#aSession.finishOperation() +#assert (anArcCentr.x() == 15) +#assert (anArcCentr.y() == 20) +#assert (anArcStartPoint.x() == 10) +#assert (anArcStartPoint.y() == 60) +#assert (anArcEndPoint.x() != aPrevEndPointX) +#assert (anArcEndPoint.y() != aPrevEndPointY) #========================================================================= # Check results of the Arc #========================================================================= diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 82ba507be..d83e41b6b 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -6,101 +6,108 @@ - + - - + + - + - - - + + + - + - + - + - + - - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + - + - - - - - + + + + + diff --git a/src/SketchSolver/SketchSolver_ConstraintManager.cpp b/src/SketchSolver/SketchSolver_ConstraintManager.cpp index 24c6572c4..a69eb95bc 100644 --- a/src/SketchSolver/SketchSolver_ConstraintManager.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintManager.cpp @@ -107,7 +107,7 @@ void SketchSolver_ConstraintManager::processEvent( std::dynamic_pointer_cast(*aFeatIter); if (!aFeature) continue; - changeConstraintOrEntity(aFeature); + changeConstraintOrEntity(aFeature); } } @@ -169,7 +169,7 @@ bool SketchSolver_ConstraintManager::changeWorkplane( if (!isUpdated) { SketchSolver_ConstraintGroup* aNewGroup = new SketchSolver_ConstraintGroup(theSketch); // Verify that the group is created successfully - if (!aNewGroup->isBaseWorkplane(theSketch)) { + if (!aNewGroup->isBaseWorkplane(theSketch) || !aNewGroup->isWorkplaneValid()) { delete aNewGroup; return false; } @@ -374,14 +374,24 @@ void SketchSolver_ConstraintManager::resolveConstraints() { myIsComputed = true; bool needToUpdate = false; + static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + // to avoid redisplay of each segment on update by solver one by one in the viewer + bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent); + if (isUpdateFlushed) { + Events_Loop::loop()->setFlushed(anUpdateEvent, false); + } + std::vector::iterator aGroupIter; for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) if ((*aGroupIter)->resolveConstraints()) needToUpdate = true; - // Features may be updated => send events + // Features may be updated => now send events, btu for all changed at once + if (isUpdateFlushed) { + Events_Loop::loop()->setFlushed(anUpdateEvent, true); + } if (needToUpdate) - Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + Events_Loop::loop()->flush(anUpdateEvent); myIsComputed = false; } diff --git a/src/XGUI/NewGeom.xml b/src/XGUI/NewGeom.xml index 1b1bd2a0b..af912ddf2 100644 --- a/src/XGUI/NewGeom.xml +++ b/src/XGUI/NewGeom.xml @@ -10,4 +10,9 @@ +
+ + +
+ diff --git a/src/XGUI/XGUI_ContextMenuMgr.cpp b/src/XGUI/XGUI_ContextMenuMgr.cpp index 73808b9af..27e596a48 100644 --- a/src/XGUI/XGUI_ContextMenuMgr.cpp +++ b/src/XGUI/XGUI_ContextMenuMgr.cpp @@ -114,7 +114,7 @@ QMenu* XGUI_ContextMenuMgr::objectBrowserMenu() const { QMenu* aMenu = new QMenu(); XGUI_SelectionMgr* aSelMgr = myWorkshop->selector(); - QList aObjects = aSelMgr->selection()->selectedObjects(); + QObjectPtrList aObjects = aSelMgr->selection()->selectedObjects(); int aSelected = aObjects.size(); if (aSelected > 0) { SessionPtr aMgr = ModelAPI_Session::get(); @@ -197,7 +197,7 @@ QMenu* XGUI_ContextMenuMgr::viewerMenu() const void XGUI_ContextMenuMgr::addViewerItems(QMenu* theMenu) const { XGUI_SelectionMgr* aSelMgr = myWorkshop->selector(); - QList aObjects = aSelMgr->selection()->selectedObjects(); + QObjectPtrList aObjects = aSelMgr->selection()->selectedObjects(); if (aObjects.size() > 0) { //if (aObjects.size() == 1) // theMenu->addAction(action("EDIT_CMD")); diff --git a/src/XGUI/XGUI_Displayer.cpp b/src/XGUI/XGUI_Displayer.cpp index 0d0f6e384..427d83fbb 100644 --- a/src/XGUI/XGUI_Displayer.cpp +++ b/src/XGUI/XGUI_Displayer.cpp @@ -43,7 +43,7 @@ XGUI_Displayer::~XGUI_Displayer() bool XGUI_Displayer::isVisible(ObjectPtr theObject) const { - return myResult2AISObjectMap.find(theObject) != myResult2AISObjectMap.end(); + return myResult2AISObjectMap.contains(theObject); } void XGUI_Displayer::display(ObjectPtr theObject, bool isUpdateViewer) @@ -115,7 +115,7 @@ void XGUI_Displayer::erase(ObjectPtr theObject, const bool isUpdateViewer) aContext->Remove(anAIS, isUpdateViewer); } } - myResult2AISObjectMap.erase(theObject); + myResult2AISObjectMap.remove(theObject); } void XGUI_Displayer::redisplay(ObjectPtr theObject, bool isUpdateViewer) @@ -160,6 +160,12 @@ void XGUI_Displayer::deactivate(ObjectPtr theObject) } } +void XGUI_Displayer::activate(ObjectPtr theFeature) +{ + QIntList aModes; + activate(theFeature, aModes); +} + void XGUI_Displayer::activate(ObjectPtr theObject, const QIntList& theModes) { if (isVisible(theObject)) { @@ -189,7 +195,7 @@ bool XGUI_Displayer::isActive(ObjectPtr theObject) const if (!isVisible(theObject)) return false; - AISObjectPtr anObj = myResult2AISObjectMap.at(theObject); + AISObjectPtr anObj = myResult2AISObjectMap[theObject]; Handle(AIS_InteractiveObject) anAIS = anObj->impl(); TColStd_ListOfInteger aModes; @@ -197,7 +203,7 @@ bool XGUI_Displayer::isActive(ObjectPtr theObject) const return aModes.Extent() > 0; } -void XGUI_Displayer::stopSelection(const QList& theResults, const bool isStop, +void XGUI_Displayer::stopSelection(const QObjectPtrList& theResults, const bool isStop, const bool isUpdateViewer) { Handle(AIS_InteractiveContext) aContext = AISContext(); @@ -205,7 +211,7 @@ void XGUI_Displayer::stopSelection(const QList& theResults, const boo return; Handle(AIS_Shape) anAIS; - QList::const_iterator anIt = theResults.begin(), aLast = theResults.end(); + QObjectPtrList::const_iterator anIt = theResults.begin(), aLast = theResults.end(); ObjectPtr aFeature; for (; anIt != aLast; anIt++) { aFeature = *anIt; @@ -233,23 +239,32 @@ void XGUI_Displayer::stopSelection(const QList& theResults, const boo updateViewer(); } -void XGUI_Displayer::setSelected(const QList& theResults, const bool isUpdateViewer) +void XGUI_Displayer::setSelected(const QObjectPtrList& theResults, const bool isUpdateViewer) { Handle(AIS_InteractiveContext) aContext = AISContext(); - // we need to unhighligth objects manually in the current local context - // in couple with the selection clear (TODO) - Handle(AIS_LocalContext) aLocalContext = aContext->LocalContext(); - if (!aLocalContext.IsNull()) - aLocalContext->UnhilightLastDetected(myWorkshop->viewer()->activeView()); - - aContext->ClearSelected(); - foreach(ObjectPtr aResult, theResults) - { - if (isVisible(aResult)) { - AISObjectPtr anObj = myResult2AISObjectMap[aResult]; - Handle(AIS_InteractiveObject) anAIS = anObj->impl(); - if (!anAIS.IsNull()) - aContext->SetSelected(anAIS, false); + if (aContext.IsNull()) + return; + if (aContext->HasOpenedContext()) { + aContext->UnhilightSelected(); + aContext->ClearSelected(); + foreach(ObjectPtr aResult, theResults) { + if (isVisible(aResult)) { + AISObjectPtr anObj = myResult2AISObjectMap[aResult]; + Handle(AIS_InteractiveObject) anAIS = anObj->impl(); + if (!anAIS.IsNull()) + aContext->SetSelected(anAIS, false); + } + } + } else { + aContext->UnhilightCurrents(); + aContext->ClearCurrents(); + foreach(ObjectPtr aResult, theResults) { + if (isVisible(aResult)) { + AISObjectPtr anObj = myResult2AISObjectMap[aResult]; + Handle(AIS_InteractiveObject) anAIS = anObj->impl(); + if (!anAIS.IsNull()) + aContext->SetCurrentObject(anAIS, false); + } } } if (isUpdateViewer) @@ -268,17 +283,15 @@ void XGUI_Displayer::clearSelected() void XGUI_Displayer::eraseAll(const bool isUpdateViewer) { - Handle(AIS_InteractiveContext) ic = AISContext(); - if (ic.IsNull()) + Handle(AIS_InteractiveContext) aContext = AISContext(); + if (aContext.IsNull()) return; - ResultToAISMap::iterator aIt; - for (aIt = myResult2AISObjectMap.begin(); aIt != myResult2AISObjectMap.end(); aIt++) { + foreach (AISObjectPtr aAISObj, myResult2AISObjectMap) { // erase an object - AISObjectPtr aAISObj = (*aIt).second; Handle(AIS_InteractiveObject) anIO = aAISObj->impl(); if (!anIO.IsNull()) - ic->Remove(anIO, false); + aContext->Remove(anIO, false); } myResult2AISObjectMap.clear(); if (isUpdateViewer) @@ -291,25 +304,21 @@ void XGUI_Displayer::eraseDeletedResults(const bool isUpdateViewer) if (aContext.IsNull()) return; - ResultToAISMap::const_iterator aFIt = myResult2AISObjectMap.begin(), aFLast = - myResult2AISObjectMap.end(); - std::list aRemoved; - for (; aFIt != aFLast; aFIt++) { - ObjectPtr aFeature = (*aFIt).first; + QObjectPtrList aRemoved; + foreach (ObjectPtr aFeature, myResult2AISObjectMap.keys()) { if (!aFeature || !aFeature->data() || !aFeature->data()->isValid()) { - AISObjectPtr anObj = (*aFIt).second; + AISObjectPtr anObj = myResult2AISObjectMap[aFeature]; if (!anObj) continue; Handle(AIS_InteractiveObject) anAIS = anObj->impl(); if (!anAIS.IsNull()) { aContext->Remove(anAIS, false); - aRemoved.push_back(aFeature); + aRemoved.append(aFeature); } } } - std::list::const_iterator anIt = aRemoved.begin(), aLast = aRemoved.end(); - for (; anIt != aLast; anIt++) { - myResult2AISObjectMap.erase(myResult2AISObjectMap.find(*anIt)); + foreach(ObjectPtr aObj, aRemoved) { + myResult2AISObjectMap.remove(aObj); } if (isUpdateViewer) @@ -323,27 +332,91 @@ void XGUI_Displayer::openLocalContext() return; // Open local context if there is no one if (!aContext->HasOpenedContext()) { - aContext->ClearCurrents(false); - //aContext->OpenLocalContext(false/*use displayed objects*/, true/*allow shape decomposition*/); + // Preserve selected objects + //AIS_ListOfInteractive aAisList; + //for (aContext->InitCurrent(); aContext->MoreCurrent(); aContext->NextCurrent()) + // aAisList.Append(aContext->Current()); + + // get the filters from the global context and append them to the local context + // a list of filters in the global context is not cleared and should be cleared here + SelectMgr_ListOfFilter aFilters; + aFilters.Assign(aContext->Filters()); + // it is important to remove the filters in the global context, because there is a code + // in the closeLocalContex, which restore the global context filters + aContext->RemoveFilters(); + + aContext->ClearCurrents(); aContext->OpenLocalContext(); aContext->NotUseDisplayedObjects(); myUseExternalObjects = false; myActiveSelectionModes.clear(); + + SelectMgr_ListIteratorOfListOfFilter aIt(aFilters); + for (;aIt.More(); aIt.Next()) { + aContext->AddFilter(aIt.Value()); + } + // Restore selection + //AIS_ListIteratorOfListOfInteractive aIt2(aAisList); + //for(; aIt2.More(); aIt2.Next()) { + // aContext->SetSelected(aIt2.Value(), false); + //} } } void XGUI_Displayer::closeLocalContexts(const bool isUpdateViewer) { - AISContext()->ClearSelected(false); - closeAllContexts(true); + Handle(AIS_InteractiveContext) aContext = AISContext(); + if ( (!aContext.IsNull()) && (aContext->HasOpenedContext()) ) { + // Preserve selected objects + //AIS_ListOfInteractive aAisList; + //for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected()) + // aAisList.Append(aContext->SelectedInteractive()); + + // get the filters from the local context and append them to the global context + // a list of filters in the local context is cleared + SelectMgr_ListOfFilter aFilters; + aFilters.Assign(aContext->Filters()); + + aContext->ClearSelected(); + aContext->CloseAllContexts(false); + + // Redisplay all object if they were displayed in localContext + Handle(AIS_InteractiveObject) aAISIO; + foreach (AISObjectPtr aAIS, myResult2AISObjectMap) { + aAISIO = aAIS->impl(); + if (aContext->DisplayStatus(aAISIO) != AIS_DS_Displayed) { + aContext->Display(aAISIO, false); + aContext->SetDisplayMode(aAISIO, Shading, false); + } + } + + // Append the filters from the local selection in the global selection context + SelectMgr_ListIteratorOfListOfFilter aIt(aFilters); + for (;aIt.More(); aIt.Next()) { + Handle(SelectMgr_Filter) aFilter = aIt.Value(); + aContext->AddFilter(aFilter); + } + + if (isUpdateViewer) + updateViewer(); + myUseExternalObjects = false; + myActiveSelectionModes.clear(); + + // Restore selection + //AIS_ListIteratorOfListOfInteractive aIt2(aAisList); + //for(; aIt2.More(); aIt2.Next()) { + // if (aContext->IsDisplayed(aIt2.Value())) + // aContext->SetCurrentObject(aIt2.Value(), false); + //} + } } AISObjectPtr XGUI_Displayer::getAISObject(ObjectPtr theObject) const { AISObjectPtr anIO; - if (myResult2AISObjectMap.find(theObject) != myResult2AISObjectMap.end()) - anIO = (myResult2AISObjectMap.find(theObject))->second; + if (myResult2AISObjectMap.contains(theObject)) + anIO = myResult2AISObjectMap[theObject]; return anIO; } @@ -356,37 +429,20 @@ ObjectPtr XGUI_Displayer::getObject(const AISObjectPtr& theIO) const ObjectPtr XGUI_Displayer::getObject(const Handle(AIS_InteractiveObject)& theIO) const { ObjectPtr aFeature; - ResultToAISMap::const_iterator aFIt = myResult2AISObjectMap.begin(), aFLast = - myResult2AISObjectMap.end(); - for (; aFIt != aFLast && !aFeature; aFIt++) { - AISObjectPtr anObj = (*aFIt).second; - if (!anObj) - continue; - Handle(AIS_InteractiveObject) anAIS = anObj->impl(); - if (anAIS != theIO) - continue; - aFeature = (*aFIt).first; + foreach (ObjectPtr anObj, myResult2AISObjectMap.keys()) { + AISObjectPtr aAIS = myResult2AISObjectMap[anObj]; + Handle(AIS_InteractiveObject) anAIS = aAIS->impl(); + if (anAIS == theIO) + return anObj; } return aFeature; } -void XGUI_Displayer::closeAllContexts(const bool isUpdateViewer) -{ - Handle(AIS_InteractiveContext) ic = AISContext(); - if (!ic.IsNull()) { - ic->CloseAllContexts(false); - if (isUpdateViewer) - updateViewer(); - myUseExternalObjects = false; - myActiveSelectionModes.clear(); - } -} - void XGUI_Displayer::updateViewer() { - Handle(AIS_InteractiveContext) ic = AISContext(); - if (!ic.IsNull()) - ic->UpdateCurrentViewer(); + Handle(AIS_InteractiveContext) aContext = AISContext(); + if (!aContext.IsNull()) + aContext->UpdateCurrentViewer(); } Handle(AIS_InteractiveContext) XGUI_Displayer::AISContext() const @@ -394,6 +450,16 @@ Handle(AIS_InteractiveContext) XGUI_Displayer::AISContext() const return myWorkshop->viewer()->AISContext(); } +Handle(SelectMgr_AndFilter) XGUI_Displayer::GetFilter() +{ + Handle(AIS_InteractiveContext) aContext = AISContext(); + if (myAndFilter.IsNull() && !aContext.IsNull()) { + myAndFilter = new SelectMgr_AndFilter(); + aContext->AddFilter(myAndFilter); + } + return myAndFilter; +} + void XGUI_Displayer::displayAIS(AISObjectPtr theAIS, bool isUpdate) { Handle(AIS_InteractiveContext) aContext = AISContext(); @@ -423,7 +489,7 @@ void XGUI_Displayer::eraseAIS(AISObjectPtr theAIS, const bool isUpdate) } } -void XGUI_Displayer::activateObjectsOutOfContext(const QIntList& theModes) +void XGUI_Displayer::activateObjects(const QIntList& theModes) { Handle(AIS_InteractiveContext) aContext = AISContext(); // Open local context if there is no one @@ -448,10 +514,18 @@ void XGUI_Displayer::activateObjectsOutOfContext(const QIntList& theModes) } } - ResultToAISMap::iterator aIt; + //Activate all displayed objects with the module modes + //AIS_ListOfInteractive aPrsList; + //aContext->DisplayedObjects(aPrsList, true); + + //AIS_ListIteratorOfListOfInteractive aLIt(aPrsList); Handle(AIS_InteractiveObject) anAISIO; - for (aIt = myResult2AISObjectMap.begin(); aIt != myResult2AISObjectMap.end(); aIt++) { - anAISIO = (*aIt).second->impl(); + for(aLIt.Initialize(aPrsList); aLIt.More(); aLIt.Next()){ + anAISIO = aLIt.Value(); + aTrihedron = Handle(AIS_Trihedron)::DownCast(anAISIO); + if (!aTrihedron.IsNull()) + continue; + aContext->Load(anAISIO, -1, true); if (theModes.size() == 0) aContext->Activate(anAISIO); @@ -464,7 +538,7 @@ void XGUI_Displayer::activateObjectsOutOfContext(const QIntList& theModes) } -void XGUI_Displayer::deactivateObjectsOutOfContext() +void XGUI_Displayer::deactivateObjects() { Handle(AIS_InteractiveContext) aContext = AISContext(); // Open local context if there is no one @@ -492,28 +566,6 @@ void XGUI_Displayer::setDisplayMode(ObjectPtr theObject, DisplayMode theMode, bo aContext->SetDisplayMode(aAISIO, theMode, toUpdate); } -void XGUI_Displayer::setSelectionModes(const QIntList& theModes) -{ - Handle(AIS_InteractiveContext) aContext = AISContext(); - if (aContext.IsNull()) - return; - if (!aContext->HasOpenedContext()) - return; - // Clear previous mode - const TColStd_ListOfInteger& aModes = aContext->ActivatedStandardModes(); - if (!aModes.IsEmpty()) { - TColStd_ListOfInteger aMModes; - aMModes.Assign(aModes); - TColStd_ListIteratorOfListOfInteger it(aMModes); - for(; it.More(); it.Next()) { - aContext->DeactivateStandardMode((TopAbs_ShapeEnum)it.Value()); - } - } - foreach(int aMode, theModes) { - aContext->ActivateStandardMode((TopAbs_ShapeEnum)aMode); - } -} - XGUI_Displayer::DisplayMode XGUI_Displayer::displayMode(ObjectPtr theObject) const { Handle(AIS_InteractiveContext) aContext = AISContext(); @@ -539,7 +591,7 @@ void XGUI_Displayer::addSelectionFilter(const Handle(SelectMgr_Filter)& theFilte if (theFilter.Access() == aIt.Value().Access()) return; } - aContext->AddFilter(theFilter); + GetFilter()->Add(theFilter); } void XGUI_Displayer::removeSelectionFilter(const Handle(SelectMgr_Filter)& theFilter) @@ -547,5 +599,27 @@ void XGUI_Displayer::removeSelectionFilter(const Handle(SelectMgr_Filter)& theFi Handle(AIS_InteractiveContext) aContext = AISContext(); if (aContext.IsNull()) return; - aContext->RemoveFilter(theFilter); + GetFilter()->Remove(theFilter); +} + +void XGUI_Displayer::removeFilters() +{ + Handle(AIS_InteractiveContext) aContext = AISContext(); + if (aContext.IsNull()) + return; + GetFilter()->Clear(); +} + +void XGUI_Displayer::showOnly(const QObjectPtrList& theList) +{ + QObjectPtrList aDispList = myResult2AISObjectMap.keys(); + foreach(ObjectPtr aObj, aDispList) { + if (!theList.contains(aObj)) + erase(aObj, false); + } + foreach(ObjectPtr aObj, theList) { + if (!isVisible(aObj)) + display(aObj, false); + } + updateViewer(); } diff --git a/src/XGUI/XGUI_Displayer.h b/src/XGUI/XGUI_Displayer.h index 5d770e85e..f0227a67b 100644 --- a/src/XGUI/XGUI_Displayer.h +++ b/src/XGUI/XGUI_Displayer.h @@ -7,11 +7,7 @@ #include "XGUI.h" -#include -#include - #include - #include #include #include @@ -22,9 +18,10 @@ #include #include -#include -#include -#include +#include + +#include +#include class XGUI_Viewer; class ModelAPI_Feature; @@ -62,7 +59,7 @@ class XGUI_EXPORT XGUI_Displayer /// \param theFeatures a list of features to be disabled /// \param theToStop the boolean state whether it it stopped or non stopped /// \param isUpdateViewer the parameter whether the viewer should be update immediatelly - void stopSelection(const QList& theFeatures, const bool isStop, + void stopSelection(const QObjectPtrList& theFeatures, const bool isStop, const bool isUpdateViewer); /** @@ -70,7 +67,7 @@ class XGUI_EXPORT XGUI_Displayer * \param theFeatures a list of features to be selected * isUpdateViewer the parameter whether the viewer should be update immediatelly */ - void setSelected(const QList& theFeatures, bool isUpdateViewer = true); + void setSelected(const QObjectPtrList& theFeatures, bool isUpdateViewer = true); /// Un select all objects @@ -99,17 +96,12 @@ class XGUI_EXPORT XGUI_Displayer /// \param isUpdateViewer the parameter whether the viewer should be update immediatelly void closeLocalContexts(const bool isUpdateViewer = true); - /* - * Set modes of selections. Selection mode has to be defined by TopAbs_ShapeEnum. - * It doesn't manages a local context - * \param theModes - list of selection modes. If the list is empty then all selectoin modes will be cleared. - */ - void setSelectionModes(const QIntList& theModes); - void addSelectionFilter(const Handle(SelectMgr_Filter)& theFilter); void removeSelectionFilter(const Handle(SelectMgr_Filter)& theFilter); + void removeFilters(); + /// Updates the viewer void updateViewer(); @@ -131,34 +123,41 @@ class XGUI_EXPORT XGUI_Displayer /// \param theModes - modes on which it has to be activated (can be empty) void activate(ObjectPtr theFeature, const QIntList& theModes); + /// Activates the given object with default modes + void activate(ObjectPtr theFeature); + /// Returns true if the given object can be selected bool isActive(ObjectPtr theObject) const; /// Activates in local context displayed outside of the context. /// \param theModes - modes on which it has to be activated (can be empty) - void activateObjectsOutOfContext(const QIntList& theModes); + void activateObjects(const QIntList& theModes); /// Activates in local context displayed outside of the context. - void deactivateObjectsOutOfContext(); + void deactivateObjects(); /// Sets display mode for the given object if this object is displayed void setDisplayMode(ObjectPtr theObject, DisplayMode theMode, bool toUpdate = true); /// Returns current display mode for the given object. - /// If object is not displayed then returns NoMode. + /// If object is not dis played then returns NoMode. DisplayMode displayMode(ObjectPtr theObject) const; + /// Displays only objects listed in the list + void showOnly(const QObjectPtrList& theList); + + /// Returns number of displayed objects int objectsCount() const { return myResult2AISObjectMap.size(); } protected: - /// Deactivate local selection - /// \param isUpdateViewer the state wether the viewer should be updated immediatelly - void closeAllContexts(const bool isUpdateViewer); - /// Returns currently installed AIS_InteractiveContext Handle(AIS_InteractiveContext) AISContext() const; + /// Returns the viewer context top filter. If there is no a filter, it is created and set into + /// The context should have only this filter inside. Other filters should be add to the filter + Handle(SelectMgr_AndFilter) GetFilter(); + /// Display the feature and a shape. This shape would be associated to the given feature /// \param theFeature a feature instance /// \param theAIS AIS presentation @@ -185,7 +184,9 @@ class XGUI_EXPORT XGUI_Displayer protected: XGUI_Workshop* myWorkshop; - typedef std::map ResultToAISMap; + Handle(SelectMgr_AndFilter) myAndFilter; + + typedef QMap ResultToAISMap; ResultToAISMap myResult2AISObjectMap; // A flag of initialization of external objects selection diff --git a/src/XGUI/XGUI_DocumentDataModel.cpp b/src/XGUI/XGUI_DocumentDataModel.cpp index 1ed348e1c..fb6a66a30 100644 --- a/src/XGUI/XGUI_DocumentDataModel.cpp +++ b/src/XGUI/XGUI_DocumentDataModel.cpp @@ -214,7 +214,7 @@ QVariant XGUI_DocumentDataModel::data(const QModelIndex& theIndex, int theRole) else return QVariant(); case Qt::DecorationRole: - return QIcon(XGUI_Workshop::featureIcon(aFeature->getKind())); + return XGUI_Workshop::featureIcon(aFeature); case Qt::ToolTipRole: return tr("Feature object"); case Qt::ForegroundRole: diff --git a/src/XGUI/XGUI_IPrefMgr.h b/src/XGUI/XGUI_IPrefMgr.h index af0752d6f..9530a6cab 100644 --- a/src/XGUI/XGUI_IPrefMgr.h +++ b/src/XGUI/XGUI_IPrefMgr.h @@ -17,6 +17,7 @@ class XGUI_IPrefMgr { public: + /** * Add preference item into preference dialog box * \param theLbl - label of the item @@ -30,8 +31,12 @@ public: SUIT_PreferenceMgr::PrefItemType theType, const QString& theSection, const QString& theName ) = 0; + virtual void setItemProperty(const QString& thePropName, + const QVariant& theValue, + const int theId = -1) = 0; + /// Returns incapsulated preference manager virtual SUIT_PreferenceMgr* prefMgr() const = 0; }; -#endif \ No newline at end of file +#endif diff --git a/src/XGUI/XGUI_ModuleConnector.cpp b/src/XGUI/XGUI_ModuleConnector.cpp index 45f2d0ed7..e45a52cce 100644 --- a/src/XGUI/XGUI_ModuleConnector.cpp +++ b/src/XGUI/XGUI_ModuleConnector.cpp @@ -23,16 +23,22 @@ XGUI_ModuleConnector::XGUI_ModuleConnector(XGUI_Workshop* theWorkshop) XGUI_OperationMgr* anOperationMgr = myWorkshop->operationMgr(); connect(anOperationMgr, SIGNAL(operationStarted(ModuleBase_Operation*)), - this, SIGNAL(operationStarted(ModuleBase_Operation*))); + SIGNAL(operationStarted(ModuleBase_Operation*))); connect(anOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)), - this, SIGNAL(operationStopped(ModuleBase_Operation*))); - - myDocumentShapeFilter = new ModuleBase_ShapeDocumentFilter(this); + SIGNAL(operationStopped(ModuleBase_Operation*))); + connect(anOperationMgr, SIGNAL(operationResumed(ModuleBase_Operation*)), + SIGNAL(operationResumed(ModuleBase_Operation*))); + connect(anOperationMgr, SIGNAL(operationComitted(ModuleBase_Operation*)), + SIGNAL(operationComitted(ModuleBase_Operation*))); + connect(anOperationMgr, SIGNAL(operationAborted(ModuleBase_Operation*)), + SIGNAL(operationAborted(ModuleBase_Operation*))); + + //myDocumentShapeFilter = new ModuleBase_ShapeDocumentFilter(this); } XGUI_ModuleConnector::~XGUI_ModuleConnector() { - myDocumentShapeFilter.Nullify(); + //myDocumentShapeFilter.Nullify(); } ModuleBase_ISelection* XGUI_ModuleConnector::selection() const @@ -67,16 +73,16 @@ void XGUI_ModuleConnector::activateSubShapesSelection(const QIntList& theTypes) foreach(int aType, theTypes) { aModes.append(AIS_Shape::SelectionMode((TopAbs_ShapeEnum)aType)); } - aDisp->activateObjectsOutOfContext(aModes); + aDisp->activateObjects(aModes); //TODO: We have to open Local context because at neutral point filters don't work (bug 25340) - aDisp->addSelectionFilter(myDocumentShapeFilter); + //aDisp->addSelectionFilter(myDocumentShapeFilter); } void XGUI_ModuleConnector::deactivateSubShapesSelection() { XGUI_Displayer* aDisp = myWorkshop->displayer(); // The document limitation selection has to be only during operation - aDisp->removeSelectionFilter(myDocumentShapeFilter); + //aDisp->removeSelectionFilter(myDocumentShapeFilter); aDisp->closeLocalContexts(false); } @@ -92,8 +98,13 @@ ObjectPtr XGUI_ModuleConnector::findPresentedObject(const AISObjectPtr& theAIS) return aDisp->getObject(theAIS); } -void XGUI_ModuleConnector::setSelected(const QList& theFeatures) +void XGUI_ModuleConnector::setSelected(const QObjectPtrList& theFeatures) { XGUI_Displayer* aDisp = myWorkshop->displayer(); aDisp->setSelected(theFeatures); -} \ No newline at end of file +} + +bool XGUI_ModuleConnector::canStartOperation(QString theId) +{ + return myWorkshop->operationMgr()->canStartOperation(theId); +} diff --git a/src/XGUI/XGUI_ModuleConnector.h b/src/XGUI/XGUI_ModuleConnector.h index 8a869f1d0..7215fd53b 100644 --- a/src/XGUI/XGUI_ModuleConnector.h +++ b/src/XGUI/XGUI_ModuleConnector.h @@ -44,6 +44,9 @@ Q_OBJECT //! Returns currently active operation virtual ModuleBase_Operation* currentOperation() const; + //! Returns true if the operation with id theId can be started + virtual bool canStartOperation(QString theId); + //! Returns AIS opbject by data object virtual AISObjectPtr findPresentation(const ObjectPtr& theObject) const; @@ -52,7 +55,7 @@ Q_OBJECT //! Select features clearing previous selection. //! If the list is empty then selection will be cleared - virtual void setSelected(const QList& theFeatures); + virtual void setSelected(const QObjectPtrList& theFeatures); XGUI_Workshop* workshop() const { return myWorkshop; } diff --git a/src/XGUI/XGUI_ObjectsBrowser.cpp b/src/XGUI/XGUI_ObjectsBrowser.cpp index 0f8244534..5ed158e45 100644 --- a/src/XGUI/XGUI_ObjectsBrowser.cpp +++ b/src/XGUI/XGUI_ObjectsBrowser.cpp @@ -336,7 +336,7 @@ void XGUI_ObjectsBrowser::rebuildDataTree() } //*************************************************** -void XGUI_ObjectsBrowser::setObjectsSelected(const QList& theObjects) +void XGUI_ObjectsBrowser::setObjectsSelected(const QObjectPtrList& theObjects) { QList theIndexes; QItemSelectionModel* aSelectModel = myTreeView->selectionModel(); diff --git a/src/XGUI/XGUI_ObjectsBrowser.h b/src/XGUI/XGUI_ObjectsBrowser.h index 15e5e3690..4f844340a 100644 --- a/src/XGUI/XGUI_ObjectsBrowser.h +++ b/src/XGUI/XGUI_ObjectsBrowser.h @@ -21,7 +21,7 @@ Q_OBJECT virtual ~XGUI_DataTree(); //! Returns list of currently selected objects - QList selectedObjects() const + QObjectPtrList selectedObjects() const { return mySelectedData; } @@ -52,7 +52,7 @@ public slots: private: //! List of currently selected data - QList mySelectedData; + QObjectPtrList mySelectedData; }; /**\class XGUI_ObjectsBrowser @@ -73,12 +73,12 @@ Q_OBJECT } //! Returns list of currently selected objects - QList selectedObjects() const + QObjectPtrList selectedObjects() const { return myObjectsList; } - void setObjectsSelected(const QList& theObjects); + void setObjectsSelected(const QObjectPtrList& theObjects); //! Returns currently selected indexes QModelIndexList selectedIndexes() const @@ -134,7 +134,7 @@ signals: QLineEdit* myActiveDocLbl; XGUI_DataTree* myTreeView; - QList myObjectsList; + QObjectPtrList myObjectsList; }; #endif diff --git a/src/XGUI/XGUI_OperationMgr.cpp b/src/XGUI/XGUI_OperationMgr.cpp index f93cb6b6a..94e5026e2 100644 --- a/src/XGUI/XGUI_OperationMgr.cpp +++ b/src/XGUI/XGUI_OperationMgr.cpp @@ -36,6 +36,25 @@ bool XGUI_OperationMgr::hasOperation() const return !myOperations.isEmpty() && (myOperations.last() != NULL); } +bool XGUI_OperationMgr::hasOperation(const QString& theId) const +{ + foreach(ModuleBase_Operation* aOp, myOperations) { + if (aOp->id() == theId) + return true; + } + return false; +} + +ModuleBase_Operation* XGUI_OperationMgr::findOperation(const QString& theId) const +{ + foreach(ModuleBase_Operation* aOp, myOperations) { + if (aOp->id() == theId) + return aOp; + } + return 0; +} + + int XGUI_OperationMgr::operationsCount() const { return myOperations.count(); @@ -75,14 +94,15 @@ bool XGUI_OperationMgr::eventFilter(QObject *theObject, QEvent *theEvent) bool XGUI_OperationMgr::startOperation(ModuleBase_Operation* theOperation) { - if (!canStartOperation(theOperation)) - return false; - + if (hasOperation()) + currentOperation()->postpone(); myOperations.append(theOperation); - connect(theOperation, SIGNAL(stopped()), this, SLOT(onOperationStopped())); - connect(theOperation, SIGNAL(started()), this, SLOT(onOperationStarted())); - connect(theOperation, SIGNAL(resumed()), this, SIGNAL(operationResumed())); + connect(theOperation, SIGNAL(started()), SLOT(onOperationStarted())); + connect(theOperation, SIGNAL(aborted()), SLOT(onOperationAborted())); + connect(theOperation, SIGNAL(committed()), SLOT(onOperationComitted())); + connect(theOperation, SIGNAL(stopped()), SLOT(onOperationStopped())); + connect(theOperation, SIGNAL(resumed()), SLOT(onOperationResumed())); theOperation->start(); onValidateOperation(); @@ -135,12 +155,12 @@ void XGUI_OperationMgr::resumeOperation(ModuleBase_Operation* theOperation) theOperation->resume(); } -bool XGUI_OperationMgr::canStartOperation(ModuleBase_Operation* theOperation) +bool XGUI_OperationMgr::canStartOperation(QString theId) { bool aCanStart = true; ModuleBase_Operation* aCurrentOp = currentOperation(); if (aCurrentOp) { - if (!aCurrentOp->isGranted(theOperation)) { + if (!aCurrentOp->isGranted(theId)) { if (canAbortOperation()) { aCurrentOp->abort(); } else { @@ -189,6 +209,24 @@ void XGUI_OperationMgr::onOperationStarted() emit operationStarted(aSenderOperation); } +void XGUI_OperationMgr::onOperationAborted() +{ + ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); + emit operationAborted(aSenderOperation); +} + +void XGUI_OperationMgr::onOperationComitted() +{ + ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); + emit operationComitted(aSenderOperation); +} + +void XGUI_OperationMgr::onOperationResumed() +{ + ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); + emit operationResumed(aSenderOperation); +} + void XGUI_OperationMgr::onOperationStopped() { ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); @@ -226,6 +264,7 @@ bool XGUI_OperationMgr::onKeyReleased(QKeyEvent* theEvent) switch (theEvent->key()) { case Qt::Key_Return: case Qt::Key_Enter: { + emit keyEnterReleased(); commitOperation(); } break; @@ -233,9 +272,9 @@ bool XGUI_OperationMgr::onKeyReleased(QKeyEvent* theEvent) isAccepted = false; break; } - if(anOperation) { - anOperation->keyReleased(theEvent->key()); - } + //if(anOperation) { + // anOperation->keyReleased(theEvent->key()); + //} return isAccepted; } diff --git a/src/XGUI/XGUI_OperationMgr.h b/src/XGUI/XGUI_OperationMgr.h index 25a155617..29a340b0d 100644 --- a/src/XGUI/XGUI_OperationMgr.h +++ b/src/XGUI/XGUI_OperationMgr.h @@ -37,13 +37,23 @@ Q_OBJECT /// Returns the current operation or NULL /// \return the current operation ModuleBase_Operation* currentOperation() const; + /// Check if the given operation is active operation. /// Also, returns false is ther is no active operation. bool isCurrentOperation(ModuleBase_Operation* theOperation); + /// Returns true is operation manager has at least one non-null operation. bool hasOperation() const; + + /// Returns true is operation manager has an operation with given Id. + bool hasOperation(const QString& theId) const; + + /// Find and return operation by its Id. + ModuleBase_Operation* findOperation(const QString& theId) const; + /// Returns number of operations in the stack int operationsCount() const; + /// Returns list of all operations IDs QStringList operationList() const; @@ -60,6 +70,16 @@ Q_OBJECT bool abortAllOperations(); + /// Returns whether the operation can be started. Check if there is already started operation and + /// the granted parameter of the launched operation + /// \param theId id of the operation which is going to start + bool canStartOperation(QString theId); + + bool canStopOperation(); + + /// Returns true if the operation can be aborted + bool canAbortOperation(); + public slots: /// Slot that commits the current operation. void onCommitOperation(); @@ -71,14 +91,26 @@ Q_OBJECT signals: /// Signal about an operation is started. It is emitted after the start() of operation is done. void operationStarted(ModuleBase_Operation* theOperation); + /// Signal about an operation is stopped. It is emitted after the stop() of operation is done. /// \param theOperation a stopped operation void operationStopped(ModuleBase_Operation* theOperation); + /// Signal about an operation is resumed. It is emitted after the resume() of operation is done. - void operationResumed(); + void operationResumed(ModuleBase_Operation* theOperation); + + /// Emitted when current operation is comitted + void operationComitted(ModuleBase_Operation* theOperation); + + /// Emitted when current operation is aborted + void operationAborted(ModuleBase_Operation* theOperation); + /// Signal is emitted after the validate methods calls. void operationValidated(bool); + /// Signal is emitted after the key released click. + void keyEnterReleased(); + protected: /// Commits the current operatin if it is valid @@ -89,16 +121,6 @@ signals: /// \return the state whether the operation is resumed void resumeOperation(ModuleBase_Operation* theOperation); - /// Returns whether the operation can be started. Check if there is already started operation and - /// the granted parameter of the launched operation - /// \param theOperation an operation to check - bool canStartOperation(ModuleBase_Operation* theOperation); - - bool canStopOperation(); - - /// Returns true if the operation can be aborted - bool canAbortOperation(); - public slots: /// SLOT, that is called by the key in the property panel is clicked. /// \param theName the attribute name @@ -110,6 +132,9 @@ signals: /// If there is a suspended operation, restart it. void onOperationStopped(); void onOperationStarted(); + void onOperationAborted(); + void onOperationComitted(); + void onOperationResumed(); private: typedef QList Operations; ///< definition for a list of operations diff --git a/src/XGUI/XGUI_PartDataModel.cpp b/src/XGUI/XGUI_PartDataModel.cpp index c7f1b81a2..b1ec5e745 100644 --- a/src/XGUI/XGUI_PartDataModel.cpp +++ b/src/XGUI/XGUI_PartDataModel.cpp @@ -295,7 +295,7 @@ QVariant XGUI_PartDataModel::data(const QModelIndex& theIndex, int theRole) cons return aObject->data()->name().c_str(); } case HistoryObject: { - ObjectPtr aObject = partDocument()->object(ModelAPI_Feature::group(), theIndex.row() - 4); + ObjectPtr aObject = partDocument()->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber()); if (aObject) return aObject->data()->name().c_str(); } @@ -319,16 +319,17 @@ QVariant XGUI_PartDataModel::data(const QModelIndex& theIndex, int theRole) cons std::string aGroup = theIndex.internalId() == ConstructObject ? ModelAPI_ResultConstruction::group() : ModelAPI_ResultBody::group(); ObjectPtr anObject = partDocument()->object(aGroup, theIndex.row()); - if (anObject && anObject->data() && anObject->data()->mustBeUpdated()) { + if (anObject && anObject->data() && + anObject->data()->execState() == ModelAPI_StateMustBeUpdated) { return QIcon(":pictures/constr_object_modified.png"); } return QIcon(":pictures/constr_object.png"); } case HistoryObject: { - ObjectPtr aObject = partDocument()->object(ModelAPI_Feature::group(), theIndex.row() - 4); + ObjectPtr aObject = partDocument()->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber()); FeaturePtr aFeature = std::dynamic_pointer_cast(aObject); if (aFeature) - return QIcon(XGUI_Workshop::featureIcon(aFeature->getKind())); + return XGUI_Workshop::featureIcon(aFeature); } } break; @@ -360,9 +361,9 @@ int XGUI_PartDataModel::rowCount(const QModelIndex& parent) const case MyRoot: { DocumentPtr aDoc = partDocument(); - if (aDoc) - return 4 + aDoc->size(ModelAPI_Feature::group()); - else + if (aDoc) { + return getRowsNumber() + aDoc->size(ModelAPI_Feature::group()); + } else return 0; } case ParamsFolder: @@ -398,7 +399,13 @@ QModelIndex XGUI_PartDataModel::index(int theRow, int theColumn, const QModelInd case 2: return createIndex(theRow, 0, (qint32) BodiesFolder); case 3: - return createIndex(theRow, 0, (qint32) GroupsFolder); + { + int aSize = partDocument()->size(ModelAPI_ResultGroup::group()); + if (aSize > 0) + return createIndex(theRow, 0, (qint32) GroupsFolder); + else + return createIndex(theRow, theColumn, (qint32) HistoryObject); + } default: return createIndex(theRow, theColumn, (qint32) HistoryObject); } @@ -475,7 +482,7 @@ ObjectPtr XGUI_PartDataModel::object(const QModelIndex& theIndex) const case GroupObject: return partDocument()->object(ModelAPI_ResultGroup::group(), theIndex.row()); case HistoryObject: - return partDocument()->object(ModelAPI_Feature::group(), theIndex.row() - 4); + return partDocument()->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber()); } return ObjectPtr(); } @@ -492,13 +499,13 @@ QModelIndex XGUI_PartDataModel::findParent(const ObjectPtr& theObject) const QModelIndex XGUI_PartDataModel::findGroup(const std::string& theGroup) const { - if (theGroup.compare(ModelAPI_ResultParameters::group()) == 0) + if (theGroup == ModelAPI_ResultParameters::group()) return createIndex(0, 0, (qint32) ParamsFolder); - if (theGroup.compare(ModelAPI_ResultConstruction::group()) == 0) + if (theGroup == ModelAPI_ResultConstruction::group()) return createIndex(1, 0, (qint32) ConstructFolder); - if (theGroup.compare(ModelAPI_ResultBody::group()) == 0) + if (theGroup == ModelAPI_ResultBody::group()) return createIndex(2, 0, (qint32) BodiesFolder); - if (theGroup.compare(ModelAPI_ResultGroup::group()) == 0) + if (theGroup == ModelAPI_ResultGroup::group()) return createIndex(3, 0, (qint32) GroupsFolder); return QModelIndex(); } @@ -538,7 +545,16 @@ QModelIndex XGUI_PartDataModel::objectIndex(const ObjectPtr& theObject) const else if (aGroup == ModelAPI_ResultGroup::group()) return createIndex(aRow, 0, (qint32) GroupObject); else - return createIndex(aRow + 4, 0, (qint32) HistoryObject); + return createIndex(aRow + getRowsNumber(), 0, (qint32) HistoryObject); } return aIndex; } + + +int XGUI_PartDataModel::getRowsNumber() const +{ + int aSize = partDocument()->size(ModelAPI_ResultGroup::group()); + if (aSize == 0) // If there are no groups then do not show group folder + return 3; + return 4; +} \ No newline at end of file diff --git a/src/XGUI/XGUI_PartDataModel.h b/src/XGUI/XGUI_PartDataModel.h index 8aec45dab..0d9a394af 100644 --- a/src/XGUI/XGUI_PartDataModel.h +++ b/src/XGUI/XGUI_PartDataModel.h @@ -111,6 +111,8 @@ Q_OBJECT //! Returns document of the current part DocumentPtr partDocument() const; + int getRowsNumber() const; + //! Types of QModelIndexes enum DataIds { diff --git a/src/XGUI/XGUI_Preferences.cpp b/src/XGUI/XGUI_Preferences.cpp index 635462d89..0dc2e5f8e 100644 --- a/src/XGUI/XGUI_Preferences.cpp +++ b/src/XGUI/XGUI_Preferences.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -125,10 +126,20 @@ void XGUI_Preferences::createCustomPage(XGUI_IPrefMgr* thePref, int thePageId) isResModified = true; } // Add item - if (aProp->type() != Config_Prop::Disabled) - thePref->addPreference(QObject::tr(aProp->title().c_str()), aTab, - (SUIT_PreferenceMgr::PrefItemType) aProp->type(), - QString(aProp->section().c_str()), QString(aProp->name().c_str())); + if (aProp->type() != Config_Prop::Disabled) { + SUIT_PreferenceMgr::PrefItemType aPrefType = SUIT_PreferenceMgr::Auto; + if (aProp->type() == Config_Prop::Directory) { + aPrefType = SUIT_PreferenceMgr::File; + } else { + aPrefType = (SUIT_PreferenceMgr::PrefItemType) aProp->type(); + } + int anId = thePref->addPreference(QObject::tr(aProp->title().c_str()), aTab, aPrefType, + QString::fromStdString(aProp->section()), + QString::fromStdString(aProp->name())); + if(aProp->type() == Config_Prop::Directory) { + thePref->setItemProperty("path_type", Qtx::PT_Directory, anId); + } + } } } } @@ -148,6 +159,11 @@ public: return myMgr->addItem(theLbl, pId, theType, theSection, theName); } + virtual void setItemProperty( const QString& thePropName, const QVariant& theValue, + const int theId = -1) { + myMgr->setItemProperty(thePropName, theValue, theId); + } + virtual SUIT_PreferenceMgr* prefMgr() const { return myMgr; } private: diff --git a/src/XGUI/XGUI_PropertyPanel.cpp b/src/XGUI/XGUI_PropertyPanel.cpp index caa9b07a4..001224625 100644 --- a/src/XGUI/XGUI_PropertyPanel.cpp +++ b/src/XGUI/XGUI_PropertyPanel.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include @@ -17,6 +17,7 @@ #include #include #include +#include #ifdef _DEBUG #include @@ -62,7 +63,7 @@ XGUI_PropertyPanel::XGUI_PropertyPanel(QWidget* theParent) myCustomWidget = new QWidget(aContent); myMainLayout->addWidget(myCustomWidget); - myMainLayout->addStretch(1); + setStretchEnabled(true); } XGUI_PropertyPanel::~XGUI_PropertyPanel() @@ -71,6 +72,8 @@ XGUI_PropertyPanel::~XGUI_PropertyPanel() void XGUI_PropertyPanel::cleanContent() { + if (myActiveWidget) + myActiveWidget->deactivate(); myWidgets.clear(); qDeleteAll(myCustomWidget->children()); myActiveWidget = NULL; @@ -79,24 +82,33 @@ void XGUI_PropertyPanel::cleanContent() void XGUI_PropertyPanel::setModelWidgets(const QList& theWidgets) { myWidgets = theWidgets; - int aS = myWidgets.size(); if (theWidgets.empty()) return; - + bool isEnableStretch = true; QList::const_iterator anIt = theWidgets.begin(), aLast = theWidgets.end(); for (; anIt != aLast; anIt++) { connect(*anIt, SIGNAL(keyReleased(QKeyEvent*)), this, SIGNAL(keyReleased(QKeyEvent*))); - - connect(*anIt, SIGNAL(focusOutWidget(ModuleBase_ModelWidget*)), this, - SLOT(activateNextWidget(ModuleBase_ModelWidget*))); + connect(*anIt, SIGNAL(focusOutWidget(ModuleBase_ModelWidget*)), + this, SLOT(activateNextWidget(ModuleBase_ModelWidget*))); connect(*anIt, SIGNAL(focusInWidget(ModuleBase_ModelWidget*)), - this, SLOT(activateWidget(ModuleBase_ModelWidget*))); - - ModuleBase_WidgetPoint2D* aPointWidget = dynamic_cast(*anIt); - if (aPointWidget) - connect(aPointWidget, SIGNAL(storedPoint2D(ObjectPtr, const std::string&)), this, - SIGNAL(storedPoint2D(ObjectPtr, const std::string&))); + this, SLOT(activateWidget(ModuleBase_ModelWidget*))); + + //ModuleBase_WidgetPoint2D* aPointWidget = dynamic_cast(*anIt); + //if (aPointWidget) + // connect(aPointWidget, SIGNAL(storedPoint2D(ObjectPtr, const std::string&)), this, + // SIGNAL(storedPoint2D(ObjectPtr, const std::string&))) + //} + + if (!isEnableStretch) continue; + foreach(QWidget* eachWidget, (*anIt)->getControls()) { + QSizePolicy::Policy aVPolicy = eachWidget->sizePolicy().verticalPolicy(); + if(aVPolicy == QSizePolicy::Expanding || + aVPolicy == QSizePolicy::MinimumExpanding) { + isEnableStretch = false; + } + } } + setStretchEnabled(isEnableStretch); ModuleBase_ModelWidget* aLastWidget = theWidgets.last(); if (aLastWidget) { QList aControls = aLastWidget->getControls(); @@ -138,6 +150,11 @@ void XGUI_PropertyPanel::updateContentWidget(FeaturePtr theFeature) void XGUI_PropertyPanel::activateNextWidget(ModuleBase_ModelWidget* theWidget) { + // TO CHECK: Editing operation does not have automatical activation of widgets + if (isEditingMode()) { + activateWidget(NULL); + return; + } ModuleBase_ModelWidget* aNextWidget = 0; QList::const_iterator anIt = myWidgets.begin(), aLast = myWidgets.end(); bool isFoundWidget = false; @@ -151,8 +168,23 @@ void XGUI_PropertyPanel::activateNextWidget(ModuleBase_ModelWidget* theWidget) } // Normaly focusTo is enough to activate widget // here is a special case on mouse click in the viewer - if(aNextWidget == NULL) { - activateWidget(NULL); + //if(aNextWidget == NULL) { + activateWidget(aNextWidget); + //} +} + +void XGUI_PropertyPanel::setStretchEnabled(bool isEnabled) +{ + if (myMainLayout->count() == 0) + return; + int aStretchIdx = myMainLayout->count() - 1; + bool hasStretch = myMainLayout->itemAt(aStretchIdx)->spacerItem() != NULL; + QLayoutItem* aChild; + if (isEnabled) { + if (!hasStretch) myMainLayout->addStretch(1); + } else if (hasStretch) { + aChild = myMainLayout->takeAt(aStretchIdx); + delete aChild; } } @@ -169,12 +201,20 @@ void XGUI_PropertyPanel::setAcceptEnabled(bool isEnabled) void XGUI_PropertyPanel::activateWidget(ModuleBase_ModelWidget* theWidget) { + // Avoid activation of already actve widget. It could happen on focusIn event many times + if (theWidget == myActiveWidget) + return; if(myActiveWidget) { + myActiveWidget->deactivate(); myActiveWidget->setHighlighted(false); } if(theWidget) { + theWidget->activate(); theWidget->setHighlighted(true); } myActiveWidget = theWidget; - emit widgetActivated(theWidget); + if (myActiveWidget) + emit widgetActivated(theWidget); + else if (!isEditingMode()) + emit noMoreWidgets(); } diff --git a/src/XGUI/XGUI_PropertyPanel.h b/src/XGUI/XGUI_PropertyPanel.h index 04c4d1ed3..28c624618 100644 --- a/src/XGUI/XGUI_PropertyPanel.h +++ b/src/XGUI/XGUI_PropertyPanel.h @@ -49,22 +49,23 @@ Q_OBJECT /// Activate the next from current widget in the property panel virtual void activateNextWidget(); + void setStretchEnabled(bool isEnabled); + public slots: void updateContentWidget(FeaturePtr theFeature); // Enables / disables "ok" ("accept") button void setAcceptEnabled(bool); - protected slots: // Makes the given widget active, highlights it and removes // highlighting from the previous active widget // emits widgetActivated(theWidget) signal - void activateWidget(ModuleBase_ModelWidget* theWidget); + virtual void activateWidget(ModuleBase_ModelWidget* theWidget); signals: /// Signal about the point 2d set to the feature /// \param the feature /// \param the attribute of the feature - void storedPoint2D(ObjectPtr theFeature, const std::string& theAttribute); + //void storedPoint2D(ObjectPtr theFeature, const std::string& theAttribute); private: diff --git a/src/XGUI/XGUI_Selection.cpp b/src/XGUI/XGUI_Selection.cpp index 265fb9029..59a5d2cce 100644 --- a/src/XGUI/XGUI_Selection.cpp +++ b/src/XGUI/XGUI_Selection.cpp @@ -21,39 +21,54 @@ XGUI_Selection::XGUI_Selection(XGUI_Workshop* theWorkshop) QList XGUI_Selection::getSelected(int theShapeTypeToSkip) const { - //std::set aPrsFeatures; + QList aSelectedIds; // Remember of selected address in order to avoid duplicates + QList aPresentations; XGUI_Displayer* aDisplayer = myWorkshop->displayer(); Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext(); - for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected()) { - ModuleBase_ViewerPrs aPrs; - - Handle(AIS_InteractiveObject) anIO = aContext->SelectedInteractive(); - aPrs.setInteractive(anIO); - - ObjectPtr aFeature = aDisplayer->getObject(anIO); - // we should not check the appearance of this feature because there can be some selected shapes - // for one feature - //if (aPrsFeatures.find(aFeature) == aPrsFeatures.end()) { - aPrs.setFeature(aFeature); - //aPrsFeatures.insert(aFeature); - //} - if (aContext->HasOpenedContext()) { + if (aContext->HasOpenedContext()) { + for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected()) { + ModuleBase_ViewerPrs aPrs; + Handle(AIS_InteractiveObject) anIO = aContext->SelectedInteractive(); + if (aSelectedIds.contains((long)anIO.Access())) + continue; + + aSelectedIds.append((long)anIO.Access()); + aPrs.setInteractive(anIO); + + ObjectPtr aFeature = aDisplayer->getObject(anIO); + // we should not check the appearance of this feature because there can be some selected shapes + // for one feature TopoDS_Shape aShape = aContext->SelectedShape(); if (!aShape.IsNull() && (aShape.ShapeType() != theShapeTypeToSkip)) aPrs.setShape(aShape); + Handle(SelectMgr_EntityOwner) anOwner = aContext->SelectedOwner(); + aPrs.setOwner(anOwner); + aPrs.setFeature(aFeature); + aPresentations.append(aPrs); + } + } else { + for (aContext->InitCurrent(); aContext->MoreCurrent(); aContext->NextCurrent()) { + ModuleBase_ViewerPrs aPrs; + Handle(AIS_InteractiveObject) anIO = aContext->Current(); + if (aSelectedIds.contains((long)anIO.Access())) + continue; + + aSelectedIds.append((long)anIO.Access()); + aPrs.setInteractive(anIO); + + ObjectPtr aFeature = aDisplayer->getObject(anIO); + aPrs.setFeature(aFeature); + aPresentations.append(aPrs); } - Handle(SelectMgr_EntityOwner) anOwner = aContext->SelectedOwner(); - aPrs.setOwner(anOwner); - aPresentations.append(aPrs); } return aPresentations; } QList XGUI_Selection::getHighlighted(int theShapeTypeToSkip) const { - //std::set aPrsFeatures; + QList aSelectedIds; // Remember of selected address in order to avoid duplicates QList aPresentations; XGUI_Displayer* aDisplayer = myWorkshop->displayer(); @@ -61,15 +76,16 @@ QList XGUI_Selection::getHighlighted(int theShapeTypeToSki for (aContext->InitDetected(); aContext->MoreDetected(); aContext->NextDetected()) { ModuleBase_ViewerPrs aPrs; Handle(AIS_InteractiveObject) anIO = aContext->DetectedInteractive(); + if (aSelectedIds.contains((long)anIO.Access())) + continue; + + aSelectedIds.append((long)anIO.Access()); aPrs.setInteractive(anIO); ObjectPtr aResult = aDisplayer->getObject(anIO); // we should not check the appearance of this feature because there can be some selected shapes // for one feature - //if (aPrsFeatures.find(aResult) == aPrsFeatures.end()) { - aPrs.setFeature(aResult); - //aPrsFeatures.insert(aResult); - //} + aPrs.setFeature(aResult); if (aContext->HasOpenedContext()) { TopoDS_Shape aShape = aContext->DetectedShape(); if (!aShape.IsNull() && aShape.ShapeType() != theShapeTypeToSkip) @@ -80,14 +96,14 @@ QList XGUI_Selection::getHighlighted(int theShapeTypeToSki return aPresentations; } -QList XGUI_Selection::selectedObjects() const +QObjectPtrList XGUI_Selection::selectedObjects() const { return myWorkshop->objectBrowser()->selectedObjects(); } -QList XGUI_Selection::selectedPresentations() const +QObjectPtrList XGUI_Selection::selectedPresentations() const { - QList aSelectedList; + QObjectPtrList aSelectedList; Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext(); for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected()) { diff --git a/src/XGUI/XGUI_Selection.h b/src/XGUI/XGUI_Selection.h index 4868a9a80..1f8c5fc97 100644 --- a/src/XGUI/XGUI_Selection.h +++ b/src/XGUI/XGUI_Selection.h @@ -34,14 +34,14 @@ class XGUI_EXPORT XGUI_Selection : public ModuleBase_ISelection virtual QList getHighlighted(int theShapeTypeToSkip = -1) const; /** - * Returns list of currently selected objects + * Returns list of currently selected objects in object browser */ - virtual QList selectedObjects() const; + virtual QObjectPtrList selectedObjects() const; /** * Returns list of currently selected results */ - virtual QList selectedPresentations() const; + virtual QObjectPtrList selectedPresentations() const; //! Returns list of currently selected QModelIndexes virtual QModelIndexList selectedIndexes() const; diff --git a/src/XGUI/XGUI_SelectionMgr.cpp b/src/XGUI/XGUI_SelectionMgr.cpp index 3d3937fc6..25bfd7030 100644 --- a/src/XGUI/XGUI_SelectionMgr.cpp +++ b/src/XGUI/XGUI_SelectionMgr.cpp @@ -40,7 +40,7 @@ void XGUI_SelectionMgr::connectViewers() //************************************************************** void XGUI_SelectionMgr::onObjectBrowserSelection() { - QList aObjects = myWorkshop->objectBrowser()->selectedObjects(); + QObjectPtrList aObjects = myWorkshop->objectBrowser()->selectedObjects(); XGUI_Displayer* aDisplayer = myWorkshop->displayer(); aDisplayer->setSelected(aObjects); emit selectionChanged(); @@ -49,7 +49,7 @@ void XGUI_SelectionMgr::onObjectBrowserSelection() //************************************************************** void XGUI_SelectionMgr::onViewerSelection() { - QList aFeatures; + QObjectPtrList aFeatures; Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext(); for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected()) { Handle(AIS_InteractiveObject) anIO = aContext->SelectedInteractive(); diff --git a/src/XGUI/XGUI_ViewWindow.cpp b/src/XGUI/XGUI_ViewWindow.cpp index b07d4676a..e36aff2c5 100644 --- a/src/XGUI/XGUI_ViewWindow.cpp +++ b/src/XGUI/XGUI_ViewWindow.cpp @@ -672,7 +672,7 @@ void XGUI_ViewWindow::vpMousePressEvent(QMouseEvent* theEvent) if (ic->NbSelected() == 0) myCurrPointType = myPrevPointType; //if ( mySetRotationPointDlg ) mySetRotationPointDlg->toggleChange(); - ic->CloseAllContexts(); + //ic->CloseAllContexts(); myOperation = NOTHING; myViewPort->setCursor(myCursor); myCursorIsHand = false; @@ -1215,3 +1215,8 @@ void XGUI_ViewWindow::updateEnabledDrawMode() { myEnableDrawMode = myViewer->isSelectionEnabled() && myViewer->isMultiSelectionEnabled(); } + +Handle(V3d_View) XGUI_ViewWindow::v3dView() const +{ + return myViewPort->getView(); +} \ No newline at end of file diff --git a/src/XGUI/XGUI_ViewWindow.h b/src/XGUI/XGUI_ViewWindow.h index bd2aef20e..f3216a580 100644 --- a/src/XGUI/XGUI_ViewWindow.h +++ b/src/XGUI/XGUI_ViewWindow.h @@ -4,6 +4,8 @@ #include "XGUI.h" #include "XGUI_Constants.h" +#include + #include #include @@ -12,8 +14,8 @@ #include #include -#include -#include +//#include +//#include class XGUI_ViewPort; class XGUI_Viewer; @@ -29,7 +31,7 @@ class QMdiSubWindow; It contains a view port object (drawing area) and toolbars for view camera and window management. Also it managements events in view port */ -class XGUI_EXPORT XGUI_ViewWindow : public QFrame +class XGUI_EXPORT XGUI_ViewWindow : public QFrame, public ModuleBase_IViewWindow { Q_OBJECT public: @@ -109,6 +111,9 @@ Q_OBJECT //! Updates drawing mode in the view window void updateEnabledDrawMode(); + /// Returns OCCT object which contains 3d view object + virtual Handle(V3d_View) v3dView() const; + signals: //! Emited whien view transformation operation is started void vpTransformationStarted(XGUI_ViewWindow::OperationType type); diff --git a/src/XGUI/XGUI_ViewerProxy.cpp b/src/XGUI/XGUI_ViewerProxy.cpp index 782023d87..ffd09a2a5 100644 --- a/src/XGUI/XGUI_ViewerProxy.cpp +++ b/src/XGUI/XGUI_ViewerProxy.cpp @@ -5,6 +5,7 @@ #include "XGUI_ViewWindow.h" #include "XGUI_Viewer.h" #include "XGUI_SalomeConnector.h" +#include "XGUI_Displayer.h" XGUI_ViewerProxy::XGUI_ViewerProxy(XGUI_Workshop* theParent) : ModuleBase_IViewer(theParent), @@ -68,23 +69,35 @@ void XGUI_ViewerProxy::connectToViewer() ModuleBase_IViewer* aViewer = myWorkshop->salomeConnector()->viewer(); connect(aViewer, SIGNAL(lastViewClosed()), this, SIGNAL(lastViewClosed())); - connect(aViewer, SIGNAL(tryCloseView()), this, SIGNAL(tryCloseView())); - connect(aViewer, SIGNAL(deleteView()), this, SIGNAL(deleteView())); - connect(aViewer, SIGNAL(viewCreated()), this, SIGNAL(viewCreated())); - connect(aViewer, SIGNAL(activated()), this, SIGNAL(activated())); + connect(aViewer, SIGNAL(tryCloseView(ModuleBase_IViewWindow*)), + this, SIGNAL(tryCloseView(ModuleBase_IViewWindow*))); - connect(aViewer, SIGNAL(mousePress(QMouseEvent*)), this, SIGNAL(mousePress(QMouseEvent*))); + connect(aViewer, SIGNAL(deleteView(ModuleBase_IViewWindow*)), + this, SIGNAL(deleteView(ModuleBase_IViewWindow*))); - connect(aViewer, SIGNAL(mouseRelease(QMouseEvent*)), this, SIGNAL(mouseRelease(QMouseEvent*))); + connect(aViewer, SIGNAL(viewCreated(ModuleBase_IViewWindow*)), + this, SIGNAL(viewCreated(ModuleBase_IViewWindow*))); - connect(aViewer, SIGNAL(mouseDoubleClick(QMouseEvent*)), this, - SIGNAL(mouseDoubleClick(QMouseEvent*))); + connect(aViewer, SIGNAL(activated(ModuleBase_IViewWindow*)), + this, SIGNAL(activated(ModuleBase_IViewWindow*))); - connect(aViewer, SIGNAL(mouseMove(QMouseEvent*)), this, SIGNAL(mouseMove(QMouseEvent*))); + connect(aViewer, SIGNAL(mousePress(ModuleBase_IViewWindow*, QMouseEvent*)), + this, SIGNAL(mousePress(ModuleBase_IViewWindow*, QMouseEvent*))); - connect(aViewer, SIGNAL(keyPress(QKeyEvent*)), this, SIGNAL(keyPress(QKeyEvent*))); + connect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)), + this, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*))); - connect(aViewer, SIGNAL(keyRelease(QKeyEvent*)), this, SIGNAL(keyRelease(QKeyEvent*))); + connect(aViewer, SIGNAL(mouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)), this, + SIGNAL(mouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*))); + + connect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)), + this, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*))); + + connect(aViewer, SIGNAL(keyPress(ModuleBase_IViewWindow*, QKeyEvent*)), + this, SIGNAL(keyPress(ModuleBase_IViewWindow*, QKeyEvent*))); + + connect(aViewer, SIGNAL(keyRelease(ModuleBase_IViewWindow*, QKeyEvent*)), + this, SIGNAL(keyRelease(ModuleBase_IViewWindow*, QKeyEvent*))); connect(aViewer, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged())); connect(aViewer, SIGNAL(contextMenuRequested(QContextMenuEvent*)), this, @@ -94,21 +107,34 @@ void XGUI_ViewerProxy::connectToViewer() XGUI_Viewer* aViewer = myWorkshop->mainWindow()->viewer(); connect(aViewer, SIGNAL(lastViewClosed()), this, SIGNAL(lastViewClosed())); - connect(aViewer, SIGNAL(tryCloseView(XGUI_ViewWindow*)), this, SIGNAL(tryCloseView())); - connect(aViewer, SIGNAL(deleteView(XGUI_ViewWindow*)), this, SIGNAL(deleteView())); - connect(aViewer, SIGNAL(viewCreated(XGUI_ViewWindow*)), this, SIGNAL(viewCreated())); - connect(aViewer, SIGNAL(activated(XGUI_ViewWindow*)), this, SIGNAL(activated())); + + connect(aViewer, SIGNAL(tryCloseView(XGUI_ViewWindow*)), + this, SLOT(onTryCloseView(XGUI_ViewWindow*))); + + connect(aViewer, SIGNAL(deleteView(XGUI_ViewWindow*)), + this, SLOT(onDeleteView(XGUI_ViewWindow*))); + + connect(aViewer, SIGNAL(viewCreated(XGUI_ViewWindow*)), + this, SLOT(onViewCreated(XGUI_ViewWindow*))); + + connect(aViewer, SIGNAL(activated(XGUI_ViewWindow*)), + this, SLOT(onActivated(XGUI_ViewWindow*))); connect(aViewer, SIGNAL(mousePress(XGUI_ViewWindow*, QMouseEvent*)), this, SLOT(onMousePress(XGUI_ViewWindow*, QMouseEvent*))); + connect(aViewer, SIGNAL(mouseRelease(XGUI_ViewWindow*, QMouseEvent*)), this, SLOT(onMouseRelease(XGUI_ViewWindow*, QMouseEvent*))); + connect(aViewer, SIGNAL(mouseDoubleClick(XGUI_ViewWindow*, QMouseEvent*)), this, SLOT(onMouseDoubleClick(XGUI_ViewWindow*, QMouseEvent*))); + connect(aViewer, SIGNAL(mouseMove(XGUI_ViewWindow*, QMouseEvent*)), this, SLOT(onMouseMove(XGUI_ViewWindow*, QMouseEvent*))); + connect(aViewer, SIGNAL(keyPress(XGUI_ViewWindow*, QKeyEvent*)), this, SLOT(onKeyPress(XGUI_ViewWindow*, QKeyEvent*))); + connect(aViewer, SIGNAL(keyRelease(XGUI_ViewWindow*, QKeyEvent*)), this, SLOT(onKeyRelease(XGUI_ViewWindow*, QKeyEvent*))); @@ -118,36 +144,59 @@ void XGUI_ViewerProxy::connectToViewer() } } -void XGUI_ViewerProxy::onMousePress(XGUI_ViewWindow*, QMouseEvent* theEvent) + +void XGUI_ViewerProxy::onTryCloseView(XGUI_ViewWindow* theWnd) +{ + emit tryCloseView(theWnd); +} + +void XGUI_ViewerProxy::onDeleteView(XGUI_ViewWindow* theWnd) +{ + emit deleteView(theWnd); +} + +void XGUI_ViewerProxy::onViewCreated(XGUI_ViewWindow* theWnd) { - emit mousePress(theEvent); + emit viewCreated(theWnd); } -void XGUI_ViewerProxy::onMouseRelease(XGUI_ViewWindow*, QMouseEvent* theEvent) +void XGUI_ViewerProxy::onActivated(XGUI_ViewWindow* theWnd) { - emit mouseRelease(theEvent); + emit activated(theWnd); } -void XGUI_ViewerProxy::onMouseDoubleClick(XGUI_ViewWindow*, QMouseEvent* theEvent) +void XGUI_ViewerProxy::onMousePress(XGUI_ViewWindow* theWnd, QMouseEvent* theEvent) { - emit mouseDoubleClick(theEvent); + emit mousePress(theWnd, theEvent); } -void XGUI_ViewerProxy::onMouseMove(XGUI_ViewWindow*, QMouseEvent* theEvent) +void XGUI_ViewerProxy::onMouseRelease(XGUI_ViewWindow* theWnd, QMouseEvent* theEvent) { - emit mouseMove(theEvent); + emit mouseRelease(theWnd, theEvent); } -void XGUI_ViewerProxy::onKeyPress(XGUI_ViewWindow*, QKeyEvent* theEvent) +void XGUI_ViewerProxy::onMouseDoubleClick(XGUI_ViewWindow* theWnd, QMouseEvent* theEvent) { - emit keyPress(theEvent); + emit mouseDoubleClick(theWnd, theEvent); } -void XGUI_ViewerProxy::onKeyRelease(XGUI_ViewWindow*, QKeyEvent* theEvent) +void XGUI_ViewerProxy::onMouseMove(XGUI_ViewWindow* theWnd, QMouseEvent* theEvent) { - emit keyRelease(theEvent); + emit mouseMove(theWnd, theEvent); } +void XGUI_ViewerProxy::onKeyPress(XGUI_ViewWindow* theWnd, QKeyEvent* theEvent) +{ + emit keyPress(theWnd, theEvent); +} + +void XGUI_ViewerProxy::onKeyRelease(XGUI_ViewWindow* theWnd, QKeyEvent* theEvent) +{ + emit keyRelease(theWnd, theEvent); +} + + + //*************************************** void XGUI_ViewerProxy::enableSelection(bool isEnabled) { @@ -191,26 +240,17 @@ bool XGUI_ViewerProxy::isMultiSelectionEnabled() const //*************************************** void XGUI_ViewerProxy::addSelectionFilter(const Handle(SelectMgr_Filter)& theFilter) { - Handle(AIS_InteractiveContext) aContext = AISContext(); - if (!aContext.IsNull()) { - aContext->AddFilter(theFilter); - } + myWorkshop->displayer()->addSelectionFilter(theFilter); } //*************************************** void XGUI_ViewerProxy::removeSelectionFilter(const Handle(SelectMgr_Filter)& theFilter) { - Handle(AIS_InteractiveContext) aContext = AISContext(); - if (!aContext.IsNull()) { - aContext->RemoveFilter(theFilter); - } + myWorkshop->displayer()->removeSelectionFilter(theFilter); } //*************************************** void XGUI_ViewerProxy::clearSelectionFilters() { - Handle(AIS_InteractiveContext) aContext = AISContext(); - if (!aContext.IsNull()) { - aContext->RemoveFilters(); - } + myWorkshop->displayer()->removeFilters(); } diff --git a/src/XGUI/XGUI_ViewerProxy.h b/src/XGUI/XGUI_ViewerProxy.h index caca6ec42..f3872f86c 100644 --- a/src/XGUI/XGUI_ViewerProxy.h +++ b/src/XGUI/XGUI_ViewerProxy.h @@ -61,11 +61,17 @@ Q_OBJECT /// Remove all selection filters from the viewer virtual void clearSelectionFilters(); - private slots: +private slots: + void onTryCloseView(XGUI_ViewWindow*); + void onDeleteView(XGUI_ViewWindow*); + void onViewCreated(XGUI_ViewWindow*); + void onActivated(XGUI_ViewWindow*); + void onMousePress(XGUI_ViewWindow*, QMouseEvent*); void onMouseRelease(XGUI_ViewWindow*, QMouseEvent*); void onMouseDoubleClick(XGUI_ViewWindow*, QMouseEvent*); void onMouseMove(XGUI_ViewWindow*, QMouseEvent*); + void onKeyPress(XGUI_ViewWindow*, QKeyEvent*); void onKeyRelease(XGUI_ViewWindow*, QKeyEvent*); diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 12f3a4767..0bf4c4bcb 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -75,12 +76,44 @@ QMap XGUI_Workshop::myIcons; -QString XGUI_Workshop::featureIcon(const std::string& theId) +std::string XGUI_Workshop::featureIconStr(const FeaturePtr& theFeature) { - QString aId(theId.c_str()); - if (myIcons.contains(aId)) - return myIcons[aId]; - return QString(); + std::string aKind = theFeature->getKind(); + QString aId(aKind.c_str()); + if (!myIcons.contains(aId)) + return std::string(); + + return myIcons[aId].toStdString(); +} + +QIcon XGUI_Workshop::featureIcon(const FeaturePtr& theFeature) +{ + QIcon anIcon; + + QString anIconString = featureIconStr(theFeature).c_str(); + + ModelAPI_ExecState aState = theFeature->data()->execState(); + switch(aState) { + case ModelAPI_StateDone: + case ModelAPI_StateNothing: + anIcon = QIcon(anIconString); + case ModelAPI_StateMustBeUpdated: { + anIcon = ModuleBase_Tools::lighter(anIconString); + } + break; + case ModelAPI_StateExecFailed: { + anIcon = ModuleBase_Tools::composite(":pictures/exec_state_failed.png", + 12, 12, anIconString); + } + break; + case ModelAPI_StateInvalidArgument: { + anIcon = ModuleBase_Tools::composite(":pictures/exec_state_invalid_parameters.png", + 12, 12, anIconString); + } + break; + default: break; + } + return anIcon; } XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) @@ -115,7 +148,7 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) connect(myOperationMgr, SIGNAL(operationStarted(ModuleBase_Operation*)), SLOT(onOperationStarted())); - connect(myOperationMgr, SIGNAL(operationResumed()), SLOT(onOperationStarted())); + connect(myOperationMgr, SIGNAL(operationResumed(ModuleBase_Operation*)), SLOT(onOperationStarted())); connect(myOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)), SLOT(onOperationStopped(ModuleBase_Operation*))); connect(myMainWindow, SIGNAL(exitKeySequence()), SLOT(onExit())); @@ -137,6 +170,10 @@ XGUI_Workshop::~XGUI_Workshop(void) void XGUI_Workshop::startApplication() { initMenu(); + + Config_PropManager::registerProp("Plugins", "default_path", "Default Path", + Config_Prop::Directory, ""); + //Initialize event listening Events_Loop* aLoop = Events_Loop::loop(); aLoop->registerListener(this, Events_Error::errorID()); //!< Listening application errors. @@ -153,12 +190,15 @@ void XGUI_Workshop::startApplication() aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TOHIDE)); registerValidators(); + // Calling of loadCustomProps before activating module is required + // by Config_PropManger to restore user-defined path to plugins + XGUI_Preferences::loadCustomProps(); activateModule(); if (myMainWindow) { myMainWindow->show(); updateCommandStatus(); } - XGUI_Preferences::loadCustomProps(); + onNew(); } @@ -324,7 +364,7 @@ void XGUI_Workshop::processEvent(const std::shared_ptr& theMessa std::shared_ptr anUpdateMsg = std::dynamic_pointer_cast(theMessage); const std::set& aObjList = anUpdateMsg->objects(); - QList aList; + QObjectPtrList aList; std::set::const_iterator aIt; for (aIt = aObjList.cbegin(); aIt != aObjList.cend(); ++aIt) aList.append(*aIt); @@ -335,7 +375,7 @@ void XGUI_Workshop::processEvent(const std::shared_ptr& theMessa std::shared_ptr anUpdateMsg = std::dynamic_pointer_cast(theMessage); const std::set& aObjList = anUpdateMsg->objects(); - QList aList; + QObjectPtrList aList; std::set::const_iterator aIt; for (aIt = aObjList.cbegin(); aIt != aObjList.cend(); ++aIt) aList.append(*aIt); @@ -428,7 +468,6 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptr aObjects = theMsg->objects(); std::set::const_iterator aIt; - QIntList aModes; for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { ObjectPtr aObj = (*aIt); bool aHide = !aObj->data() || !aObj->data()->isValid(); @@ -443,15 +482,14 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptrdisplay(aObj, false); // In order to update presentation if (myOperationMgr->hasOperation()) { ModuleBase_Operation* aOperation = myOperationMgr->currentOperation(); - if (!aOperation->hasObject(aObj)) - if (!myDisplayer->isActive(aObj)) - myDisplayer->activate(aObj, aModes); + if (aOperation->hasObject(aObj) && myDisplayer->isActive(aObj)) + myDisplayer->deactivate(aObj); } } else { if (myOperationMgr->hasOperation()) { ModuleBase_Operation* aOperation = myOperationMgr->currentOperation(); // Display only current operation results if operation has preview - if (aOperation->hasObject(aObj) && aOperation->hasPreview()) { + if (aOperation->hasObject(aObj)/* && aOperation->hasPreview()*/) { myDisplayer->display(aObj, false); // Deactivate object of current operation from selection if (myDisplayer->isActive(aObj)) @@ -535,10 +573,17 @@ void XGUI_Workshop::onOperationStarted() } } - aOperation->setPropertyPanel(myPropertyPanel); myPropertyPanel->setModelWidgets(aWidgets); - if (!aOperation->activateByPreselection()) - myPropertyPanel->activateNextWidget(NULL); + aOperation->setPropertyPanel(myPropertyPanel); + // Do not activate widgets by default if the current operation is editing operation + // Because we don't know which widget is going to be edited. + if ((!aOperation->isEditOperation())) { + if (!aOperation->activateByPreselection()) + myPropertyPanel->activateNextWidget(NULL); + } + // Set final definitions if they are necessary + myModule->propertyPanelDefined(aOperation); + // Widget activation (from the previous method) may commit the current operation // if pre-selection is enougth for it. So we shouldn't update prop panel's title if(myOperationMgr->isCurrentOperation(aOperation)) { @@ -555,6 +600,15 @@ void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation) updateCommandStatus(); hidePropertyPanel(); myPropertyPanel->cleanContent(); + + // Activate objects created by current operation + FeaturePtr aFeature = theOperation->feature(); + myDisplayer->activate(aFeature); + const std::list& aResults = aFeature->results(); + std::list::const_iterator aIt; + for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) { + myDisplayer->activate(*aIt); + } } bool XGUI_Workshop::event(QEvent * theEvent) @@ -598,7 +652,7 @@ void XGUI_Workshop::addFeature(const std::shared_ptr& the salomeConnector()->setDocumentKind(aFeatureId, QString::fromStdString(theMessage->documentKind())); myActionsMgr->addCommand(aAction); - myModule->featureCreated(aAction); + myModule->actionCreated(aAction); } else { XGUI_MainMenu* aMenuBar = myMainWindow->menuObject(); @@ -626,7 +680,7 @@ void XGUI_Workshop::addFeature(const std::shared_ptr& the isUsePropPanel); aCommand->setNestedCommands(aNestedFeatures.split(" ", QString::SkipEmptyParts)); myActionsMgr->addCommand(aCommand); - myModule->featureCreated(aCommand); + myModule->actionCreated(aCommand); } } @@ -1016,6 +1070,9 @@ void XGUI_Workshop::createDockWidgets() aDesktop->addDockWidget(Qt::LeftDockWidgetArea, aObjDock); myPropertyPanel = new XGUI_PropertyPanel(aDesktop); myPropertyPanel->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); + + connect(myPropertyPanel, SIGNAL(noMoreWidgets()), myModule, SLOT(onNoMoreWidgets())); + aDesktop->addDockWidget(Qt::LeftDockWidgetArea, myPropertyPanel); hidePropertyPanel(); // aObjects = mySelector->selection()->selectedObjects(); + QObjectPtrList aObjects = mySelector->selection()->selectedObjects(); if ((theId == "ACTIVATE_PART_CMD") && (aObjects.size() > 0)) { ResultPartPtr aPart = std::dynamic_pointer_cast(aObjects.first()); activatePart(aPart); @@ -1127,6 +1184,11 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked) setDisplayMode(aObjects, XGUI_Displayer::Wireframe); else if (theId == "HIDEALL_CMD") myDisplayer->eraseAll(); + else if (theId == "EDIT_CMD") { + FeaturePtr aFeature = std::dynamic_pointer_cast(aObjects.first()); + if (aFeature) + myModule->editFeature(aFeature); + } } //************************************************************** @@ -1177,7 +1239,7 @@ void XGUI_Workshop::activateLastPart() } //************************************************************** -void XGUI_Workshop::deleteObjects(const QList& theList) +void XGUI_Workshop::deleteObjects(const QObjectPtrList& theList) { QMainWindow* aDesktop = isSalomeMode() ? salomeConnector()->desktop() : myMainWindow; QMessageBox::StandardButton aRes = QMessageBox::warning( @@ -1208,27 +1270,23 @@ void XGUI_Workshop::deleteObjects(const QList& theList) } //************************************************************** -void XGUI_Workshop::showObjects(const QList& theList, bool isVisible) +void XGUI_Workshop::showObjects(const QObjectPtrList& theList, bool isVisible) { foreach (ObjectPtr aObj, theList) { - ResultPtr aRes = std::dynamic_pointer_cast(aObj); - if (aRes) { - if (isVisible) { - myDisplayer->display(aRes, false); - } else { - myDisplayer->erase(aRes, false); - } + if (isVisible) { + myDisplayer->display(aObj, false); + } else { + myDisplayer->erase(aObj, false); } } myDisplayer->updateViewer(); } //************************************************************** -void XGUI_Workshop::showOnlyObjects(const QList& theList) +void XGUI_Workshop::showOnlyObjects(const QObjectPtrList& theList) { - myDisplayer->eraseAll(false); - showObjects(theList, true); + myDisplayer->showOnly(theList); } @@ -1310,7 +1368,7 @@ void XGUI_Workshop::displayGroupResults(DocumentPtr theDoc, std::string theGroup } //************************************************************** -void XGUI_Workshop::setDisplayMode(const QList& theList, int theMode) +void XGUI_Workshop::setDisplayMode(const QObjectPtrList& theList, int theMode) { foreach(ObjectPtr aObj, theList) { myDisplayer->setDisplayMode(aObj, (XGUI_Displayer::DisplayMode)theMode, false); diff --git a/src/XGUI/XGUI_Workshop.h b/src/XGUI/XGUI_Workshop.h index 400465898..95a70579a 100644 --- a/src/XGUI/XGUI_Workshop.h +++ b/src/XGUI/XGUI_Workshop.h @@ -6,11 +6,12 @@ #include #include #include +#include #include #include -#include #include +#include class XGUI_MainWindow; class XGUI_Command; @@ -142,23 +143,26 @@ Q_OBJECT return myModuleConnector; } - //! Returns icon name according to feature Id - static QString featureIcon(const std::string& theId); + //! Returns icon name according to feature + static QIcon featureIcon(const FeaturePtr& theFeature); + + //! Returns icon name according to feature + static std::string featureIconStr(const FeaturePtr& theFeature); //! Activates or deactivates a part //! If PartPtr is Null pointer then PartSet will be activated void activatePart(std::shared_ptr theFeature); //! Delete features - void deleteObjects(const QList& theList); + void deleteObjects(const QObjectPtrList& theList); //! Show the given features in 3d Viewer - void showObjects(const QList& theList, bool isVisible); + void showObjects(const QObjectPtrList& theList, bool isVisible); //! Show the given features in 3d Viewer - void showOnlyObjects(const QList& theList); + void showOnlyObjects(const QObjectPtrList& theList); - void setDisplayMode(const QList& theList, int theMode); + void setDisplayMode(const QObjectPtrList& theList, int theMode); ModuleBase_IModule* module() const { @@ -239,6 +243,7 @@ signals: /// SLOT, that is called after the operation is started. Update workshop state according to /// the started operation, e.g. visualizes the property panel and connect to it. void onOperationStarted(); + /// SLOT, that is called after the operation is stopped. Update workshop state, e.g. /// hides the property panel and udpate the command status. /// \param theOpertion a stopped operation diff --git a/src/XGUI/XGUI_pictures.qrc b/src/XGUI/XGUI_pictures.qrc index 6aaa26762..1e001dc7c 100644 --- a/src/XGUI/XGUI_pictures.qrc +++ b/src/XGUI/XGUI_pictures.qrc @@ -55,6 +55,10 @@ pictures/tile_views.png pictures/new_view.png pictures/edit.png + + pictures/exec_state_failed.png + pictures/exec_state_invalid_parameters.png + pictures/assembly.png pictures/activate.png pictures/delete.png diff --git a/src/XGUI/pictures/exec_state_failed.png b/src/XGUI/pictures/exec_state_failed.png new file mode 100644 index 000000000..738f30371 Binary files /dev/null and b/src/XGUI/pictures/exec_state_failed.png differ diff --git a/src/XGUI/pictures/exec_state_invalid_parameters.png b/src/XGUI/pictures/exec_state_invalid_parameters.png new file mode 100644 index 000000000..c34340c9c Binary files /dev/null and b/src/XGUI/pictures/exec_state_invalid_parameters.png differ