SET(CAS_OCAF ${CAS_TKernel} ${CAS_TKMath} ${CAS_TKCDF} ${CAS_TKLCAF})
SET(CAS_VIEWER ${CAS_TKService} ${CAS_TKV3d} ${CAS_TKG3d} ${CAS_TKGeomBase} ${CAS_TKBRep})
SET(CAS_OCAFVIS ${CAS_TKCAF} ${CAS_TKBRep} ${CAS_TKG2d})
-SET(CAS_MODELER ${CAS_TKG3d} ${CAS_TKGeomBase} ${CAS_TKGeomAlgo} ${CAS_TKBRep} ${CAS_TKTopAlgo} ${CAS_TKG2d})
+SET(CAS_MODELER ${CAS_TKG3d} ${CAS_TKGeomBase} ${CAS_TKGeomAlgo} ${CAS_TKBRep} ${CAS_TKTopAlgo} ${CAS_TKG2d} ${CAS_TKFeat})
# TODO(mpv, vsv) Give a proper name for the following variable
SET(CAS_SHAPE ${CAS_TKShHealing} ${CAS_TKMesh} ${CAS_TKHLR})
--- /dev/null
+
+# Find absolute path to ROOT_DIR
+export ROOT_DIR=$(pwd)/..
+export ROOT_DIR=`cd "${ROOT_DIR}";pwd`
+
+SRC_DIR=${ROOT_DIR}/sources
+
+source ${SRC_DIR}/linux_env.sh
+mkdir -p ${ROOT_DIR}/build-centos
+cd ${ROOT_DIR}/build-centos
+
+export LD_LIBRARY_PATH=${KERNEL_ROOT_DIR}/lib/salome:${LD_LIBRARY_PATH}
+export LightAppConfig=${ROOT_DIR}/install/share/salome/resources/newgeom:${GUI_ROOT_DIR}/share/salome/resources/gui
+
+CMAKE_ARGS="-D_ECLIPSE_VERSION=4.3"
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_BUILD_TYPE=Debug"
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT=ON"
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=${ROOT_DIR}/install"
+CMAKE_ARGS="${CMAKE_ARGS} -DPYTHON_EXECUTABLE=${PYTHONHOME}/bin/python"
+CMAKE_ARGS="${CMAKE_ARGS} -DUSE_TEST_COVERAGE=OFF"
+CMAKE_ARGS="${CMAKE_ARGS} ${SRC_DIR}"
+
+cmake -G "Eclipse CDT4 - Unix Makefiles" ${CMAKE_ARGS}
+
+/misc/dn48/newgeom/common/eclipse-4.4.0/eclipse&
--- /dev/null
+
+# Find absolute path to ROOT_DIR
+export ROOT_DIR=$(pwd)/..
+export ROOT_DIR=`cd "${ROOT_DIR}";pwd`
+
+SRC_DIR=${ROOT_DIR}/sources
+
+export INST_ROOT=/misc/dn48/newgeom/common/SALOME-7.5.1_Debian-6.0
+source ${SRC_DIR}/linux_env.sh
+mkdir -p ${ROOT_DIR}/build-debian
+cd ${ROOT_DIR}/build-debian
+
+export LD_LIBRARY_PATH=${KERNEL_ROOT_DIR}/lib/salome:${LD_LIBRARY_PATH}
+export LightAppConfig=${ROOT_DIR}/install/share/salome/resources/newgeom:${GUI_ROOT_DIR}/share/salome/resources/gui
+
+CMAKE_ARGS="-D_ECLIPSE_VERSION=4.3"
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_BUILD_TYPE=Debug"
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT=ON"
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=${ROOT_DIR}/install"
+CMAKE_ARGS="${CMAKE_ARGS} -DPYTHON_EXECUTABLE=${PYTHONHOME}/bin/python"
+CMAKE_ARGS="${CMAKE_ARGS} -DUSE_TEST_COVERAGE=OFF"
+CMAKE_ARGS="${CMAKE_ARGS} ${SRC_DIR}"
+
+cmake -G "Eclipse CDT4 - Unix Makefiles" ${CMAKE_ARGS}
+
+/misc/dn48/newgeom/common/eclipse-4.4.0/eclipse&
--- /dev/null
+
+# Find absolute path to ROOT_DIR
+export ROOT_DIR=$(pwd)/..
+export ROOT_DIR=`cd "${ROOT_DIR}";pwd`
+
+SRC_DIR=${ROOT_DIR}/sources
+
+source ${SRC_DIR}/linux_env.sh
+mkdir -p ${ROOT_DIR}/build
+cd ${ROOT_DIR}/build
+
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_BUILD_TYPE=Release"
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=${ROOT_DIR}/install"
+CMAKE_ARGS="${CMAKE_ARGS} ${SRC_DIR}"
+
+cmake -G "Unix Makefiles" ${CMAKE_ARGS}
+make
+make install
--- /dev/null
+
+# Find absolute path to ROOT_DIR
+export ROOT_DIR=$(pwd)/..
+export ROOT_DIR=`cd "${ROOT_DIR}";pwd`
+
+SRC_DIR=${ROOT_DIR}/sources
+
+export INST_ROOT=/misc/dn48/newgeom/common/SALOME-7.5.1_Debian-6.0
+source ${SRC_DIR}/linux_env.sh
+mkdir -p ${ROOT_DIR}/build-debian
+cd ${ROOT_DIR}/build-debian
+
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_BUILD_TYPE=Release"
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=${ROOT_DIR}/install"
+CMAKE_ARGS="${CMAKE_ARGS} ${SRC_DIR}"
+
+cmake -G "Unix Makefiles" ${CMAKE_ARGS}
+make
+make install
// Widgets
const static char* WDG_INFO = "label";
const static char* WDG_DOUBLEVALUE = "doublevalue";
+const static char* WDG_INTEGERVALUE = "integervalue";
const static char* WDG_BOOLVALUE = "boolvalue";
const static char* WDG_STRINGVALUE = "stringvalue";
const static char* WDG_MULTISELECTOR = "multi_selector";
bool isCustomized = theDefaultPrs.get() != NULL &&
theDefaultPrs->customisePresentation(theResult, thePrs, theDefaultPrs);
- isCustomized = thePrs->setLineStyle(3);
+ isCustomized = thePrs->setLineStyle(3) || isCustomized;
+ isCustomized = thePrs->setWidth(2) || isCustomized;
return isCustomized;
}
/// default color for a plane
inline static const std::string& DEFAULT_COLOR()
{
- static const std::string CONSTRUCTION_PLANE_COLOR("#32FF32");
+ static const std::string CONSTRUCTION_PLANE_COLOR("150,150,180");
return CONSTRUCTION_PLANE_COLOR;
}
${PROJECT_SOURCE_DIR}/src/GeomAPI
${PROJECT_SOURCE_DIR}/src/GeomAlgoAPI
${CAS_INCLUDE_DIRS}
-)
+)
SET(PROJECT_HEADERS
ExchangePlugin.h
ExchangePlugin_Plugin.h
ExchangePlugin_ImportFeature.h
+ ExchangePlugin_ExportFeature.h
ExchangePlugin_Validators.h
+ ExchangePlugin_Tools.h
)
-
+
SET(PROJECT_SOURCES
ExchangePlugin_Plugin.cpp
ExchangePlugin_ImportFeature.cpp
+ ExchangePlugin_ExportFeature.cpp
ExchangePlugin_Validators.cpp
+ ExchangePlugin_Tools.cpp
)
SET(XML_RESOURCES
#define EXCHANGEPLUGIN_H
#if defined EXCHANGEPLUGIN_EXPORTS
-#if defined WIN32
-#define EXCHANGEPLUGIN_EXPORT __declspec( dllexport )
+# if defined WIN32
+# define EXCHANGEPLUGIN_EXPORT __declspec( dllexport )
+# else
+# define EXCHANGEPLUGIN_EXPORT
+# endif
#else
-#define EXCHANGEPLUGIN_EXPORT
-#endif
-#else
-#if defined WIN32
-#define EXCHANGEPLUGIN_EXPORT __declspec( dllimport )
-#else
-#define EXCHANGEPLUGIN_EXPORT
-#endif
+# if defined WIN32
+# define EXCHANGEPLUGIN_EXPORT __declspec( dllimport )
+# else
+# define EXCHANGEPLUGIN_EXPORT
+# endif
#endif
#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+/*
+ * ExchangePlugin_ExportFeature.cpp
+ *
+ * Created on: May 14, 2015
+ * Author: spo
+ */
+
+#include <ExchangePlugin_ExportFeature.h>
+
+#include <ExchangePlugin_Tools.h>
+
+#include <GeomAlgoAPI_BREPExport.h>
+#include <GeomAlgoAPI_STEPExport.h>
+#include <GeomAlgoAPI_IGESExport.h>
+
+#include <Config_Common.h>
+#include <Config_PropManager.h>
+
+#include <GeomAlgoAPI_CompoundBuilder.h>
+
+#include <GeomAPI_Shape.h>
+
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Object.h>
+#include <ModelAPI_ResultBody.h>
+
+#include <TCollection_AsciiString.hxx>
+#include <TDF_Label.hxx>
+#include <TopoDS_Shape.hxx>
+#include <OSD_Path.hxx>
+
+#include <algorithm>
+#include <iterator>
+#include <string>
+#ifdef _DEBUG
+#include <iostream>
+#include <ostream>
+#endif
+
+ExchangePlugin_ExportFeature::ExchangePlugin_ExportFeature()
+{
+}
+
+ExchangePlugin_ExportFeature::~ExchangePlugin_ExportFeature()
+{
+ // TODO Auto-generated destructor stub
+}
+
+/*
+ * Returns the unique kind of a feature
+ */
+const std::string& ExchangePlugin_ExportFeature::getKind()
+{
+ return ExchangePlugin_ExportFeature::ID();
+}
+
+/*
+ * Request for initialization of data model of the feature: adding all attributes
+ */
+void ExchangePlugin_ExportFeature::initAttributes()
+{
+ data()->addAttribute(ExchangePlugin_ExportFeature::FILE_FORMAT_ID(), ModelAPI_AttributeString::typeId());
+ data()->addAttribute(ExchangePlugin_ExportFeature::FILE_PATH_ID(), ModelAPI_AttributeString::typeId());
+ data()->addAttribute(ExchangePlugin_ExportFeature::SELECTION_LIST_ID(), ModelAPI_AttributeSelectionList::typeId());
+}
+
+/*
+ * Computes or recomputes the results
+ */
+void ExchangePlugin_ExportFeature::execute()
+{
+ AttributeStringPtr aFormatAttr =
+ this->string(ExchangePlugin_ExportFeature::FILE_FORMAT_ID());
+ std::string aFormat = aFormatAttr->value();
+ if (aFormat.empty())
+ return;
+
+ AttributeStringPtr aFilePathAttr =
+ this->string(ExchangePlugin_ExportFeature::FILE_PATH_ID());
+ std::string aFilePath = aFilePathAttr->value();
+ if (aFilePath.empty())
+ return;
+
+ AttributeSelectionListPtr aSelectionListAttr =
+ this->selectionList(ExchangePlugin_ExportFeature::SELECTION_LIST_ID());
+ std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
+ for (int i = 0, aSize = aSelectionListAttr->size(); i < aSize; ++i) {
+ aShapes.push_back(aSelectionListAttr->value(i)->value());
+ }
+ std::shared_ptr<GeomAPI_Shape> aShape =
+ GeomAlgoAPI_CompoundBuilder::compound(aShapes);
+
+ exportFile(aFilePath, aFormat, aShape);
+}
+
+bool ExchangePlugin_ExportFeature::exportFile(const std::string& theFileName,
+ const std::string& theFormat,
+ std::shared_ptr<GeomAPI_Shape> theShape)
+{
+ // retrieve the file and plugin library names
+ TCollection_AsciiString aFileName(theFileName.c_str());
+ TCollection_AsciiString aFormatName(theFormat.c_str());
+
+ // Perform the export
+ TCollection_AsciiString anError;
+ TopoDS_Shape aShape(theShape->impl<TopoDS_Shape>());
+ bool aResult = false;
+ if (aFormatName == "BREP") {
+ aResult = BREPExport::Export(aFileName, aFormatName, aShape, anError);
+ } else if (aFormatName == "STEP") {
+ aResult = STEPExport::Export(aFileName, aFormatName, aShape, anError);
+ } else if (aFormatName.SubString(1, 4) == "IGES") {
+ aResult = IGESExport::Export(aFileName, aFormatName, aShape, anError);
+ } else {
+ anError = TCollection_AsciiString("Unsupported format ") + aFormatName;
+ }
+
+ if (!aResult) {
+ std::string aShapeError =
+ "An error occurred while exporting " + theFileName + ": " + anError.ToCString();
+ setError(aShapeError);
+ return false;
+ }
+
+ return true;
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+#ifndef EXCHANGEPLUGIN_EXPORTFEATURE_H_
+#define EXCHANGEPLUGIN_EXPORTFEATURE_H_
+
+#include <ExchangePlugin.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Result.h>
+
+#include <map>
+
+/**\class ExchangePlugin_ExportFeature
+ * \ingroup Plugins
+ * \brief Feature for export shapes to the external files in CAD formats.
+ *
+ * The set of supported formats is defined in the configuration file.
+ */
+class ExchangePlugin_ExportFeature : public ModelAPI_Feature
+{
+public:
+ inline static const std::string& ID()
+ {
+ static const std::string MY_EXPORT_ID("Export");
+ return MY_EXPORT_ID;
+ }
+ /// attribute name of file format
+ inline static const std::string& FILE_FORMAT_ID()
+ {
+ static const std::string MY_FILE_FORMAT_ID("export_file_format");
+ return MY_FILE_FORMAT_ID;
+ }
+ /// attribute name of file path
+ inline static const std::string& FILE_PATH_ID()
+ {
+ static const std::string MY_FILE_PATH_ID("export_file_selector");
+ return MY_FILE_PATH_ID;
+ }
+ /// attribute name of selection list
+ inline static const std::string& SELECTION_LIST_ID()
+ {
+ static const std::string MY_SELECTION_LIST_ID("selection_list");
+ return MY_SELECTION_LIST_ID;
+ }
+ /// default constructor
+ EXCHANGEPLUGIN_EXPORT ExchangePlugin_ExportFeature();
+ /// default destructor
+ EXCHANGEPLUGIN_EXPORT virtual ~ExchangePlugin_ExportFeature();
+
+ /// Request for initialization of data model of the feature: adding all attributes
+ EXCHANGEPLUGIN_EXPORT virtual void initAttributes();
+
+ /// Returns the unique kind of a feature
+ EXCHANGEPLUGIN_EXPORT virtual const std::string& getKind();
+
+ /// Computes or recomputes the results
+ EXCHANGEPLUGIN_EXPORT virtual void execute();
+
+ /// Reimplemented from ModelAPI_Feature::isMacro(). Returns true.
+ EXCHANGEPLUGIN_EXPORT virtual bool isMacro() const { return true; }
+
+ /// Reimplemented from ModelAPI_Feature::isPreviewNeeded(). Returns false.
+ EXCHANGEPLUGIN_EXPORT virtual bool isPreviewNeeded() const { return false; }
+
+protected:
+ /// Performs the export of the file
+ EXCHANGEPLUGIN_EXPORT bool exportFile(const std::string& theFileName,
+ const std::string& theFormat,
+ std::shared_ptr<GeomAPI_Shape> theShape);
+};
+
+#endif /* EXPORT_EXPORTFEATURE_H_ */
#include <ExchangePlugin_ImportFeature.h>
#include <GeomAlgoAPI_BREPImport.h>
#include <GeomAlgoAPI_STEPImport.h>
+#include <GeomAlgoAPI_IGESImport.h>
#include <GeomAPI_Shape.h>
#include <Config_Common.h>
*/
void ExchangePlugin_ImportFeature::execute()
{
- AttributeStringPtr aFilePathAttr = std::dynamic_pointer_cast<ModelAPI_AttributeString>(
- data()->attribute(ExchangePlugin_ImportFeature::FILE_PATH_ID()));
+ AttributeStringPtr aFilePathAttr =
+ this->string(ExchangePlugin_ImportFeature::FILE_PATH_ID());
std::string aFilePath = aFilePathAttr->value();
- if(aFilePath.empty())
+ if (aFilePath.empty())
return;
+
importFile(aFilePath);
}
bool ExchangePlugin_ImportFeature::importFile(const std::string& theFileName)
{
// retrieve the file and plugin library names
- TCollection_AsciiString aFileName (theFileName.c_str());
+ TCollection_AsciiString aFileName(theFileName.c_str());
OSD_Path aPath(aFileName);
- TCollection_AsciiString aFormatName = aPath.Extension();
+ TCollection_AsciiString anExtension = aPath.Extension();
// ".brep" -> "BREP", TCollection_AsciiString are numbered from 1
- aFormatName = aFormatName.SubString(2, aFormatName.Length());
- aFormatName.UpperCase();
+ anExtension = anExtension.SubString(2, anExtension.Length());
+ anExtension.UpperCase();
// Perform the import
TCollection_AsciiString anError;
- TDF_Label anUnknownLabel = TDF_Label();
TopoDS_Shape aShape;
- if (aFormatName == "BREP") {
- aShape = BREPImport::Import(aFileName, aFormatName, anError, anUnknownLabel);
- } else if (aFormatName == "STEP") {
- aShape = STEPImport::Import(aFileName, aFormatName, anError, anUnknownLabel);
+ if (anExtension == "BREP") {
+ aShape = BREPImport::Import(aFileName, anExtension, anError);
+ } else if (anExtension == "STEP" || anExtension == "STP") {
+ aShape = STEPImport::Import(aFileName, anExtension, anError);
+ } else if (anExtension == "IGES") {
+ aShape = IGESImport::Import(aFileName, anExtension, anError);
}
// Check if shape is valid
if ( aShape.IsNull() ) {
- const static std::string aShapeError =
+ const static std::string aShapeError =
"An error occurred while importing " + theFileName + ": " + anError.ToCString();
setError(aShapeError);
return false;
//============================================================================
void ExchangePlugin_ImportFeature::loadNamingDS(
- std::shared_ptr<GeomAPI_Shape> theGeomShape,
- std::shared_ptr<ModelAPI_ResultBody> theResultBody)
-{
+ std::shared_ptr<GeomAPI_Shape> theGeomShape,
+ std::shared_ptr<ModelAPI_ResultBody> theResultBody)
+{
//load result
theResultBody->store(theGeomShape);
-
+
int aTag(1);
std::string aNameMS = "Shape";
theResultBody->loadFirstLevel(theGeomShape, aNameMS, aTag);
- //std::string aNameDE = "DiscEdges";
- //theResultBody->loadDisconnectedEdges(theGeomShape, aNameDE, aTag);
- //std::string aNameDV = "DiscVertexes";
- //theResultBody->loadDisconnectedVertexes(theGeomShape, aNameDV, aTag);
}
}
protected:
- /// POerforms the import of the file
+ /// Performs the import of the file
EXCHANGEPLUGIN_EXPORT bool importFile(const std::string& theFileName);
private:
/// Loads Naming data structure to the document
void loadNamingDS(std::shared_ptr<GeomAPI_Shape> theGeomShape,
- std::shared_ptr<ModelAPI_ResultBody> theResultBody);
+ std::shared_ptr<ModelAPI_ResultBody> theResultBody);
};
#endif /* IMPORT_IMPORTFEATURE_H_ */
#include <ExchangePlugin_Plugin.h>
#include <ExchangePlugin_ImportFeature.h>
+#include <ExchangePlugin_ExportFeature.h>
#include <ExchangePlugin_Validators.h>
#include <Config_PropManager.h>
ModelAPI_ValidatorsFactory* aFactory = aSession->validators();
aFactory->registerValidator("ExchangePlugin_ImportFormat",
new ExchangePlugin_ImportFormatValidator);
-
- // register construction properties
- //Config_PropManager::registerProp("Visualization", "import_feature_color", "Imported feature color",
- // Config_Prop::Color, ExchangePlugin_ImportFeature::DEFAULT_COLOR());
+ aFactory->registerValidator("ExchangePlugin_ExportFormat",
+ new ExchangePlugin_ExportFormatValidator);
}
FeaturePtr ExchangePlugin_Plugin::createFeature(string theFeatureID)
{
if (theFeatureID == ExchangePlugin_ImportFeature::ID()) {
return FeaturePtr(new ExchangePlugin_ImportFeature);
+ } else
+ if (theFeatureID == ExchangePlugin_ExportFeature::ID()) {
+ return FeaturePtr(new ExchangePlugin_ExportFeature);
}
// feature of such kind is not found
return FeaturePtr();
--- /dev/null
+/*
+ * ExchangePlugin_Tools.cpp
+ *
+ * Created on: May 15, 2015
+ * Author: spo
+ */
+
+#include <ExchangePlugin_Tools.h>
+
+#include <sstream>
+
+std::list<std::string> ExchangePlugin_Tools::split(const std::string& theString, char theDelimiter)
+{
+ std::list<std::string> theResult;
+ std::istringstream aStream(theString);
+ std::string aSection;
+ while (std::getline(aStream, aSection, theDelimiter))
+ theResult.push_back(aSection);
+ return theResult;
+}
--- /dev/null
+/*
+ * ExchangePlugin_Tools.h
+ *
+ * Created on: May 15, 2015
+ * Author: spo
+ */
+
+#ifndef EXCHANGEPLUGIN_TOOLS_H_
+#define EXCHANGEPLUGIN_TOOLS_H_
+
+#include <ExchangePlugin.h>
+
+#include <list>
+#include <string>
+
+/**\class ExchangePlugin_Tools
+ * \ingroup Plugins
+ * \brief Internal tools for the plugin.
+ */
+class EXCHANGEPLUGIN_EXPORT ExchangePlugin_Tools {
+public:
+ /// Splits theString using theDelimiter.
+ static std::list<std::string> split(const std::string& theString,
+ char theDelimiter);
+
+};
+
+#endif /* EXCHANGEPLUGIN_TOOLS_H_ */
// Author: Vitaly SMETANNIKOV
#include <ExchangePlugin_Validators.h>
+
+#include <ExchangePlugin_Tools.h>
+
#include <ModelAPI_Feature.h>
#include <ModelAPI_Object.h>
#include <ModelAPI_Session.h>
#include <string>
#include <algorithm>
-bool ExchangePlugin_ImportFormatValidator::parseFormats(const std::list<std::string>& theArguments,
- std::list<std::string>& outFormats)
+bool ExchangePlugin_FormatValidator::parseFormats(const std::list<std::string>& theArguments,
+ std::list<std::string>& outFormats)
{
std::list<std::string>::const_iterator it = theArguments.begin();
bool result = true;
result = false;
continue;
}
- std::string aFormat = anArg.substr(0, aSepPos);
- std::transform(aFormat.begin(), aFormat.end(), aFormat.begin(), toupper);
- outFormats.push_back(aFormat);
+ std::string aFormats = anArg.substr(0, aSepPos);
+ std::transform(aFormats.begin(), aFormats.end(), aFormats.begin(), toupper);
+ std::list<std::string> aFormatList = ExchangePlugin_Tools::split(aFormats, '|');
+ outFormats.insert(outFormats.end(), aFormatList.begin(), aFormatList.end());
}
return result;
}
-bool ExchangePlugin_ImportFormatValidator::isValid(const AttributePtr& theAttribute,
- const std::list<std::string>& theArguments) const
+bool ExchangePlugin_FormatValidator::isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments) const
{
- SessionPtr aMgr = ModelAPI_Session::get();
- ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
- if (theAttribute->isInitialized()) {
- const AttributeStringPtr aStrAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeString>(theAttribute);
- if(!aStrAttr)
- return false;
- std::string aFileName = aStrAttr->value();
- if (!aFileName.empty()) {
- std::list<std::string> aFormats;
- ExchangePlugin_ImportFormatValidator::parseFormats(theArguments, aFormats);
- std::list<std::string>::const_iterator itFormats = aFormats.begin();
- size_t aFileNameLen = aFileName.length();
- std::transform(aFileName.begin(), aFileName.end(), aFileName.begin(), toupper);
- // Is file name ends with the format
- for (; itFormats != aFormats.end(); ++itFormats) {
- size_t aFormatBeginPos = aFileNameLen - (*itFormats).length();
- if (aFileName.compare(aFormatBeginPos, std::string::npos, *itFormats) == 0) {
- return true;
- }
- }
+ if (!theAttribute->isInitialized())
+ return false;
+
+ const AttributeStringPtr aStrAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeString>(theAttribute);
+ if (!aStrAttr)
+ return false;
+
+ std::string aFileName = aStrAttr->value();
+ if (aFileName.empty())
+ return false;
+
+ std::list<std::string> aFormats;
+ ExchangePlugin_FormatValidator::parseFormats(theArguments, aFormats);
+ std::list<std::string>::const_iterator itFormats = aFormats.begin();
+ size_t aFileNameLen = aFileName.length();
+ std::transform(aFileName.begin(), aFileName.end(), aFileName.begin(), toupper);
+ // Is file name ends with the format
+ for (; itFormats != aFormats.end(); ++itFormats) {
+ size_t aFormatBeginPos = aFileNameLen - (*itFormats).length();
+ if (aFileName.compare(aFormatBeginPos, std::string::npos, *itFormats) == 0) {
+ return true;
}
}
return false;
}
-
* about which formats are supported and the extension of the associated files.
* This validator filters out files that are out of this description.
*/
-class ExchangePlugin_ImportFormatValidator : public ModelAPI_AttributeValidator
+class ExchangePlugin_FormatValidator : public ModelAPI_AttributeValidator
{
/**
- * Parses input arguments "BREP:BREPImport", "STEP:STEPImport"
- * into list of file formats "BREP","STEP"
+ * Parses input arguments "BREP:BREPImport", "STEP|STP:STEPImport"
+ * into list of file formats "BREP","STEP","STP"
* and list of corresponding plugins: "BREPImport", "STEPImport"
*/
static bool parseFormats(const std::list<std::string>& theArguments,
- std::list<std::string>& outFormats);
+ std::list<std::string>& outFormats);
public:
/**
* Returns true is the file-name attribute correctly corresponds to the set of
*/
virtual bool isValid(const AttributePtr& theAttribute,
const std::list<std::string>& theArguments) const;
+};
+class ExchangePlugin_ImportFormatValidator : public ExchangePlugin_FormatValidator
+{
+};
+
+class ExchangePlugin_ExportFormatValidator : public ExchangePlugin_FormatValidator
+{
};
<workbench id="Features" document="Part">
<group id="Exchange">
<feature id="Import" title="Import" tooltip="Import a file" icon=":icons/import.png">
- <file_selector
- id="import_file_selector"
- title="Import file"
- path="">
- <validator id="ExchangePlugin_ImportFormat" parameters="BREP:BREPImport,STEP:STEPImport" />
+ <file_selector id="import_file_selector" title="Import file" path="">
+ <validator id="ExchangePlugin_ImportFormat" parameters="BREP:BREP,STEP|STP:STEP,IGES:IGES" />
</file_selector>
</feature>
+ <feature id="Export" title="Export" tooltip="Export to file" icon=":icons/export.png">
+ <export_file_selector id="export_file_selector" type="save" title="Export file" path="">
+ <validator id="ExchangePlugin_ExportFormat" parameters="BREP:BREP,STEP|STP:STEP,IGES:IGES-5.1,IGES:IGES-5.3" />
+ </export_file_selector>
+ <multi_selector id="selection_list" tooltip="Select a set of objects" type_choice="Vertices Edges Faces Solids" />
+ </feature>
</group>
</workbench>
</plugin>
\ No newline at end of file
#include <ModelAPI_AttributeReference.h>
#include <ModelAPI_AttributeInteger.h>
#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_AttributeSelectionList.h>
#include <GeomAlgoAPI_Boolean.h>
using namespace std;
+//#define DEBUG_ONE_OBJECT
+
#define FACE 4
#define _MODIFY_TAG 1
#define _DELETED_TAG 2
void FeaturesPlugin_Boolean::initAttributes()
{
data()->addAttribute(FeaturesPlugin_Boolean::TYPE_ID(), ModelAPI_AttributeInteger::typeId());
+
+#ifdef DEBUG_ONE_OBJECT
data()->addAttribute(FeaturesPlugin_Boolean::OBJECT_ID(), ModelAPI_AttributeReference::typeId());
+#else
+ AttributeSelectionListPtr aSelection =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
+ FeaturesPlugin_Boolean::OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
+ // extrusion works with faces always
+ aSelection->setSelectionType("SOLID");
+#endif
+
+#ifdef DEBUG_ONE_OBJECT
data()->addAttribute(FeaturesPlugin_Boolean::TOOL_ID(), ModelAPI_AttributeReference::typeId());
+#else
+ aSelection = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
+ FeaturesPlugin_Boolean::TOOL_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
+ // extrusion works with faces always
+ aSelection->setSelectionType("SOLID");
+#endif
}
std::shared_ptr<GeomAPI_Shape> FeaturesPlugin_Boolean::getShape(const std::string& theAttrName)
if (!aTypeAttr)
return;
int aType = aTypeAttr->value();
-
+#ifdef DEBUG_ONE_OBJECT
std::shared_ptr<GeomAPI_Shape> anObject = this->getShape(FeaturesPlugin_Boolean::OBJECT_ID());
+#else
+ std::shared_ptr<GeomAPI_Shape> anObject;
+ {
+ AttributeSelectionListPtr anObjects = selectionList(FeaturesPlugin_Boolean::OBJECT_LIST_ID());
+ if (anObjects->size() == 0)
+ return;
+
+ // Getting bounding planes.
+ std::shared_ptr<ModelAPI_AttributeSelection> anObjRef = anObjects->value(0);
+ if (!anObjRef.get())
+ return;
+ anObject = std::dynamic_pointer_cast<GeomAPI_Shape>(anObjRef->value());
+ }
+#endif
if (!anObject)
return;
+#ifdef DEBUG_ONE_OBJECT
std::shared_ptr<GeomAPI_Shape> aTool = this->getShape(FeaturesPlugin_Boolean::TOOL_ID());
+#else
+ std::shared_ptr<GeomAPI_Shape> aTool;
+ {
+ AttributeSelectionListPtr anObjects = selectionList(FeaturesPlugin_Boolean::TOOL_LIST_ID());
+ if (anObjects->size() == 0)
+ return;
+
+ // Getting bounding planes.
+ std::shared_ptr<ModelAPI_AttributeSelection> anObjRef = anObjects->value(0);
+ if (!anObjRef.get())
+ return;
+ aTool = std::dynamic_pointer_cast<GeomAPI_Shape>(anObjRef->value());
+ }
+#endif
if (!aTool)
return;
return MY_ID;
}
/// attribute name of referenced object
+ inline static const std::string& OBJECT_LIST_ID()
+ {
+ static const std::string MY_OBJECT_LIST_ID("main_objects");
+ return MY_OBJECT_LIST_ID;
+ }
+ /// attribute name of referenced object
inline static const std::string& OBJECT_ID()
{
static const std::string MY_OBJECT_ID("main_object");
static const std::string MY_TOOL_ID("tool_object");
return MY_TOOL_ID;
}
+ /// attribute name of tool object
+ inline static const std::string& TOOL_LIST_ID()
+ {
+ static const std::string MY_TOOL_LIST_ID("tool_objects");
+ return MY_TOOL_LIST_ID;
+ }
/// attribute name of operation type
inline static const std::string& TYPE_ID()
{
#include "FeaturesPlugin_Extrusion.h"
#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
#include <ModelAPI_Document.h>
#include <ModelAPI_Data.h>
#include <ModelAPI_ResultConstruction.h>
#include <ModelAPI_AttributeSelection.h>
#include <ModelAPI_AttributeSelectionList.h>
#include <ModelAPI_AttributeBoolean.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeReference.h>
+#include <GeomAPI_Pln.h>
+#include <GeomAPI_XYZ.h>
#include <GeomAlgoAPI_Extrusion.h>
+#include <GeomAlgoAPI_FaceBuilder.h>
+#include <GeomAlgoAPI_Prism.h>
using namespace std;
#define _LATERAL_TAG 1
FeaturesPlugin_Extrusion::LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
// extrusion works with faces always
aSelection->setSelectionType("FACE");
- data()->addAttribute(FeaturesPlugin_Extrusion::SIZE_ID(), ModelAPI_AttributeDouble::typeId());
- data()->addAttribute(FeaturesPlugin_Extrusion::REVERSE_ID(), ModelAPI_AttributeBoolean::typeId());
+
+ data()->addAttribute(FeaturesPlugin_Extrusion::TO_SIZE_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(FeaturesPlugin_Extrusion::FROM_SIZE_ID(), ModelAPI_AttributeDouble::typeId());
+
+ //data()->addAttribute(FeaturesPlugin_Extrusion::AXIS_OBJECT_ID(), ModelAPI_AttributeReference::typeId());
+
+ data()->addAttribute(FeaturesPlugin_Extrusion::FROM_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
+ data()->addAttribute(FeaturesPlugin_Extrusion::TO_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
+
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FeaturesPlugin_Extrusion::FROM_OBJECT_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FeaturesPlugin_Extrusion::TO_OBJECT_ID());
}
void FeaturesPlugin_Extrusion::execute()
{
AttributeSelectionListPtr aFaceRefs = selectionList(FeaturesPlugin_Extrusion::LIST_ID());
+ std::shared_ptr<GeomAPI_Shape> aFromShape(new GeomAPI_Shape);
+ std::shared_ptr<GeomAPI_Shape> aToShape(new GeomAPI_Shape);
+
+ // Getting bounding planes.
+ std::shared_ptr<ModelAPI_AttributeSelection> anObjRef = selection(FeaturesPlugin_Extrusion::FROM_OBJECT_ID());
+ if (anObjRef) {
+ aFromShape = std::dynamic_pointer_cast<GeomAPI_Shape>(anObjRef->value());
+ }
+ anObjRef = selection(FeaturesPlugin_Extrusion::TO_OBJECT_ID());
+ if (anObjRef) {
+ aToShape = std::dynamic_pointer_cast<GeomAPI_Shape>(anObjRef->value());
+ }
+
+ // Getting sizes.
+ double aFromSize = real(FeaturesPlugin_Extrusion::FROM_SIZE_ID())->value();
+ double aToSize = real(FeaturesPlugin_Extrusion::TO_SIZE_ID())->value();
+
// for each selected face generate a result
int anIndex = 0, aResultIndex = 0;
for(; anIndex < aFaceRefs->size(); anIndex++) {
setError(aContextError);
break;
}
- double aSize = real(FeaturesPlugin_Extrusion::SIZE_ID())->value();
- if (boolean(FeaturesPlugin_Extrusion::REVERSE_ID())->value())
- aSize = -aSize;
std::shared_ptr<GeomAPI_Shape> aValueFace = aFaceRef->value();
int aFacesNum = -1; // this mean that "aFace" is used
for(int aFaceIndex = 0; aFaceIndex < aFacesNum || aFacesNum == -1; aFaceIndex++) {
ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
- std::shared_ptr<GeomAPI_Shape> aFace;
+ std::shared_ptr<GeomAPI_Shape> aBaseShape;
if (aFacesNum == -1) {
- aFace = aValueFace;
+ aBaseShape = aValueFace;
} else {
- aFace = std::dynamic_pointer_cast<GeomAPI_Shape>(aConstruction->face(aFaceIndex));
+ aBaseShape = std::dynamic_pointer_cast<GeomAPI_Shape>(aConstruction->face(aFaceIndex));
+ }
+
+ // If bounding faces was not set creating them.
+ std::shared_ptr<GeomAPI_Face> aBaseFace(new GeomAPI_Face(aBaseShape));
+ std::shared_ptr<GeomAPI_Pln> aBasePlane = aBaseFace->getPlane();
+ std::shared_ptr<GeomAPI_Dir> aBaseDir = aBasePlane->direction();
+ std::shared_ptr<GeomAPI_Pnt> aBaseLoc = aBasePlane->location();
+
+ if(!aFromShape) {
+ aFromShape = GeomAlgoAPI_FaceBuilder::plane(aBaseLoc, aBaseDir);
+ }
+ if(!aToShape) {
+ aToShape = GeomAlgoAPI_FaceBuilder::plane(aBaseLoc, aBaseDir);
}
- GeomAlgoAPI_Extrusion aFeature(aFace, aSize);
+
+ // Moving bounding faces according to "from" and "to" sizes.
+ std::shared_ptr<GeomAPI_Face> aFromFace(new GeomAPI_Face(aFromShape));
+ std::shared_ptr<GeomAPI_Pln> aFromPlane = aFromFace->getPlane();
+ std::shared_ptr<GeomAPI_Pnt> aFromLoc = aFromPlane->location();
+ std::shared_ptr<GeomAPI_Dir> aFromDir = aFromPlane->direction();
+
+ std::shared_ptr<GeomAPI_Face> aToFace(new GeomAPI_Face(aToShape));
+ std::shared_ptr<GeomAPI_Pln> aToPlane = aToFace->getPlane();
+ std::shared_ptr<GeomAPI_Pnt> aToLoc = aToPlane->location();
+ std::shared_ptr<GeomAPI_Dir> aToDir = aToPlane->direction();
+
+ bool aSign = aFromLoc->xyz()->dot(aBaseDir->xyz()) > aToLoc->xyz()->dot(aBaseDir->xyz());
+
+ std::shared_ptr<GeomAPI_Pnt> aFromPnt(new GeomAPI_Pnt(aFromLoc->xyz()->added(aBaseDir->xyz()->multiplied(aSign ? aFromSize : -aFromSize))));
+ aFromShape = GeomAlgoAPI_FaceBuilder::plane(aFromPnt, aFromDir);
+
+ std::shared_ptr<GeomAPI_Pnt> aToPnt(new GeomAPI_Pnt(aToLoc->xyz()->added(aBaseDir->xyz()->multiplied(aSign ? -aToSize : aToSize))));
+ aToShape = GeomAlgoAPI_FaceBuilder::plane(aToPnt, aToDir);
+
+ //GeomAlgoAPI_Extrusion aFeature(aFace, aFromSize);
+ GeomAlgoAPI_Prism aFeature(aBaseShape, aFromShape, aToShape);
if(!aFeature.isDone()) {
- static const std::string aFeatureError = "Extrusion algorithm failed";
+ static const std::string aFeatureError = "Extrusion algorithm failed";
setError(aFeatureError);
break;
}
// Check if shape is valid
- if (aFeature.shape()->isNull()) {
- static const std::string aShapeError = "Resulting shape is Null";
+ if(aFeature.shape()->isNull()) {
+ static const std::string aShapeError = "Resulting shape is Null";
setError(aShapeError);
break;
}
if(!aFeature.isValid()) {
- std::string aFeatureError = "Warning: resulting shape is not valid";
+ std::string aFeatureError = "Warning: resulting shape is not valid";
setError(aFeatureError);
break;
- }
+ }
//LoadNamingDS
- LoadNamingDS(aFeature, aResultBody, aFace, aContext);
+ LoadNamingDS(aFeature, aResultBody, aBaseShape, aContext);
setResult(aResultBody, aResultIndex);
aResultIndex++;
}
//============================================================================
-void FeaturesPlugin_Extrusion::LoadNamingDS(GeomAlgoAPI_Extrusion& theFeature,
- std::shared_ptr<ModelAPI_ResultBody> theResultBody,
- std::shared_ptr<GeomAPI_Shape> theBasis,
- std::shared_ptr<GeomAPI_Shape> theContext)
-{
-
-
+void FeaturesPlugin_Extrusion::LoadNamingDS(GeomAlgoAPI_Prism& theFeature,
+ std::shared_ptr<ModelAPI_ResultBody> theResultBody,
+ std::shared_ptr<GeomAPI_Shape> theBasis,
+ std::shared_ptr<GeomAPI_Shape> theContext)
+{
//load result
if(theBasis->isEqual(theContext))
theResultBody->store(theFeature.shape());
else
- theResultBody->storeGenerated(theContext, theFeature.shape());
+ theResultBody->storeGenerated(theContext, theFeature.shape());
GeomAPI_DataMapOfShapeShape* aSubShapes = new GeomAPI_DataMapOfShapeShape();
theFeature.mapOfShapes(*aSubShapes);
//Insert bottom face
std::string aBotName = "BottomFace";
- std::shared_ptr<GeomAPI_Shape> aBottomFace = theFeature.firstShape();
- if (!aBottomFace->isNull()) {
- if (aSubShapes->isBound(aBottomFace)) {
- aBottomFace = aSubShapes->find(aBottomFace);
- }
+ std::shared_ptr<GeomAPI_Shape> aBottomFace = theFeature.firstShape();
+ if(!aBottomFace->isNull()) {
+ if(aSubShapes->isBound(aBottomFace)) {
+ aBottomFace = aSubShapes->find(aBottomFace);
+ }
theResultBody->generated(aBottomFace, aBotName, _FIRST_TAG);
}
-
-
//Insert top face
std::string aTopName = "TopFace";
std::shared_ptr<GeomAPI_Shape> aTopFace = theFeature.lastShape();
if (!aTopFace->isNull()) {
- if (aSubShapes->isBound(aTopFace)) {
- aTopFace = aSubShapes->find(aTopFace);
+ if (aSubShapes->isBound(aTopFace)) {
+ aTopFace = aSubShapes->find(aTopFace);
}
theResultBody->generated(aTopFace, aTopName, _LAST_TAG);
}
-
}
//============================================================================
#include <ModelAPI_Feature.h>
#include <ModelAPI_ResultBody.h>
#include <GeomAlgoAPI_Extrusion.h>
+#include <GeomAlgoAPI_Prism.h>
#include <GeomAPI_Shape.h>
/**\class FeaturesPlugin_Extrusion
* \brief Feature for creation of extrusion from the planar face.
*
* Extrusion creates the lateral faces based on edges of the base face and
- * the top face equal to the base face. Direction of extrusion is taken from the face
- * plane, but can be corrected by the "reverse" flag.
+ * the top and bottom faces equal to the base face or this faces can be projection on the
+ * bounding planes if they were set. Direction of extrusion is taken from the face
+ * plane or if the bounding faces were set then it will be from the bottom to the top plane.
*/
class FeaturesPlugin_Extrusion : public ModelAPI_Feature
{
return MY_GROUP_LIST_ID;
}
+ /// attribute name of an object to which the extrusion grows
+ inline static const std::string& AXIS_OBJECT_ID()
+ {
+ static const std::string MY_TO_OBJECT_ID("axis_object");
+ return MY_TO_OBJECT_ID;
+ }
+
/// attribute name of extrusion size
- inline static const std::string& SIZE_ID()
+ inline static const std::string& TO_SIZE_ID()
{
- static const std::string MY_SIZE_ID("size");
- return MY_SIZE_ID;
+ static const std::string MY_TO_SIZE_ID("to_size");
+ return MY_TO_SIZE_ID;
}
- /// attribute name of reverse direction
- inline static const std::string& REVERSE_ID()
+
+ /// attribute name of extrusion size
+ inline static const std::string& FROM_SIZE_ID()
+ {
+ static const std::string MY_FROM_SIZE_ID("from_size");
+ return MY_FROM_SIZE_ID;
+ }
+
+ /// attribute name of an object to which the extrusion grows
+ inline static const std::string& TO_OBJECT_ID()
+ {
+ static const std::string MY_TO_OBJECT_ID("to_object");
+ return MY_TO_OBJECT_ID;
+ }
+
+ /// attribute name of tool object
+ inline static const std::string& FROM_OBJECT_ID()
{
- static const std::string MY_REVERSE_ID("reverse");
- return MY_REVERSE_ID;
+ static const std::string MY_FROM_OBJECT_ID("from_object");
+ return MY_FROM_OBJECT_ID;
}
/// Returns the kind of a feature
FeaturesPlugin_Extrusion();
private:
/// Load Naming data structure of the feature to the document
- void LoadNamingDS(GeomAlgoAPI_Extrusion& theFeature, std::shared_ptr<ModelAPI_ResultBody> theResultBody,
- std::shared_ptr<GeomAPI_Shape> theBasis,
- std::shared_ptr<GeomAPI_Shape> theContext);
+ void LoadNamingDS(GeomAlgoAPI_Prism& theFeature, std::shared_ptr<ModelAPI_ResultBody> theResultBody,
+ std::shared_ptr<GeomAPI_Shape> theBasis,
+ std::shared_ptr<GeomAPI_Shape> theContext);
/// Set an empty shape to the result of extrusion
void clearResult();
anExtrusionFt = aPart.addFeature("Extrusion")
anExtrusionFt.selectionList("base").append(
aSketchResult, aSketchFaces[0])
- anExtrusionFt.real("size").setValue(50)
- anExtrusionFt.boolean("reverse").setValue(False)
+ anExtrusionFt.real("from_size").setValue(0)
+ anExtrusionFt.real("to_size").setValue(50)
anExtrusionFt.execute()
extrudedObjects.append(modelAPI_ResultBody(anExtrusionFt.firstResult()))
aSession.finishOperation()
class FeaturesPlugin_Extrusion : public ModelAPI_Feature
static const std::string MY_EXTRUSION_ID("Extrusion");
- static const std::string MY_FACE_ID("base");
- static const std::string MY_SIZE_ID("size");
- static const std::string MY_REVERSE_ID("reverse");
-
- data()->addAttribute(FeaturesPlugin_Extrusion::FACE_ID(), ModelAPI_AttributeSelection::typeId());
- data()->addAttribute(FeaturesPlugin_Extrusion::SIZE_ID(), ModelAPI_AttributeDouble::typeId());
- data()->addAttribute(FeaturesPlugin_Extrusion::REVERSE_ID(), ModelAPI_AttributeBoolean::typeId());
+ static const std::string LIST_ID("base");
+ static const std::string MY_TO_SIZE_ID("to_size");
+ static const std::string MY_FROM_SIZE_ID("from_size");
+ static const std::string MY_TO_OBJECT_ID("to_object");
+ static const std::string MY_FROM_OBJECT_ID("from_object");
+
+ data()->addAttribute(FeaturesPlugin_Extrusion::LIST_ID(), ModelAPI_AttributeSelection::typeId());
+ data()->addAttribute(FeaturesPlugin_Extrusion::FROM_SIZE_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(FeaturesPlugin_Extrusion::TO_SIZE_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(FeaturesPlugin_Extrusion::FROM_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
+ data()->addAttribute(FeaturesPlugin_Extrusion::TO_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
"""
#=========================================================================
# Initialization of the test
from GeomDataAPI import *
from GeomAlgoAPI import *
from GeomAPI import *
+import math
__updated__ = "2014-12-16"
# Create a sketch circle to extrude
#=========================================================================
aSession.startOperation()
-aSketchFeature = featureToCompositeFeature(aPart.addFeature("Sketch"))
-origin = geomDataAPI_Point(aSketchFeature.attribute("Origin"))
+aCircleSketchFeature = featureToCompositeFeature(aPart.addFeature("Sketch"))
+origin = geomDataAPI_Point(aCircleSketchFeature.attribute("Origin"))
origin.setValue(0, 0, 0)
-dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX"))
+dirx = geomDataAPI_Dir(aCircleSketchFeature.attribute("DirX"))
dirx.setValue(1, 0, 0)
-norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm"))
+norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm"))
norm.setValue(0, 0, 1)
# Create circle
-aSketchCircle = aSketchFeature.addFeature("SketchCircle")
+aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
aCircleRadius = aSketchCircle.real("CircleRadius")
anCircleCentr.setValue(50., 50)
# Make extrusion on circle
#=========================================================================
# Build shape from sketcher results
-aSketchResult = aSketchFeature.firstResult()
-aSketchEdges = modelAPI_ResultConstruction(aSketchResult).shape()
-origin = geomDataAPI_Point(aSketchFeature.attribute("Origin")).pnt()
-dirX = geomDataAPI_Dir(aSketchFeature.attribute("DirX")).dir()
-norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm")).dir()
-aSketchFaces = ShapeList()
+aCircleSketchResult = aCircleSketchFeature.firstResult()
+aCircleSketchEdges = modelAPI_ResultConstruction(aCircleSketchResult).shape()
+origin = geomDataAPI_Point(aCircleSketchFeature.attribute("Origin")).pnt()
+dirX = geomDataAPI_Dir(aCircleSketchFeature.attribute("DirX")).dir()
+norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm")).dir()
+aCircleSketchFaces = ShapeList()
GeomAlgoAPI_SketchBuilder.createFaces(
- origin, dirX, norm, aSketchEdges, aSketchFaces)
-assert (len(aSketchFaces) > 0)
-assert (aSketchFaces[0] is not None)
+ origin, dirX, norm, aCircleSketchEdges, aCircleSketchFaces)
+assert (len(aCircleSketchFaces) > 0)
+assert (aCircleSketchFaces[0] is not None)
# Create extrusion
aSession.startOperation()
anExtrusionFt = aPart.addFeature("Extrusion")
assert (anExtrusionFt.getKind() == "Extrusion")
# selection type FACE=4
anExtrusionFt.selectionList("base").append(
- aSketchResult, aSketchFaces[0])
-anExtrusionFt.real("size").setValue(50)
-anExtrusionFt.boolean("reverse").setValue(False)
+ aCircleSketchResult, aCircleSketchFaces[0])
+anExtrusionFt.real("from_size").setValue(0)
+anExtrusionFt.real("to_size").setValue(50)
anExtrusionFt.execute()
aSession.finishOperation()
-assert (anExtrusionFt.real("size").value() == 50.0)
-assert (anExtrusionFt.boolean("reverse").value() == False)
+assert (anExtrusionFt.real("to_size").value() == 50.0)
# Check extrusion results
assert (len(anExtrusionFt.results()) > 0)
anExtrusionResult = modelAPI_ResultBody(anExtrusionFt.firstResult())
assert (anExtrusionResult is not None)
+
+#=========================================================================
+# Test extrusion between bounding planes
+#=========================================================================
+# Create from plane
+aSession.startOperation()
+aFromPlaneFeature = aPart.addFeature("Plane")
+aFromPlaneFeature.string("CreationMethod").setValue("PlaneByGeneralEquation")
+aFromPlaneFeature.real("A").setValue(0.)
+aFromPlaneFeature.real("B").setValue(0.)
+aFromPlaneFeature.real("C").setValue(1.)
+aFromPlaneFeature.real("D").setValue(30.)
+aSession.finishOperation()
+
+# Create to plane
+aSession.startOperation()
+aToPlaneFeature = aPart.addFeature("Plane")
+aToPlaneFeature.string("CreationMethod").setValue("PlaneByGeneralEquation")
+aToPlaneFeature.real("A").setValue(0.)
+aToPlaneFeature.real("B").setValue(0.)
+aToPlaneFeature.real("C").setValue(1.)
+aToPlaneFeature.real("D").setValue(-30.)
+aSession.finishOperation()
+
+# Create extrusion
+aSession.startOperation()
+anExtrusionFt = aPart.addFeature("Extrusion")
+assert (anExtrusionFt.getKind() == "Extrusion")
+# selection type FACE=4
+anExtrusionFt.selectionList("base").append(
+ aCircleSketchResult, aCircleSketchFaces[0])
+aFromResult = aFromPlaneFeature.firstResult()
+aFromShape = modelAPI_ResultConstruction(aFromResult).shape()
+anExtrusionFt.selection("from_object").setValue(aFromResult, aFromShape)
+anExtrusionFt.real("from_size").setValue(10)
+aToResult = aToPlaneFeature.firstResult()
+aToShape = modelAPI_ResultConstruction(aToResult).shape()
+anExtrusionFt.selection("to_object").setValue(aToResult, aToShape)
+anExtrusionFt.real("to_size").setValue(10)
+anExtrusionFt.execute()
+aSession.finishOperation()
+
+# Check extrusion results
+assert (len(anExtrusionFt.results()) > 0)
+anExtrusionResult = modelAPI_ResultBody(anExtrusionFt.firstResult())
+assert (anExtrusionResult is not None)
+
+# Check extrusion volume
+aRefVolume = 100530.96491487337
+aResVolume = GeomAlgoAPI_ShapeProps_volume(anExtrusionResult.shape())
+assert (math.fabs(aResVolume - aRefVolume) < 10 ** -5)
+
+#=========================================================================
+# Test extrusion between bounding faces from other sketch result
+#=========================================================================
+aSession.startOperation()
+aClampSketchFeature = featureToCompositeFeature(aPart.addFeature("Sketch"))
+origin = geomDataAPI_Point(aClampSketchFeature.attribute("Origin"))
+origin.setValue(0, 0, 0)
+dirx = geomDataAPI_Dir(aClampSketchFeature.attribute("DirX"))
+dirx.setValue(1, 0, 0)
+norm = geomDataAPI_Dir(aClampSketchFeature.attribute("Norm"))
+norm.setValue(0, 1, 0)
+# Create clamp
+aSketchLineA = aClampSketchFeature.addFeature("SketchLine")
+aSketchLineB = aClampSketchFeature.addFeature("SketchLine")
+aSketchLineC = aClampSketchFeature.addFeature("SketchLine")
+aSketchLineD = aClampSketchFeature.addFeature("SketchLine")
+aSketchLineE = aClampSketchFeature.addFeature("SketchLine")
+aLineAStartPoint = geomDataAPI_Point2D(aSketchLineA.attribute("StartPoint"))
+aLineAEndPoint = geomDataAPI_Point2D(aSketchLineA.attribute("EndPoint"))
+aLineBStartPoint = geomDataAPI_Point2D(aSketchLineB.attribute("StartPoint"))
+aLineBEndPoint = geomDataAPI_Point2D(aSketchLineB.attribute("EndPoint"))
+aLineCStartPoint = geomDataAPI_Point2D(aSketchLineC.attribute("StartPoint"))
+aLineCEndPoint = geomDataAPI_Point2D(aSketchLineC.attribute("EndPoint"))
+aLineDStartPoint = geomDataAPI_Point2D(aSketchLineD.attribute("StartPoint"))
+aLineDEndPoint = geomDataAPI_Point2D(aSketchLineD.attribute("EndPoint"))
+aLineEStartPoint = geomDataAPI_Point2D(aSketchLineE.attribute("StartPoint"))
+aLineEEndPoint = geomDataAPI_Point2D(aSketchLineE.attribute("EndPoint"))
+aLineAStartPoint.setValue(0., -50.)
+aLineAEndPoint.setValue(0., 50.)
+aLineBStartPoint.setValue(0., 50.)
+aLineBEndPoint.setValue(100., 50.)
+aLineCStartPoint.setValue(100., 50.)
+aLineCEndPoint.setValue(10., 0.)
+aLineDStartPoint.setValue(10., 0.)
+aLineDEndPoint.setValue(100., -50.)
+aLineEStartPoint.setValue(100., -50.)
+aLineEEndPoint.setValue(0., -50.)
+aSession.finishOperation()
+
+# Extrude clamp
+aClampSketchResult = aClampSketchFeature.firstResult()
+aClampSketchEdges = modelAPI_ResultConstruction(aClampSketchResult).shape()
+origin = geomDataAPI_Point(aClampSketchFeature.attribute("Origin")).pnt()
+dirX = geomDataAPI_Dir(aClampSketchFeature.attribute("DirX")).dir()
+norm = geomDataAPI_Dir(aClampSketchFeature.attribute("Norm")).dir()
+aClampSketchFaces = ShapeList()
+GeomAlgoAPI_SketchBuilder.createFaces(
+ origin, dirX, norm, aClampSketchEdges, aClampSketchFaces)
+aSession.startOperation()
+aClampExtrusionFt = aPart.addFeature("Extrusion")
+assert (aClampExtrusionFt.getKind() == "Extrusion")
+# selection type FACE=4
+aClampExtrusionFt.selectionList("base").append(
+ aClampSketchResult, aClampSketchFaces[0])
+aClampExtrusionFt.real("from_size").setValue(0)
+aClampExtrusionFt.real("to_size").setValue(70)
+aClampExtrusionFt.execute()
+aSession.finishOperation()
+
+# Check extrusion results
+assert (len(aClampExtrusionFt.results()) > 0)
+anExtrusionResult = modelAPI_ResultBody(aClampExtrusionFt.firstResult())
+assert (anExtrusionResult is not None)
+
+# Extrude circle
+aSession.startOperation()
+anExtrusionFt = aPart.addFeature("Extrusion")
+assert (anExtrusionFt.getKind() == "Extrusion")
+# selection type FACE=4
+anExtrusionFt.selectionList("base").append(
+ aCircleSketchResult, aCircleSketchFaces[0])
+aClampResult = aClampExtrusionFt.firstResult()
+anExtrusionFt.selection("from_object").selectSubShape("face", "Extrusion_3/LateralFace_1")
+anExtrusionFt.real("from_size").setValue(0)
+anExtrusionFt.selection("to_object").selectSubShape("face", "Extrusion_3/LateralFace_2")
+anExtrusionFt.real("to_size").setValue(0)
+anExtrusionFt.execute()
+aSession.finishOperation()
+
+# Check extrusion results
+assert (len(anExtrusionFt.results()) > 0)
+anExtrusionResult = modelAPI_ResultBody(anExtrusionFt.firstResult())
+assert (anExtrusionResult is not None)
+
#=========================================================================
# End of test
#=========================================================================
anExtrusionFt = aPart.addFeature("Extrusion")
anExtrusionFt.selectionList("base").append(
aSketchResult, aSketchFaces[0])
-anExtrusionFt.real("size").setValue(50)
-anExtrusionFt.boolean("reverse").setValue(False)
+anExtrusionFt.real("from_size").setValue(50)
+anExtrusionFt.real("to_size").setValue(50)
anExtrusionFt.execute()
aSession.finishOperation()
anExtrusionBody = modelAPI_ResultBody(anExtrusionFt.firstResult())
anExtrusionFt.selectionList("base").append(
aSketchResult, aSketchFaces[0])
- anExtrusionFt.real("size").setValue(10)
- anExtrusionFt.boolean("reverse").setValue(False)
+ anExtrusionFt.real("from_size").setValue(0)
+ anExtrusionFt.real("to_size").setValue(10)
# v1.0.2 from master
# anExtrusionFt.selection("extrusion_face").setValue(
# aSketchResult, aSketchFaces[0])
aBox = aPart.addFeature("Extrusion")
aBox.selectionList("base").append(
aSketchResult, aSketchFaces[0])
-aBox.real("size").setValue(10)
-aBox.boolean("reverse").setValue(False)
+aBox.real("from_size").setValue(0)
+aBox.real("to_size").setValue(10)
# v 1.0.2 from master
# aBox.selection("extrusion_face").setValue(
# aSketchResult, aSketchFaces[0])
<!-- Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
<source>
- <shape_selector id="main_object"
+ <!--<shape_selector id="main_object"
label="Main object"
icon=":icons/cut_shape.png"
tooltip="Select an object solid"
shape_types="solid shell"
concealment="true"
+ />-->
+ <multi_selector id="main_objects"
+ label="Main object"
+ icon=":icons/cut_shape.png"
+ tooltip="Select an object solid"
+ type_choice="Solids"
+ concealment="true"
/>
- <shape_selector id="tool_object"
+ <multi_selector id="tool_objects"
+ label="Tool object"
+ icon=":icons/cut_tool.png"
+ tooltip="Select a tool solid"
+ type_choice="Solids"
+ concealment="true" >
+ <validator id="PartSet_DifferentObjects"/>
+ </multi_selector>
+ <!--<shape_selector id="tool_object"
label="Tool object"
icon=":icons/cut_tool.png"
tooltip="Select a tool solid"
shape_types="solid"
concealment="true" >
<validator id="PartSet_DifferentObjects"/>
- </shape_selector>
+ </shape_selector>-->
<choice id="bool_type"
label="Type"
tooltip="Type of boolean operation"
string_list="Cut Fuse Common"
+ default="0"
/>
</source>
type_choice="Faces">
<validator id="PartSet_SketchEntityValidator" parameters="Sketch"/>
</multi_selector>
- <doublevalue
- id="size"
- label="Size"
- min="0"
- step="1.0"
- default="1"
- icon=":icons/dimension_v.png"
- tooltip="Height">
- <validator id="GeomValidators_Positive"/>
- </doublevalue>
- <boolvalue id="reverse" label="Reverse" default="false" tooltip="Reverse default direction"/>
+ <groupbox title="From">
+ <shape_selector id="from_object"
+ icon=":icons/plane.png"
+ label="Plane face"
+ tooltip="Select a planar face"
+ shape_types="face"
+ default="<sketch>">
+ <validator id="GeomValidators_Face" parameters="plane"/>
+ </shape_selector>
+ <doublevalue
+ id="from_size"
+ label="Size"
+ min="0"
+ step="1.0"
+ default="0"
+ icon=":icons/dimension_down.png"
+ tooltip="Height">
+ <validator id="GeomValidators_Positive"/>
+ </doublevalue>
+ </groupbox>
+ <groupbox title="To">
+ <shape_selector id="to_object"
+ icon=":icons/plane_inverted.png"
+ label="Plane face"
+ tooltip="Select a planar face"
+ shape_types="face"
+ default="<sketch>">
+ <validator id="GeomValidators_Face" parameters="plane"/>
+ </shape_selector>
+ <doublevalue
+ id="to_size"
+ label="Size"
+ min="0"
+ step="1.0"
+ default="10"
+ icon=":icons/dimension_up.png"
+ tooltip="Height">
+ <validator id="GeomValidators_Positive"/>
+ </doublevalue>
+ </groupbox>
+<!--XML definition of the revolution:-->
+<!-- <multi_selector id="base"
+ label="Select a sketch face"
+ icon=":icons/sketch.png"
+ tooltip="Select a sketch face"
+ type_choice="Faces">
+ <validator id="PartSet_SketchEntityValidator" parameters="Sketch"/>
+ </multi_selector>
+ <shape_selector id="axis_object"
+ icon=":icons/axis.png"
+ label="Plane face"
+ tooltip="Select a planar face"
+ shape_types="edge">
+ </shape_selector>
+ <groupbox title="From">
+ <shape_selector id="from_object"
+ icon=":icons/plane.png"
+ label="Plane face"
+ tooltip="Select a planar face"
+ shape_types="face">
+ <validator id="GeomValidators_Face" parameters="plane"/>
+ </shape_selector>
+ <doublevalue
+ id="from_size"
+ label="Size"
+ min="0"
+ step="1.0"
+ default="0"
+ icon=":icons/angle_down.png"
+ tooltip="Height">
+ <validator id="GeomValidators_Positive"/>
+ </doublevalue>
+ </groupbox>
+ <groupbox title="To">
+ <shape_selector id="to_object"
+ icon=":icons/plane_inverted.png"
+ label="Plane face"
+ tooltip="Select a planar face"
+ shape_types="face">
+ <validator id="GeomValidators_Face" parameters="plane"/>
+ </shape_selector>
+ <doublevalue
+ id="to_size"
+ label="Size"
+ min="0"
+ step="1.0"
+ default="10"
+ icon=":icons/angle_up.png"
+ tooltip="Height">
+ <validator id="GeomValidators_Positive"/>
+ </doublevalue>
+ </groupbox>-->
</source>
return std::shared_ptr<GeomAPI_XYZ>(new GeomAPI_XYZ(aResult.X(), aResult.Y(), aResult.Z()));
}
+double GeomAPI_Dir::angle(const std::shared_ptr<GeomAPI_Dir>& theArg) const
+{
+ return MY_DIR->Angle(theArg->impl<gp_Dir>());
+}
+
double dot(const std::shared_ptr<GeomAPI_Dir>& theArg) const;
/// result is a cross product of two directions
const std::shared_ptr<GeomAPI_XYZ> cross(const std::shared_ptr<GeomAPI_Dir>& theArg) const;
+
+ /// calculates angle between two directions
+ double angle(const std::shared_ptr<GeomAPI_Dir>& theArg) const;
};
#endif
return MY_DIR->XY().Crossed(theArg->impl<gp_Dir2d>().XY());
}
+double GeomAPI_Dir2d::angle(const std::shared_ptr<GeomAPI_Dir2d>& theArg) const
+{
+ return MY_DIR->Angle(theArg->impl<gp_Dir2d>());
+}
double dot(const std::shared_ptr<GeomAPI_Dir2d>& theArg) const;
/// result is a cross product of two directions
double cross(const std::shared_ptr<GeomAPI_Dir2d>& theArg) const;
+
+ /// calculates angle between two directions
+ double angle(const std::shared_ptr<GeomAPI_Dir2d>& theArg) const;
};
#endif
#include <BRepAdaptor_Surface.hxx>
#include <Geom_Surface.hxx>
#include <Geom_Plane.hxx>
+#include <GeomLib_IsPlanarSurface.hxx>
GeomAPI_Face::GeomAPI_Face()
: GeomAPI_Shape()
{
const TopoDS_Shape& aShape = const_cast<GeomAPI_Face*>(this)->impl<TopoDS_Shape>();
Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aShape));
- if (aSurf->IsKind(STANDARD_TYPE(Geom_Plane)))
- return true;
- return false;
+ GeomLib_IsPlanarSurface isPlanar(aSurf);
+ return isPlanar.IsPlanar();
}
std::shared_ptr<GeomAPI_Pln> GeomAPI_Face::getPlane() const
SET(PROJECT_HEADERS
GeomAlgoAPI.h
+ GeomAlgoAPI_Tools.h
GeomAlgoAPI_CompoundBuilder.h
GeomAlgoAPI_FaceBuilder.h
GeomAlgoAPI_EdgeBuilder.h
GeomAlgoAPI_PointBuilder.h
GeomAlgoAPI_SketchBuilder.h
GeomAlgoAPI_Extrusion.h
+ GeomAlgoAPI_Prism.h
GeomAlgoAPI_Boolean.h
GeomAlgoAPI_MakeShape.h
+ GeomAlgoAPI_ShapeProps.h
GeomAlgoAPI_DFLoader.h
GeomAlgoAPI_Placement.h
GeomAlgoAPI_BREPImport.h
GeomAlgoAPI_STEPImport.h
+ GeomAlgoAPI_IGESImport.h
+ GeomAlgoAPI_BREPExport.h
+ GeomAlgoAPI_STEPExport.h
+ GeomAlgoAPI_IGESExport.h
)
SET(PROJECT_SOURCES
+ GeomAlgoAPI_Tools.cpp
GeomAlgoAPI_CompoundBuilder.cpp
GeomAlgoAPI_FaceBuilder.cpp
GeomAlgoAPI_EdgeBuilder.cpp
GeomAlgoAPI_PointBuilder.cpp
GeomAlgoAPI_SketchBuilder.cpp
GeomAlgoAPI_Extrusion.cpp
+ GeomAlgoAPI_Prism.cpp
GeomAlgoAPI_Boolean.cpp
GeomAlgoAPI_MakeShape.cpp
+ GeomAlgoAPI_ShapeProps.cpp
GeomAlgoAPI_DFLoader.cpp
GeomAlgoAPI_Placement.cpp
GeomAlgoAPI_BREPImport.cpp
GeomAlgoAPI_STEPImport.cpp
+ GeomAlgoAPI_IGESImport.cpp
+ GeomAlgoAPI_BREPExport.cpp
+ GeomAlgoAPI_STEPExport.cpp
+ GeomAlgoAPI_IGESExport.cpp
)
SET(PROJECT_LIBRARIES
${CAS_TKPrim}
${CAS_TKSTEP}
${CAS_TKSTEPBase}
+ ${CAS_TKIGES}
${CAS_TKTopAlgo}
${CAS_TKXSBase}
)
#include "GeomAlgoAPI_FaceBuilder.h"
#include "GeomAlgoAPI_MakeShape.h"
#include "GeomAlgoAPI_PointBuilder.h"
+ #include "GeomAlgoAPI_Prism.h"
+ #include "GeomAlgoAPI_ShapeProps.h"
#include "GeomAlgoAPI_SketchBuilder.h"
#include <memory>
%include "GeomAlgoAPI_FaceBuilder.h"
%include "GeomAlgoAPI_MakeShape.h"
%include "GeomAlgoAPI_PointBuilder.h"
+%include "GeomAlgoAPI_Prism.h"
+%include "GeomAlgoAPI_ShapeProps.h"
%include "GeomAlgoAPI_SketchBuilder.h"
%template(ShapeList) std::list<std::shared_ptr<GeomAPI_Shape> >;
\ No newline at end of file
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+#include <GeomAlgoAPI_BREPExport.h>
+
+#include "GeomAlgoAPI_Tools.h"
+
+#include <BRepTools.hxx>
+#include <BRep_Builder.hxx>
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+//extern "C" {
+namespace BREPExport {
+bool Export(const TCollection_AsciiString& theFileName,
+ const TCollection_AsciiString&,
+ const TopoDS_Shape& theShape,
+ TCollection_AsciiString& theError)
+{
+ #ifdef _DEBUG
+ std::cout << "Export BREP into file " << theFileName << std::endl;
+ #endif
+
+ // Set "C" numeric locale to save numbers correctly
+ GeomAlgoAPI_Tools::Localizer loc;
+
+ if ( !BRepTools::Write( theShape, theFileName.ToCString() ) ) {
+ theError = "BREP Export failed";
+ return false;
+ }
+ return true;
+}
+
+}
+//}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+/*
+ * GEOMALGOAPI_BREPExport.h
+ *
+ * Created on: May 14, 2015
+ * Author: spo
+ */
+
+#ifndef GEOMALGOAPI_BREPEXPORT_H_
+#define GEOMALGOAPI_BREPEXPORT_H_
+
+#include <GeomAlgoAPI.h>
+
+#include <TCollection_AsciiString.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TDF_Label.hxx>
+
+namespace BREPExport {
+
+/// Implementation of the export BREP files algorithms
+GEOMALGOAPI_EXPORT
+bool Export(const TCollection_AsciiString& theFileName,
+ const TCollection_AsciiString& theFormatName,
+ const TopoDS_Shape& theShape,
+ TCollection_AsciiString& theError);
+
+}
+
+#endif /* GEOMALGOAPI_BREPEXPORT_H_ */
namespace BREPImport {
TopoDS_Shape Import(const TCollection_AsciiString& theFileName,
const TCollection_AsciiString&,
- TCollection_AsciiString& theError, const TDF_Label&)
+ TCollection_AsciiString& theError)
{
#ifdef _DEBUG
std::cout << "Import BREP from file " << theFileName << std::endl;
GEOMALGOAPI_EXPORT
TopoDS_Shape Import(const TCollection_AsciiString& theFileName,
const TCollection_AsciiString& theFormatName,
- TCollection_AsciiString& theError, const TDF_Label&);
+ TCollection_AsciiString& theError);
}
#include <TopoDS.hxx>
#include <BRep_Tool.hxx>
#include <Geom_Plane.hxx>
+#include <GeomLib_IsPlanarSurface.hxx>
std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_FaceBuilder::square(
return aRes;
}
+std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_FaceBuilder::plane(std::shared_ptr<GeomAPI_Pnt> theCenter,
+ std::shared_ptr<GeomAPI_Dir> theNormal)
+{
+ const gp_Pnt& aCenter = theCenter->impl<gp_Pnt>();
+ const gp_Dir& aDir = theNormal->impl<gp_Dir>();
+ gp_Pln aPlane(aCenter, aDir);
+ BRepBuilderAPI_MakeFace aFaceBuilder(aPlane);
+ std::shared_ptr<GeomAPI_Shape> aRes(new GeomAPI_Shape);
+ aRes->setImpl(new TopoDS_Shape(aFaceBuilder.Face()));
+ return aRes;
+}
+
std::shared_ptr<GeomAPI_Pln> GeomAlgoAPI_FaceBuilder::plane(
std::shared_ptr<GeomAPI_Shape> theFace)
{
Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
if (aSurf.IsNull())
return aResult; // no surface
- Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(aSurf);
- if (aPlane.IsNull())
- return aResult; // not planar
+ GeomLib_IsPlanarSurface isPlanar(aSurf);
+ if(!isPlanar.IsPlanar()) {
+ return aResult;
+ }
+ gp_Pln aPln = isPlanar.Plan();
double aA, aB, aC, aD;
- aPlane->Coefficients(aA, aB, aC, aD);
+ aPln.Coefficients(aA, aB, aC, aD);
aResult = std::shared_ptr<GeomAPI_Pln>(new GeomAPI_Pln(aA, aB, aC, aD));
return aResult;
}
static std::shared_ptr<GeomAPI_Shape> square(std::shared_ptr<GeomAPI_Pln> thePlane,
const double theSize);
+ /// Creates the plane by given point of the center and normal to the plane.
+ static std::shared_ptr<GeomAPI_Shape> plane(std::shared_ptr<GeomAPI_Pnt> theCenter,
+ std::shared_ptr<GeomAPI_Dir> theNormal);
+
/// Returns the plane of the planar face. If it is not planar, returns empty ptr.
static std::shared_ptr<GeomAPI_Pln> plane(std::shared_ptr<GeomAPI_Shape> theFace);
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+#include <GeomAlgoAPI_IGESExport.h>
+
+#include "GeomAlgoAPI_Tools.h"
+
+// OOCT includes
+#include <IGESControl_Controller.hxx>
+#include <IGESControl_Writer.hxx>
+#include <Interface_Static.hxx>
+
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Iterator.hxx>
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+/*!
+ * KindOfBRep
+ * \return 0 if theShape contains only simple entities (wires, edges and vertices),
+ * 1 if theShape contains only complex entities (shells, solids and compsolids)
+ * 2 if theShape contains only indifferent entities (faces)
+ * -1 if theShape contains both simple and complex entities (and in this case it
+ * cannot be saved without any loss neither in BRepMode == 0 nor in BRepMode == 1)
+ */
+//=============================================================================
+int KindOfBRep (const TopoDS_Shape& theShape)
+{
+ int aKind = 2;
+
+ switch (theShape.ShapeType())
+ {
+ case TopAbs_COMPOUND:
+ {
+ bool isSimple = false;
+ bool isComplex = false;
+ TopoDS_Iterator anIt (theShape, Standard_True, Standard_True);
+ for (; anIt.More(); anIt.Next()) {
+ TopoDS_Shape aS = anIt.Value();
+ int aKindSub = KindOfBRep(aS);
+ if (aKindSub == 0)
+ isSimple = true;
+ else if (aKindSub == 1)
+ isComplex = true;
+ else if (aKindSub == -1) {
+ return -1; // heterogeneous
+ }
+ }
+ if (isSimple && isComplex)
+ aKind = -1; // heterogeneous
+ else if (isSimple)
+ aKind = 0;
+ else if (isComplex)
+ aKind = 1;
+ }
+ break;
+ case TopAbs_COMPSOLID:
+ case TopAbs_SOLID:
+ case TopAbs_SHELL:
+ aKind = 1;
+ break;
+ case TopAbs_WIRE:
+ case TopAbs_EDGE:
+ case TopAbs_VERTEX:
+ aKind = 0;
+ break;
+ default:
+ aKind = 2;
+ }
+
+ return aKind;
+}
+
+//=============================================================================
+//extern "C" {
+
+namespace IGESExport {
+
+bool Export(const TCollection_AsciiString& theFileName,
+ const TCollection_AsciiString& theFormatName,
+ const TopoDS_Shape& theShape,
+ TCollection_AsciiString& theError)
+{
+ // theFormatName expected "IGES-5.1", "IGES-5.3"...
+ TCollection_AsciiString aVersion = theFormatName.Token("-", 2);
+ #ifdef _DEBUG
+ if (!aVersion.IsEqual("5.1") || !aVersion.IsEqual("5.3"))
+ std::cout << "Warning: unrecognized version " << aVersion.ToCString()
+ << ". Default version: 5.1." << std::endl;
+ #endif
+ // define, whether to write only faces (5.1 IGES format)
+ // or shells and solids also (5.3 IGES format)
+ int aBrepMode = 0;
+ if( aVersion.IsEqual( "5.3" ) )
+ aBrepMode = 1;
+
+ #ifdef _DEBUG
+ std::cout << "Export IGES into file " << theFileName.ToCString() << std::endl;
+ #endif
+
+ // Mantis issue 0021350: check being exported shape, as some stand-alone
+ // entities (edges, wires and vertices) cannot be saved in BRepMode
+ if( aBrepMode == 1 ) {
+ int aKind = KindOfBRep( theShape );
+ if( aKind == -1 ) {
+ theError = "EXPORT_IGES_HETEROGENEOUS_COMPOUND";
+ return false;
+ } else if( aKind == 2 )
+ aBrepMode = 1;
+ else
+ aBrepMode = aKind;
+ }
+
+ // Set "C" numeric locale to save numbers correctly
+ GeomAlgoAPI_Tools::Localizer loc;
+
+ // initialize writer
+ IGESControl_Controller::Init();
+ IGESControl_Writer ICW( "M", aBrepMode ); // export explicitly in meters
+ Interface_Static::SetCVal( "xstep.cascade.unit", "M" );
+
+ // 09.03.2010 skl for bug 0020726
+ // change default value "Average" to "Max"
+ Interface_Static::SetCVal( "write.precision.mode", "Max" );
+
+ // perform shape writing
+ if( ICW.AddShape( theShape ) ) {
+ ICW.ComputeModel();
+ return ICW.Write( theFileName.ToCString() );
+ }
+ return false;
+}
+
+}
+
+//}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+/*
+ * GEOMALGOAPI_IGESExport.h
+ *
+ * Created on: Dec 24, 2014
+ * Author: sbh
+ */
+
+#ifndef GEOMALGOAPI_IGESEXPORT_H_
+#define GEOMALGOAPI_IGESEXPORT_H_
+
+#include <GeomAlgoAPI.h>
+
+#include <TCollection_AsciiString.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TDF_Label.hxx>
+
+namespace IGESExport {
+
+/// Implementation of the export IGES files algorithms
+GEOMALGOAPI_EXPORT
+bool Export(const TCollection_AsciiString& theFileName,
+ const TCollection_AsciiString& theFormatName,
+ const TopoDS_Shape& theShape,
+ TCollection_AsciiString& theError);
+
+}
+
+#endif /* GEOMALGOAPI_IGESEXPORT_H_ */
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+#include <GeomAlgoAPI_IGESImport.h>
+
+// OOCT includes
+#include <IGESControl_Reader.hxx>
+#include <IGESData_IGESModel.hxx>
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+//extern "C" {
+namespace IGESImport {
+TopoDS_Shape Import(const TCollection_AsciiString& theFileName,
+ const TCollection_AsciiString&,
+ TCollection_AsciiString& theError)
+{
+ #ifdef _DEBUG
+ std::cout << "Import IGES from file " << theFileName << std::endl;
+ #endif
+ TopoDS_Shape aResShape;
+ IGESControl_Reader aReader;
+ try {
+ IFSelect_ReturnStatus status = aReader.ReadFile( theFileName.ToCString() );
+
+ if (status == IFSelect_RetDone) {
+ #ifdef _DEBUG
+ std::cout << "ImportIGES : all Geometry Transfer" << std::endl;
+ #endif
+ aReader.ClearShapes();
+ aReader.TransferRoots();
+
+ #ifdef _DEBUG
+ std::cout << "ImportIGES : count of shapes produced = " << aReader.NbShapes() << std::endl;
+ #endif
+ aResShape = aReader.OneShape();
+ }
+ else {
+ switch (status) {
+ case IFSelect_RetVoid:
+ theError = "Nothing created or No data to process";
+ break;
+ case IFSelect_RetError:
+ theError = "Error in command or input data";
+ break;
+ case IFSelect_RetFail:
+ theError = "Execution was run, but has failed";
+ break;
+ case IFSelect_RetStop:
+ theError = "Execution has been stopped. Quite possible, an exception was raised";
+ break;
+ default:
+ theError = "Wrong format of the imported file. Can't import file.";
+ break;
+ }
+ aResShape.Nullify();
+ }
+ }
+ catch( Standard_Failure ) {
+ Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+ theError = aFail->GetMessageString();
+ aResShape.Nullify();
+ }
+
+ return aResShape;
+}
+
+}
+//}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+/*
+ * GEOMALGOAPI_IGESImport.h
+ *
+ * Created on: May 14, 2015
+ * Author: spo
+ */
+
+#ifndef GEOMALGOAPI_IGESIMPORT_H_
+#define GEOMALGOAPI_IGESIMPORT_H_
+
+#include <GeomAlgoAPI.h>
+
+#include <TCollection_AsciiString.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TDF_Label.hxx>
+
+namespace IGESImport {
+
+/// Implementation of the import IGES files algorithms
+GEOMALGOAPI_EXPORT
+TopoDS_Shape Import(const TCollection_AsciiString& theFileName,
+ const TCollection_AsciiString& theFormatName,
+ TCollection_AsciiString& theError);
+
+}
+
+#endif /* GEOMALGOAPI_IGESIMPORT_H_ */
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: GeomAlgoAPI_Prism.h
+// Created: 5 May 2015
+// Author: Dmitry Bobylev
+
+#include <GeomAlgoAPI_Prism.h>
+
+#include <GeomAlgoAPI_DFLoader.h>
+
+#include <BRep_Tool.hxx>
+#include <BRepCheck_Analyzer.hxx>
+#include <BRepFeat_MakePrism.hxx>
+#include <BRepGProp.hxx>
+#include <Geom_CylindricalSurface.hxx>
+#include <Geom_Plane.hxx>
+#include <Geom_RectangularTrimmedSurface.hxx>
+#include <gp_Cylinder.hxx>
+#include <gp_Pln.hxx>
+#include <GProp_GProps.hxx>
+#include <LocOpe_FindEdgesInFace.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+
+GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(std::shared_ptr<GeomAPI_Shape> theBasis,
+ std::shared_ptr<GeomAPI_Shape> theFromShape,
+ std::shared_ptr<GeomAPI_Shape> theToShape)
+: myFromShape(theFromShape),
+ myToShape(theToShape),
+ myShape(new GeomAPI_Shape()),
+ myFirst(new GeomAPI_Shape()),myLast(new GeomAPI_Shape())
+{
+ build(theBasis);
+}
+
+//============================================================================
+void GeomAlgoAPI_Prism::build(const std::shared_ptr<GeomAPI_Shape>& theBasis)
+{
+ TopoDS_Face aBasis = TopoDS::Face(theBasis->impl<TopoDS_Shape>());
+ Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(
+ BRep_Tool::Surface(aBasis));
+ if(aPlane.IsNull()) { // non-planar shapes is not supported for extrusion yet
+ return;
+ }
+
+ const gp_Dir& aNormal = aPlane->Pln().Axis().Direction();
+ BRepFeat_MakePrism* aBuilder = new BRepFeat_MakePrism(aBasis, aBasis, aBasis, aNormal, 2, Standard_True);
+
+ if(aBuilder) {
+ setImpl(aBuilder);
+ TopoDS_Shape aFromShape = myFromShape->impl<TopoDS_Shape>();
+ TopoDS_Shape aToShape = myToShape->impl<TopoDS_Shape>();
+ aBuilder->Perform(myFromShape->impl<TopoDS_Shape>(), myToShape->impl<TopoDS_Shape>());
+ myDone = aBuilder->IsDone();
+ if (myDone) {
+ TopoDS_Shape aResult;
+ if(aBuilder->Shape().ShapeType() == TopAbs_COMPOUND) {
+ aResult = GeomAlgoAPI_DFLoader::refineResult(aBuilder->Shape());
+ }
+ else {
+ aResult = aBuilder->Shape();
+ }
+ TopExp_Explorer anExp(aResult, TopAbs_SOLID);
+ if(!anExp.More()) {
+ return;
+ }
+ // fill data map to keep correct orientation of sub-shapes
+ for (TopExp_Explorer Exp(aResult,TopAbs_FACE); Exp.More(); Exp.Next()) {
+ std::shared_ptr<GeomAPI_Shape> aCurrentShape(new GeomAPI_Shape());
+ aCurrentShape->setImpl(new TopoDS_Shape(Exp.Current()));
+ myMap.bind(aCurrentShape, aCurrentShape);
+ }
+ myShape->setImpl(new TopoDS_Shape(aResult));
+ myFirst->setImpl(new TopoDS_Shape(aBuilder->Modified(aFromShape).First()));
+ myLast->setImpl(new TopoDS_Shape(aBuilder->Modified(aToShape).First()));
+ myMkShape = new GeomAlgoAPI_MakeShape (aBuilder);
+ }
+ }
+}
+
+//============================================================================
+const bool GeomAlgoAPI_Prism::isDone() const
+{
+ return myDone;
+}
+
+//============================================================================
+const bool GeomAlgoAPI_Prism::isValid() const
+{
+ BRepCheck_Analyzer aChecker(myShape->impl<TopoDS_Shape>());
+ return (aChecker.IsValid() == Standard_True);
+}
+
+//============================================================================
+const bool GeomAlgoAPI_Prism::hasVolume() const
+{
+ bool hasVolume(false);
+ if(isValid()) {
+ const TopoDS_Shape& aRShape = myShape->impl<TopoDS_Shape>();
+ GProp_GProps aGProp;
+ BRepGProp::VolumeProperties(aRShape, aGProp);
+ if(aGProp.Mass() > Precision::Confusion())
+ hasVolume = true;
+ }
+ return hasVolume;
+}
+
+//============================================================================
+const std::shared_ptr<GeomAPI_Shape>& GeomAlgoAPI_Prism::shape () const
+{
+ return myShape;
+}
+
+//============================================================================
+const std::shared_ptr<GeomAPI_Shape>& GeomAlgoAPI_Prism::firstShape()
+{
+ return myFirst;
+}
+
+//============================================================================
+const std::shared_ptr<GeomAPI_Shape>& GeomAlgoAPI_Prism::lastShape()
+{
+ return myLast;
+}
+
+//============================================================================
+void GeomAlgoAPI_Prism::mapOfShapes (GeomAPI_DataMapOfShapeShape& theMap) const
+{
+ theMap = myMap;
+}
+
+//============================================================================
+GeomAlgoAPI_MakeShape* GeomAlgoAPI_Prism::makeShape() const
+{
+ return myMkShape;
+}
+
+//============================================================================
+GeomAlgoAPI_Prism::~GeomAlgoAPI_Prism()
+{
+ if (myImpl) {
+ myMap.clear();
+ }
+}
\ No newline at end of file
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: GeomAlgoAPI_Prism.h
+// Created: 5 May 2015
+// Author: Dmitry Bobylev
+
+#ifndef GeomAlgoAPI_Prism_H_
+#define GeomAlgoAPI_Prism_H_
+
+#include <GeomAlgoAPI.h>
+#include <GeomAPI_Shape.h>
+#include <GeomAlgoAPI_MakeShape.h>
+#include <GeomAPI_DataMapOfShapeShape.h>
+#include <memory>
+
+/**\class GeomAlgoAPI_Prism
+ * \ingroup DataAlgo
+ * \brief Allows to create the prism based on a given face and bounding planes
+ */
+
+class GeomAlgoAPI_Prism : public GeomAPI_Interface
+{
+public:
+ /* \brief Creates extrusion for the given shape along the normal for this shape
+ * \param[in] theBasis face or wire to be extruded
+ * \param[in] theFromShape bottom bounding shape
+ * \param[in] theToShape top bounding shape
+ * \return a solid or a face/shell which is obtained from specified one
+ */
+ /// Constructor
+ GEOMALGOAPI_EXPORT GeomAlgoAPI_Prism(std::shared_ptr<GeomAPI_Shape> theBasis,
+ std::shared_ptr<GeomAPI_Shape> theFromShape,
+ std::shared_ptr<GeomAPI_Shape> theToShape);
+
+ /// Returns True if algorithm succeed
+ GEOMALGOAPI_EXPORT const bool isDone() const;
+
+ /// 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 Prism algorithm which may be a Solid or a Face
+ GEOMALGOAPI_EXPORT const std::shared_ptr<GeomAPI_Shape>& shape() const;
+
+ /// Returns the first shape
+ GEOMALGOAPI_EXPORT const std::shared_ptr<GeomAPI_Shape>& firstShape();
+
+ /// returns last shape
+ GEOMALGOAPI_EXPORT const std::shared_ptr<GeomAPI_Shape>& lastShape();
+
+ /// 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 ~GeomAlgoAPI_Prism();
+private:
+ /// builds resulting shape
+ void build(const std::shared_ptr<GeomAPI_Shape>& theBasis);
+ /// fields
+ std::shared_ptr<GeomAPI_Shape> myFromShape;
+ std::shared_ptr<GeomAPI_Shape> myToShape;
+ bool myDone;
+ std::shared_ptr<GeomAPI_Shape> myShape;
+ std::shared_ptr<GeomAPI_Shape> myFirst;
+ std::shared_ptr<GeomAPI_Shape> myLast;
+ GeomAPI_DataMapOfShapeShape myMap;
+ GeomAlgoAPI_MakeShape* myMkShape;
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+#include <GeomAlgoAPI_STEPExport.h>
+
+#include "GeomAlgoAPI_Tools.h"
+
+// OOCT includes
+#include <IFSelect_ReturnStatus.hxx>
+#include <STEPControl_Writer.hxx>
+#include <Interface_Static.hxx>
+
+namespace STEPExport {
+
+bool Export(const TCollection_AsciiString& theFileName,
+ const TCollection_AsciiString& theFormatName,
+ const TopoDS_Shape& theShape,
+ TCollection_AsciiString& theError)
+{
+ #ifdef _DEBUG
+ std::cout << "Export STEP into file " << theFileName.ToCString() << std::endl;
+ #endif
+
+ try
+ {
+ // Set "C" numeric locale to save numbers correctly
+ GeomAlgoAPI_Tools::Localizer loc;
+
+ IFSelect_ReturnStatus status ;
+ //VRV: OCC 4.0 migration
+ STEPControl_Writer aWriter;
+ Interface_Static::SetCVal("xstep.cascade.unit","M");
+ Interface_Static::SetCVal("write.step.unit", "M");
+ Interface_Static::SetIVal("write.step.nonmanifold", 1);
+ status = aWriter.Transfer( theShape, STEPControl_AsIs );
+ //VRV: OCC 4.0 migration
+ if( status == IFSelect_RetDone )
+ status = aWriter.Write( theFileName.ToCString() );
+
+ // Return previous locale
+ if( status == IFSelect_RetDone )
+ return true;
+ }
+ catch (Standard_Failure)
+ {
+ theError = "Exception catched in STEPExport";
+ }
+ return false;
+}
+
+} // namespace STEPExport
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+/*
+ * GEOMALGOAPI_STEPExport.h
+ *
+ * Created on: May 14, 2015
+ * Author: spo
+ */
+
+#ifndef GEOMALGOAPI_STEPEXPORT_H_
+#define GEOMALGOAPI_STEPEXPORT_H_
+
+#include <GeomAlgoAPI.h>
+
+#include <TCollection_AsciiString.hxx>
+#include <TCollection_HAsciiString.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TDF_Label.hxx>
+
+namespace STEPExport {
+
+/// Implementation of the export parameter from the STEP file
+GEOMALGOAPI_EXPORT
+Handle(TCollection_HAsciiString) GetValue(const TCollection_AsciiString& theFileName,
+ const TCollection_AsciiString& theParameterName,
+ TCollection_AsciiString& theError);
+
+/// Implementation of the export STEP files algorithms
+GEOMALGOAPI_EXPORT
+bool Export(const TCollection_AsciiString& theFileName,
+ const TCollection_AsciiString& theFormatName,
+ const TopoDS_Shape& theShape,
+ TCollection_AsciiString& theError);
+}
+
+#endif /* GEOMALGOAPI_STEPEXPORT_H_ */
TopoDS_Shape Import (const TCollection_AsciiString& theFileName,
const TCollection_AsciiString& theFormatName,
- TCollection_AsciiString& theError,
- const TDF_Label& theShapeLabel)
+ TCollection_AsciiString& theError)
{
TopoDS_Shape aResShape;
* Author: sbh
*/
+#ifndef GEOMALGOAPI_STEPIMPORT_H_
+#define GEOMALGOAPI_STEPIMPORT_H_
+
#include <GeomAlgoAPI.h>
#include <TCollection_AsciiString.hxx>
/// Implementation of the import STEP files algorithms
GEOMALGOAPI_EXPORT
TopoDS_Shape Import(const TCollection_AsciiString& theFileName,
- const TCollection_AsciiString& theFormatName, TCollection_AsciiString& theError,
- const TDF_Label& theShapeLabel);
+ const TCollection_AsciiString& theFormatName,
+ TCollection_AsciiString& theError);
}
+
+#endif /* GEOMALGOAPI_STEPIMPORT_H_ */
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: GeomAlgoAPI_ShapeProps.cpp
+// Created: 8 May 2015
+// Author: Dmitry Bobylev
+
+#include <GeomAlgoAPI_ShapeProps.h>
+
+#include <BRepGProp.hxx>
+#include <GProp_GProps.hxx>
+#include <TopoDS_Shape.hxx>
+
+
+double GeomAlgoAPI_ShapeProps::volume(std::shared_ptr<GeomAPI_Shape> theShape)
+{
+ GProp_GProps aGProps;
+ TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
+ BRepGProp::VolumeProperties(aShape, aGProps);
+ return aGProps.Mass();
+}
\ No newline at end of file
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: GeomAlgoAPI_ShapeProps.h
+// Created: 8 May 2015
+// Author: Dmitry Bobylev
+
+#ifndef GeomAlgoAPI_ShapeProps_H_
+#define GeomAlgoAPI_ShapeProps_H_
+
+/**\class GeomAlgoAPI_ShapeProps
+ * \ingroup DataAlgo
+ * \brief Allows to compute different shape props
+ */
+
+#include <GeomAlgoAPI.h>
+#include <GeomAPI_Shape.h>
+
+class GEOMALGOAPI_EXPORT GeomAlgoAPI_ShapeProps
+{
+public:
+ /// Returns the total volume of the solids of the current shape
+ static double volume(std::shared_ptr<GeomAPI_Shape> theShape);
+};
+
+#endif
+
--- /dev/null
+/*
+ * GeomAlgoAPI_Tools.cpp
+ *
+ * Created on: May 18, 2015
+ * Author: spo
+ */
+
+#include "GeomAlgoAPI_Tools.h"
+
+#include <clocale>
+
+using namespace GeomAlgoAPI_Tools;
+
+Localizer::Localizer()
+{
+ myCurLocale = std::setlocale(LC_NUMERIC, 0);
+ std::setlocale(LC_NUMERIC, "C");
+}
+
+Localizer::~Localizer()
+{
+ std::setlocale(LC_NUMERIC, myCurLocale.c_str());
+}
--- /dev/null
+/*
+ * GeomAlgoAPI_Tools.h
+ *
+ * Created on: May 18, 2015
+ * Author: spo
+ */
+
+#ifndef GEOMALGOAPI_TOOLS_H_
+#define GEOMALGOAPI_TOOLS_H_
+
+#include <GeomAlgoAPI.h>
+
+#include <string>
+
+namespace GeomAlgoAPI_Tools {
+
+class GEOMALGOAPI_EXPORT Localizer
+{
+public:
+ Localizer();
+ ~Localizer();
+private:
+ std::string myCurLocale;
+};
+
+} // GeomAlgoAPI_Tools
+
+#endif /* GEOMALGOAPI_TOOLS_H_ */
SET(PROJECT_HEADERS
GeomValidators.h
GeomValidators_ConstructionComposite.h
- GeomValidators_Edge.h
- GeomValidators_EdgeOrVertex.h
GeomValidators_Face.h
GeomValidators_Positive.h
+ GeomValidators_ShapeType.h
GeomValidators_Tools.h
)
SET(PROJECT_SOURCES
GeomValidators_ConstructionComposite.cpp
- GeomValidators_Edge.cpp
- GeomValidators_EdgeOrVertex.cpp
GeomValidators_Face.cpp
GeomValidators_Positive.cpp
+ GeomValidators_ShapeType.cpp
GeomValidators_Tools.cpp
)
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-
-#include "GeomValidators_Edge.h"
-#include "GeomValidators_Tools.h"
-
-#include <GeomAPI_Curve.h>
-#include <Events_Error.h>
-#include <ModelAPI_Result.h>
-
-#include <StdSelect_TypeOfEdge.hxx>
-
-#include <string>
-#include <map>
-
-
-typedef std::map<std::string, GeomValidators_Edge::TypeOfEdge> EdgeTypes;
-static EdgeTypes MyEdgeTypes;
-
-GeomValidators_Edge::TypeOfEdge GeomValidators_Edge::edgeType(const std::string& theType)
-{
- if (MyEdgeTypes.size() == 0) {
- MyEdgeTypes["line"] = Line;
- MyEdgeTypes["circle"] = Circle;
- }
- std::string aType = std::string(theType.c_str());
- if (MyEdgeTypes.find(aType) != MyEdgeTypes.end())
- return MyEdgeTypes[aType];
-
- Events_Error::send("Edge type defined in XML is not implemented!");
- return AnyEdge;
-}
-
-bool GeomValidators_Edge::isValid(const AttributePtr& theAttribute,
- const std::list<std::string>& theArguments) const
-{
- bool aValid = false;
-
- TypeOfEdge anEdgeType = AnyEdge;
- if (theArguments.size() == 1) {
- std::string anArgument = theArguments.front();
- anEdgeType = edgeType(anArgument);
- }
-
- ObjectPtr anObject = GeomValidators_Tools::getObject(theAttribute);
- if (anObject.get() != NULL) {
- FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
- ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
- if (aResult.get() != NULL) {
- GeomShapePtr aShape = aResult->shape();
- if (aShape.get() != NULL && aShape->isEdge()) {
- aValid = anEdgeType == AnyEdge;
- if (!aValid) {
- bool isCircle = GeomAPI_Curve(aShape).isCircle();
- aValid = (isCircle && anEdgeType == Circle) ||
- (!isCircle && anEdgeType == Line);
- }
- }
- }
- }
- else {
- //AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
- }
- return aValid;
-}
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: GeomValidators_Edge.h
-// Created: 19 Mar 2015
-// Author: Natalia ERMOLAEVA
-
-#ifndef GeomValidators_Edge_H
-#define GeomValidators_Edge_H
-
-#include "GeomValidators.h"
-#include "ModelAPI_AttributeValidator.h"
-
-#include <string>
-
-/**
-* \ingroup Validators
-* A validator of selection
-*/
-class GeomValidators_Edge : public ModelAPI_AttributeValidator
-{
- public:
- // the edge type
- enum TypeOfEdge
- {
- AnyEdge,
- Line,
- Circle
- };
-
- public:
- GEOMVALIDATORS_EXPORT GeomValidators_Edge() {}
- //! returns true if attribute is valid
- //! \param theAttribute the checked attribute
- //! \param theArguments arguments of the attribute
- GEOMVALIDATORS_EXPORT virtual bool isValid(const AttributePtr& theAttribute,
- const std::list<std::string>& theArguments) const;
-protected:
- /// Convert string to TypeOfEdge value
- /// \param theType a string value
- static TypeOfEdge edgeType(const std::string& theType);
-};
-
-#endif
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-
-#include "GeomValidators_EdgeOrVertex.h"
-#include "GeomValidators_Tools.h"
-#include "GeomValidators_Edge.h"
-
-#include "ModelAPI_AttributeRefAttr.h"
-#include "ModelAPI_Result.h"
-
-#include <ModelAPI_Session.h>
-
-#include <GeomAPI_Curve.h>
-#include <GeomDataAPI_Point2D.h>
-
-#include <Events_Error.h>
-
-#include <StdSelect_TypeOfEdge.hxx>
-
-#include <QString>
-#include <QMap>
-
-
-bool GeomValidators_EdgeOrVertex::isValid(const AttributePtr& theAttribute,
- const std::list<std::string>& theArguments) const
-{
- bool aValid = false;
-
- // 1. check whether the attribute is a linear edge
- // there is a check whether the feature contains a point and a linear edge or two point values
- SessionPtr aMgr = ModelAPI_Session::get();
- ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
-
- const GeomValidators_Edge* aLinearEdgeValidator =
- dynamic_cast<const GeomValidators_Edge*>(aFactory->validator("GeomValidators_Edge"));
-
- std::list<std::string> anArguments;
- anArguments.push_back("line");
- aValid = aLinearEdgeValidator->isValid(theAttribute, anArguments);
- if (!aValid) {
- //2. check whether the attribute is a vertex
- ObjectPtr anObject = GeomValidators_Tools::getObject(theAttribute);
- if (anObject.get() != NULL) {
- FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
- ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
- if (aResult.get() != NULL) {
- GeomShapePtr aShape = aResult->shape();
- if (aShape.get() != NULL) {
- aValid = aShape->isVertex();
- }
- }
- }
- else {
- AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
- if (anAttr.get() != NULL) {
- AttributePtr aRefAttr = anAttr->attr();
- aValid = aRefAttr.get() != NULL && aRefAttr->attributeType() == GeomDataAPI_Point2D::typeId();
- }
- }
- }
- return aValid;
-}
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: GeomValidators_EdgeOrVertex.h
-// Created: 19 Mar 2015
-// Author: Natalia ERMOLAEVA
-
-#ifndef GeomValidators_EdgeOrVertex_H
-#define GeomValidators_EdgeOrVertex_H
-
-#include "GeomValidators.h"
-#include "ModelAPI_AttributeValidator.h"
-
-#include <StdSelect_TypeOfEdge.hxx>
-
-/**
-* \ingroup Validators
-* A validator of selection
-*/
-class GeomValidators_EdgeOrVertex : public ModelAPI_AttributeValidator
-{
- public:
- GEOMVALIDATORS_EXPORT GeomValidators_EdgeOrVertex() {}
- //! returns true if attribute is valid
- //! \param theAttribute the checked attribute
- //! \param theArguments arguments of the attribute
- GEOMVALIDATORS_EXPORT virtual bool isValid(const AttributePtr& theAttribute,
- const std::list<std::string>& theArguments) const;
-};
-
-#endif
#include "GeomValidators_Positive.h"
#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_Validator.h>
bool GeomValidators_Positive::isValid(
const AttributePtr& theAttribute, const std::list<std::string>& theArguments) const
{
- std::shared_ptr<ModelAPI_AttributeDouble> aDouble =
+ AttributeDoublePtr aDouble =
std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
- return aDouble->isInitialized() && aDouble->value() > 1.e-5;
+ if (aDouble.get())
+ return aDouble->isInitialized() && aDouble->value() > 1.e-5;
+ AttributeIntegerPtr aInteger =
+ std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(theAttribute);
+ return aInteger->isInitialized() && aInteger->value() > 0;
}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+
+#include "GeomValidators_ShapeType.h"
+#include "GeomValidators_Tools.h"
+
+#include <GeomAPI_Curve.h>
+#include <GeomDataAPI_Point2D.h>
+
+#include <ModelAPI_Result.h>
+#include "ModelAPI_AttributeRefAttr.h"
+
+#include <Events_Error.h>
+
+#include <string>
+#include <map>
+
+
+typedef std::map<std::string, GeomValidators_ShapeType::TypeOfShape> EdgeTypes;
+static EdgeTypes MyEdgeTypes;
+
+GeomValidators_ShapeType::TypeOfShape GeomValidators_ShapeType::shapeType(const std::string& theType)
+{
+ if (MyEdgeTypes.size() == 0) {
+ MyEdgeTypes["vertex"] = Vertex;
+ MyEdgeTypes["line"] = Line;
+ MyEdgeTypes["circle"] = Circle;
+ }
+ std::string aType = std::string(theType.c_str());
+ if (MyEdgeTypes.find(aType) != MyEdgeTypes.end())
+ return MyEdgeTypes[aType];
+
+ Events_Error::send("Edge type defined in XML is not implemented!");
+ return AnyShape;
+}
+
+bool GeomValidators_ShapeType::isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments) const
+{
+ bool aValid = false;
+
+ std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
+ for (; anIt != aLast && !aValid; anIt++) {
+ aValid = isValidArgument(theAttribute, *anIt);
+ }
+
+ return aValid;
+}
+
+bool GeomValidators_ShapeType::isValidArgument(const AttributePtr& theAttribute,
+ const std::string& theArgument) const
+{
+ bool aValid = false;
+ TypeOfShape aShapeType = shapeType(theArgument);
+ if (aShapeType == AnyShape)
+ return true;
+
+ ObjectPtr anObject = GeomValidators_Tools::getObject(theAttribute);
+ if (anObject.get() != NULL) {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
+ ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
+ if (aResult.get() != NULL) {
+ GeomShapePtr aShape = aResult->shape();
+ if (aShape.get() != NULL) {
+ switch (aShapeType) {
+ case Line:
+ aValid = aShape->isEdge() && !GeomAPI_Curve(aShape).isCircle();
+ break;
+ case Circle:
+ aValid = aShape->isEdge() && GeomAPI_Curve(aShape).isCircle();
+ break;
+ case Vertex:
+ aValid = aShape->isVertex();
+ break;
+ default: break;
+ }
+ }
+ }
+ }
+ else {
+ AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
+ if (anAttr.get() != NULL) {
+ if (aShapeType == Vertex) {
+ AttributePtr aRefAttr = anAttr->attr();
+ aValid = aRefAttr.get() != NULL && aRefAttr->attributeType() == GeomDataAPI_Point2D::typeId();
+ }
+ }
+ }
+ return aValid;
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: GeomValidators_ShapeType.h
+// Created: 19 Mar 2015
+// Author: Natalia ERMOLAEVA
+
+#ifndef GeomValidators_ShapeType_H
+#define GeomValidators_ShapeType_H
+
+#include "GeomValidators.h"
+#include "ModelAPI_AttributeValidator.h"
+
+#include <string>
+
+/**
+* \ingroup Validators
+* A validator for shape types, such as vertex, line, circe or arc.
+* If there are some argument parameters, this validator returns true if the attribute satisfied
+* at least one argument (OR combination of arguments).
+*/
+class GeomValidators_ShapeType : public ModelAPI_AttributeValidator
+{
+ public:
+ // the edge type
+ enum TypeOfShape
+ {
+ AnyShape,
+ Vertex,
+ Line,
+ Circle
+ };
+
+ public:
+ GEOMVALIDATORS_EXPORT GeomValidators_ShapeType() {}
+ //! returns true if attribute is valid
+ //! \param theAttribute the checked attribute
+ //! \param theArguments arguments of the attribute
+ GEOMVALIDATORS_EXPORT virtual bool isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments) const;
+protected:
+ /// Convert string to TypeOfShape value
+ /// \param theType a string value
+ static TypeOfShape shapeType(const std::string& theType);
+
+ bool isValidArgument(const AttributePtr& theAttribute,
+ const std::string& theArgument) const;
+
+};
+
+#endif
// hides the created features, the precondition is that the feature's results have been
// already built, so the createPlane/Points method calls the execute function for the planes
- static Events_ID HIDE_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TOHIDE);
std::list<FeaturePtr >::const_iterator aFIter = aFeatures.begin();
for (; aFIter != aFeatures.cend(); aFIter++) {
FeaturePtr aPlane = *aFIter;
const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aPlane->results();
std::list<ResultPtr >::const_iterator aRIter = aResults.begin();
for (; aRIter != aResults.cend(); aRIter++) {
- ModelAPI_EventCreator::get()->sendUpdated(*aRIter, HIDE_DISP);
+ (*aRIter)->setDisplayed(false);
}
}
- Events_Loop::loop()->flush(HIDE_DISP);
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
// the viewer update should be unblocked in order to avoid the features blinking before they are
// hidden
Model.h
Model_Application.h
Model_Document.h
+ Model_Objects.h
Model_Session.h
Model_Data.h
Model_AttributeDouble.h
SET(PROJECT_SOURCES
Model_Application.cpp
Model_Document.cpp
+ Model_Objects.cpp
Model_Session.cpp
Model_Data.cpp
Model_AttributeDouble.cpp
// load it if it must be loaded by demand
if (myLoadedByDemand.find(theDocID) != myLoadedByDemand.end() && !myPath.empty()) {
- aNew->load(myPath.c_str());
+ aNew->load(myPath.c_str(), aNew);
myLoadedByDemand.erase(theDocID); // done, don't do it anymore
} else {
+ aNew->setThis(aNew);
static Events_ID anId = ModelAPI_DocumentCreatedMessage::eventId();
std::shared_ptr<ModelAPI_DocumentCreatedMessage> aMessage = std::shared_ptr
<ModelAPI_DocumentCreatedMessage>(new ModelAPI_DocumentCreatedMessage(anId, this));
#include "Model_AttributeRefAttr.h"
#include "Model_Application.h"
#include "Model_Data.h"
+#include "Model_Objects.h"
#include <ModelAPI_Feature.h>
using namespace std;
{
// the back reference from the previous object to the attribute should be removed
ObjectPtr anObject = object();
- if (theObject && (!myIsInitialized || myID->Get().Length() != 0 || object() != theObject)) {
+ if (theObject.get() && (!myIsInitialized || myID->Get().Length() != 0 || object() != theObject)) {
REMOVE_BACK_REF(anObject);
std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(
owner()->document());
if (aDoc) {
TDF_Label aRefLab = myRef->Get();
- return aDoc->object(aRefLab);
+ return aDoc->objects()->object(aRefLab);
}
}
// not initialized
return ObjectPtr();
}
+bool Model_AttributeRefAttr::isInitialized()
+{
+ if (myRef->Get() == myRef->Label()) { // empty is not initialized: sketch parallelity
+ return false;
+ }
+ return ModelAPI_AttributeRefAttr::isInitialized();
+}
+
Model_AttributeRefAttr::Model_AttributeRefAttr(TDF_Label& theLabel)
{
myIsInitialized = theLabel.FindAttribute(TDataStd_Comment::GetID(), myID) == Standard_True;
/// Returns object referenced from this attribute
MODEL_EXPORT virtual ObjectPtr object();
+ /// Returns true if attribute was initialized by some value
+ MODEL_EXPORT virtual bool isInitialized();
+
+
protected:
/// Objects are created for features automatically
MODEL_EXPORT Model_AttributeRefAttr(TDF_Label& theLabel);
#include "Model_AttributeRefList.h"
#include "Model_Application.h"
#include "Model_Data.h"
+#include "Model_Objects.h"
#include <ModelAPI_Feature.h>
#include <TDF_ListIteratorOfLabelList.hxx>
if (aDoc) {
const TDF_LabelList& aList = myRef->List();
for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
- ObjectPtr anObj = aDoc->object(aLIter.Value());
+ ObjectPtr anObj = aDoc->objects()->object(aLIter.Value());
if (anObj.get() == NULL) {
myRef->Remove(aLIter.Value());
REMOVE_BACK_REF(theObject);
if (aDoc) {
const TDF_LabelList& aList = myRef->List();
for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
- ObjectPtr anObj = aDoc->object(aLIter.Value());
+ ObjectPtr anObj = aDoc->objects()->object(aLIter.Value());
aResult.push_back(anObj);
}
}
int anIndex = 0;
for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next(), anIndex++) {
if (anIndex == theIndex)
- return aDoc->object(aLIter.Value());
+ return aDoc->objects()->object(aLIter.Value());
}
}
return ObjectPtr();
#include "Model_Application.h"
#include "Model_Events.h"
#include "Model_Data.h"
+#include "Model_Objects.h"
#include <ModelAPI_Feature.h>
#include <ModelAPI_Session.h>
void Model_AttributeReference::setValue(ObjectPtr theObject)
{
- if(!theObject)
- return;
+ // now allow to deselect in this attribute: extrusion from/to
+ //if(!theObject)
+ // return;
ObjectPtr aValue = value();
if (!myIsInitialized || aValue != theObject) {
REMOVE_BACK_REF(aValue);
- std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(
- theObject->data());
- TDF_Label anObjLab = aData->label().Father(); // object label
-
- if (owner()->document() == theObject->document()) { // same document, use reference attribute
+ TDF_Label anObjLab;
+ if (theObject.get() && theObject->data().get() && theObject->data()->isValid()) {
+ std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(
+ theObject->data());
+ anObjLab = aData->label().Father(); // object label
+ }
+ // same document, use reference attribute
+ if (anObjLab.IsNull() || owner()->document() == theObject->document()) {
std::shared_ptr<Model_Document> aDoc =
std::dynamic_pointer_cast<Model_Document>(owner()->document());
- myRef->Set(anObjLab); // references to the object label
+ if (anObjLab.IsNull()) {
+ myRef->Set(myRef->Label());
+ } else {
+ myRef->Set(anObjLab); // references to the object label
+ }
// remove external link attributes (if any)
myRef->Label().ForgetAttribute(TDataStd_Comment::GetID());
myRef->Label().ForgetAttribute(TDataStd_AsciiString::GetID());
ObjectPtr Model_AttributeReference::value()
{
- if (myIsInitialized) {
+ if (isInitialized()) {
Handle(TDataStd_Comment) aDocID;
if (myRef->Label().FindAttribute(TDataStd_Comment::GetID(), aDocID)) { // external ref
DocumentPtr aRefDoc =
if (myRef->Label().FindAttribute(TDataStd_AsciiString::GetID(), anEntry)) {
std::shared_ptr<Model_Document> aDR = std::dynamic_pointer_cast<Model_Document>(aRefDoc);
TDF_Label aRefLab;
- TDF_Tool::Label(aDR->featuresLabel().Data(), anEntry->Get().ToCString(), aRefLab);
+ TDF_Tool::Label(aDR->objects()->featuresLabel().Data(), anEntry->Get().ToCString(), aRefLab);
if (!aRefLab.IsNull()) {
- return aDR->object(aRefLab);
+ return aDR->objects()->object(aRefLab);
}
}
}
if (aDoc) {
TDF_Label aRefLab = myRef->Get();
if (!aRefLab.IsNull()) { // it may happen with old document, issue #285
- return aDoc->object(aRefLab);
+ return aDoc->objects()->object(aRefLab);
}
}
}
return FeaturePtr();
}
+bool Model_AttributeReference::isInitialized()
+{
+ if (myRef->Label() == myRef->Get() && !myRef->Label().IsAttribute(TDataStd_Comment::GetID())) {
+ // empty reference is not initialized
+ return false;
+ }
+ return ModelAPI_AttributeReference::isInitialized();
+}
+
Model_AttributeReference::Model_AttributeReference(TDF_Label& theLabel)
{
myIsInitialized = theLabel.FindAttribute(TDF_Reference::GetID(), myRef) == Standard_True;
MODEL_EXPORT virtual void setObject(const std::shared_ptr<ModelAPI_Object>& theObject);
+ /// Returns true if attribute was initialized by some value
+ MODEL_EXPORT virtual bool isInitialized();
+
+
protected:
/// Objects are created for features automatically
MODEL_EXPORT Model_AttributeReference(TDF_Label& theLabel);
if(aNumber > 1) return false;
return true;
}
-std::string Model_AttributeSelection::namingName()
+std::string Model_AttributeSelection::namingName(const std::string& theDefaultName)
{
std::string aName("");
- if(!this->isInitialized()) return aName;
+ if(!this->isInitialized())
+ return !theDefaultName.empty() ? theDefaultName : aName;
Handle(TDataStd_Name) anAtt;
if(selectionLabel().FindAttribute(TDataStd_Name::GetID(), anAtt)) {
aName = TCollection_AsciiString(anAtt->Get()).ToCString();
ResultPtr aCont = context();
aName = "Undefined name";
if(!aCont.get() || aCont->shape()->isNull())
- return aName;
+ return !theDefaultName.empty() ? theDefaultName : aName;
if (!aSubSh.get() || aSubSh->isNull()) { // no subshape, so just the whole feature name
return aCont->data()->name();
}
MODEL_EXPORT virtual bool update();
/// Returns a textual string of the selection
- MODEL_EXPORT virtual std::string namingName();
+ /// \param theDefaultValue a name, which is returned if the naming name can not be obtained
+ MODEL_EXPORT virtual std::string namingName(const std::string& theDefaultValue = "");
/// Returns an Id of the selection
/// NOTE: This method has been added for temporary export of groups towards old GEOM
// myLab contains:
// TDataStd_Name - name of the object
// TDataStd_Integer - state of the object execution
+// TDataStd_BooleanArray - array of flags of this data:
+// 0 - is in history or not
+static const int kFlagInHistory = 0;
+// 1 - is displayed or not
+static const int kFlagDisplayed = 1;
Model_Data::Model_Data() : mySendAttributeUpdated(true)
{
void Model_Data::setLabel(TDF_Label theLab)
{
myLab = theLab;
+ // set or get the default flags
+ if (!myLab.FindAttribute(TDataStd_BooleanArray::GetID(), myFlags)) {
+ // set default values if not found
+ myFlags = TDataStd_BooleanArray::Set(myLab, 0, 1);
+ myFlags->SetValue(kFlagInHistory, Standard_True); // is in history by default is true
+ myFlags->SetValue(kFlagDisplayed, Standard_True); // is displayed by default is true
+ }
}
std::string Model_Data::name()
}
}
}
+
+bool Model_Data::isInHistory()
+{
+ return myFlags->Value(kFlagInHistory) == Standard_True;
+}
+
+void Model_Data::setIsInHistory(const bool theFlag)
+{
+ return myFlags->SetValue(kFlagInHistory, theFlag);
+}
+
+bool Model_Data::isDisplayed()
+{
+ return myFlags->Value(kFlagDisplayed) == Standard_True;
+}
+
+void Model_Data::setDisplayed(const bool theDisplay)
+{
+ if (theDisplay != isDisplayed()) {
+ myFlags->SetValue(kFlagDisplayed, theDisplay);
+ static Events_Loop* aLoop = Events_Loop::loop();
+ static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
+ aECreator->sendUpdated(myObject, EVENT_DISP);
+ }
+}
#include <ModelAPI_Object.h>
#include <TDF_Label.hxx>
+#include <TDataStd_BooleanArray.hxx>
#include <memory>
TDF_Label myLab; ///< label of the feature in the document
/// All attributes of the object identified by the attribute ID
std::map<std::string, std::shared_ptr<ModelAPI_Attribute> > myAttrs;
+ /// Array of flags of this data
+ Handle(TDataStd_BooleanArray) myFlags;
/// needed here to emit signal that object changed on change of the attribute
ObjectPtr myObject;
}
friend class Model_Document;
+ friend class Model_Objects;
friend class Model_Update;
friend class Model_AttributeReference;
friend class Model_AttributeRefAttr;
/// Copies all atributes content into theTarget data
MODEL_EXPORT virtual void copyTo(std::shared_ptr<ModelAPI_Data> theTarget);
+protected:
+ /// Returns true if "is in history" custom behaviors is defined for the feature
+ MODEL_EXPORT virtual bool isInHistory();
+
+ /// Defines the custom "is in history" behavior
+ MODEL_EXPORT virtual void setIsInHistory(const bool theFlag);
+
private:
/// Removes all information about back references
void eraseBackReferences();
/// \param theApplyConcealment applies consealment flag changes
void addBackReference(FeaturePtr theFeature, std::string theAttrID,
const bool theApplyConcealment = true);
+
+ /// Returns true if object must be displayed in the viewer: flag is stored in the
+ /// data model, so on undo/redo, open/save or recreation of object by history-playing it keeps
+ /// the original state i nthe current transaction.
+ MODEL_EXPORT virtual bool isDisplayed();
+
+ /// Sets the displayed/hidden state of the object. If it is changed, sends the "redisplay"
+ /// signal.
+ MODEL_EXPORT virtual void setDisplayed(const bool theDisplay);
};
/// Generic method to register back reference, used in referencing attributes.
#include <Model_Document.h>
#include <Model_Data.h>
+#include <Model_Objects.h>
#include <Model_Application.h>
#include <Model_Session.h>
#include <Model_Events.h>
-#include <Model_ResultPart.h>
-#include <Model_ResultConstruction.h>
-#include <Model_ResultBody.h>
-#include <Model_ResultGroup.h>
-#include <Model_ResultParameter.h>
+#include <ModelAPI_ResultPart.h>
#include <ModelAPI_Validator.h>
#include <ModelAPI_CompositeFeature.h>
static const int UNDO_LIMIT = 1000; // number of possible undo operations (big for sketcher)
static const int TAG_GENERAL = 1; // general properties tag
-static const int TAG_OBJECTS = 2; // tag of the objects sub-tree (features, results)
-static const int TAG_HISTORY = 3; // tag of the history sub-tree (python dump)
-// feature sub-labels
-static const int TAG_FEATURE_ARGUMENTS = 1; ///< where the arguments are located
-static const int TAG_FEATURE_RESULTS = 2; ///< where the results are located
-
-///
-/// 0:1:2 - where features are located
-/// 0:1:2:N:1 - data of the feature N
-/// 0:1:2:N:2:K:1 - data of the K result of the feature N
+// general sub-labels
+static const int TAG_CURRENT_FEATURE = 1; ///< where the reference to the current feature label is located (or no attribute if null feature)
Model_Document::Model_Document(const std::string theID, const std::string theKind)
: myID(theID), myKind(theKind),
myDoc(new TDocStd_Document("BinOcaf")) // binary OCAF format
{
+ myObjs = new Model_Objects(myDoc->Main());
myDoc->SetUndoLimit(UNDO_LIMIT);
myTransactionSave = 0;
myExecuteFeatures = true;
myDoc->CommitCommand();
}
+void Model_Document::setThis(DocumentPtr theDoc)
+{
+ myObjs->setOwner(theDoc);
+}
+
/// Returns the file name of this document by the nameof directory and identifuer of a document
static TCollection_ExtendedString DocFileName(const char* theFileName, const std::string& theID)
{
return this == Model_Session::get()->moduleDocument().get();
}
-bool Model_Document::load(const char* theFileName)
+bool Model_Document::load(const char* theFileName, DocumentPtr theThis)
{
Handle(Model_Application) anApp = Model_Application::getApplication();
if (isRoot()) {
std::dynamic_pointer_cast<Model_Session>(Model_Session::get());
aSession->setActiveDocument(anApp->getDocument(myID), false);
aSession->setCheckTransactions(false);
- synchronizeFeatures(false, true, true);
+ if (myObjs)
+ delete myObjs;
+ myObjs = new Model_Objects(myDoc->Main()); // synchronisation is inside
+ myObjs->setOwner(theThis);
+ // update the current features status
+ setCurrentFeature(currentFeature(false), false);
aSession->setCheckTransactions(true);
aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false);
aSession->setActiveDocument(anApp->getDocument(myID), true);
// close for thid document needs no transaction in this document
std::static_pointer_cast<Model_Session>(Model_Session::get())->setCheckTransactions(false);
- // delete all features of this document
- std::shared_ptr<ModelAPI_Document> aThis =
- Model_Application::getApplication()->getDocument(myID);
- Events_Loop* aLoop = Events_Loop::loop();
- NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFeaturesIter(myObjs);
- for(; aFeaturesIter.More(); aFeaturesIter.Next()) {
- FeaturePtr aFeature = aFeaturesIter.Value();
- static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- ModelAPI_EventCreator::get()->sendDeleted(aThis, ModelAPI_Feature::group());
- ModelAPI_EventCreator::get()->sendUpdated(aFeature, EVENT_DISP);
- aFeature->eraseResults();
- if (theForever) { // issue #294: do not delete content of the document until it can be redone
- aFeature->erase();
- } else {
- aFeature->data()->execState(ModelAPI_StateMustBeUpdated);
- }
- }
- if (theForever) {
- myObjs.Clear();
- }
- aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
- aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
-
// close all only if it is really asked, otherwise it can be undoed/redoed
if (theForever) {
+ delete myObjs;
+ myObjs = 0;
if (myDoc->CanClose() == CDM_CCS_OK)
myDoc->Close();
+ } else {
+ setCurrentFeature(FeaturePtr(), false); // disables all features
}
std::static_pointer_cast<Model_Session>(Model_Session::get())->setCheckTransactions(true);
bool isNestedClosed = !myDoc->HasOpenCommand() && !myNestedNum.empty();
static std::shared_ptr<Model_Session> aSession =
std::static_pointer_cast<Model_Session>(Model_Session::get());
- synchronizeBackRefs();
+ myObjs->synchronizeBackRefs();
Events_Loop* aLoop = Events_Loop::loop();
aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
- aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TOHIDE));
aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
// this must be here just after everything is finished but before real transaction stop
// to avoid messages about modifications outside of the transaction
for (; aSubIter != aSubs.end(); aSubIter++)
subDoc(*aSubIter)->abortOperation();
// references may be changed because they are set in attributes on the fly
- synchronizeFeatures(true, true, isRoot());
+ myObjs->synchronizeFeatures(true, true, isRoot());
}
bool Model_Document::isOperation() const
subDoc(*aSubIter)->undoInternal(theWithSubs, theSynchronize);
}
// after redo of all sub-documents to avoid updates on not-modified data (issue 370)
- if (theSynchronize)
- synchronizeFeatures(true, true, isRoot());
+ if (theSynchronize) {
+ myObjs->synchronizeFeatures(true, true, isRoot());
+ // update the current features status
+ setCurrentFeature(currentFeature(false), false);
+ }
}
void Model_Document::undo()
subDoc(*aSubIter)->redo();
// after redo of all sub-documents to avoid updates on not-modified data (issue 370)
- synchronizeFeatures(true, true, isRoot());
+ myObjs->synchronizeFeatures(true, true, isRoot());
+ // update the current features status
+ setCurrentFeature(currentFeature(false), false);
}
std::list<std::string> Model_Document::undoList() const
myTransactions.rbegin()->myId = theId;
}
-/// Append to the array of references a new referenced label
-static void AddToRefArray(TDF_Label& theArrayLab, TDF_Label& theReferenced)
-{
- Handle(TDataStd_ReferenceArray) aRefs;
- if (!theArrayLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
- aRefs = TDataStd_ReferenceArray::Set(theArrayLab, 0, 0);
- aRefs->SetValue(0, theReferenced);
- } else { // extend array by one more element
- Handle(TDataStd_HLabelArray1) aNewArray = new TDataStd_HLabelArray1(aRefs->Lower(),
- aRefs->Upper() + 1);
- for (int a = aRefs->Lower(); a <= aRefs->Upper(); a++) {
- aNewArray->SetValue(a, aRefs->Value(a));
- }
- aNewArray->SetValue(aRefs->Upper() + 1, theReferenced);
- aRefs->SetInternalArray(aNewArray);
- }
-}
-
-FeaturePtr Model_Document::addFeature(std::string theID)
+FeaturePtr Model_Document::addFeature(std::string theID, const bool theMakeCurrent)
{
- TDF_Label anEmptyLab;
- FeaturePtr anEmptyFeature;
std::shared_ptr<Model_Session> aSession =
std::dynamic_pointer_cast<Model_Session>(ModelAPI_Session::get());
FeaturePtr aFeature = aSession->createFeature(theID, this);
aDocToAdd = this;
}
if (aFeature) {
- TDF_Label aFeatureLab;
+ aDocToAdd->myObjs->addFeature(aFeature, currentFeature(false));
if (!aFeature->isAction()) { // do not add action to the data model
- TDF_Label aFeaturesLab = aDocToAdd->featuresLabel();
- aFeatureLab = aFeaturesLab.NewChild();
- aDocToAdd->initData(aFeature, aFeatureLab, TAG_FEATURE_ARGUMENTS);
- // keep the feature ID to restore document later correctly
- TDataStd_Comment::Set(aFeatureLab, aFeature->getKind().c_str());
- aDocToAdd->myObjs.Bind(aFeatureLab, aFeature);
- // store feature in the history of features array
- if (aFeature->isInHistory()) {
- AddToRefArray(aFeaturesLab, aFeatureLab);
- }
- }
- if (!aFeature->isAction()) { // do not add action to the data model
- // event: feature is added
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
- ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent);
+ if (theMakeCurrent) // after all this feature stays in the document, so make it current
+ setCurrentFeature(aFeature, false);
} else { // feature must be executed
// no creation event => updater not working, problem with remove part
aFeature->execute();
return aFeature;
}
-/// Appenad to the array of references a new referenced label.
-/// If theIndex is not -1, removes element at this index, not theReferenced.
-/// \returns the index of removed element
-static int RemoveFromRefArray(TDF_Label theArrayLab, TDF_Label theReferenced,
- const int theIndex = -1)
-{
- int aResult = -1; // no returned
- Handle(TDataStd_ReferenceArray) aRefs;
- if (theArrayLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
- if (aRefs->Length() == 1) { // just erase an array
- if ((theIndex == -1 && aRefs->Value(0) == theReferenced) || theIndex == 0) {
- theArrayLab.ForgetAttribute(TDataStd_ReferenceArray::GetID());
- }
- aResult = 0;
- } else { // reduce the array
- Handle(TDataStd_HLabelArray1) aNewArray = new TDataStd_HLabelArray1(aRefs->Lower(),
- aRefs->Upper() - 1);
- int aCount = aRefs->Lower();
- for (int a = aCount; a <= aRefs->Upper(); a++, aCount++) {
- if ((theIndex == -1 && aRefs->Value(a) == theReferenced) || theIndex == a) {
- aCount--;
- aResult = a;
- } else {
- aNewArray->SetValue(aCount, aRefs->Value(a));
- }
- }
- aRefs->SetInternalArray(aNewArray);
- }
- }
- return aResult;
-}
void Model_Document::refsToFeature(FeaturePtr theFeature,
- std::set<std::shared_ptr<ModelAPI_Feature> >& theRefs,
- const bool isSendError)
-{
- // check the feature: it must have no depended objects on it
- // the dependencies can be in the feature results
- std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
- for(; aResIter != theFeature->results().cend(); aResIter++) {
- ResultPtr aResult = (*aResIter);
- std::shared_ptr<Model_Data> aData =
- std::dynamic_pointer_cast<Model_Data>(aResult->data());
- if (aData.get() != NULL) {
- const std::set<AttributePtr>& aRefs = aData->refsToMe();
- std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin(), aRefLast = aRefs.end();
- for(; aRefIt != aRefLast; aRefIt++) {
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIt)->owner());
- if (aFeature.get() != NULL)
- theRefs.insert(aFeature);
- }
- }
- }
- // the dependencies can be in the feature itself
- std::shared_ptr<Model_Data> aData =
- std::dynamic_pointer_cast<Model_Data>(theFeature->data());
- if (aData && !aData->refsToMe().empty()) {
- const std::set<AttributePtr>& aRefs = aData->refsToMe();
- std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin(), aRefLast = aRefs.end();
- for(; aRefIt != aRefLast; aRefIt++) {
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIt)->owner());
- if (aFeature.get() != NULL)
- theRefs.insert(aFeature);
- }
- }
-
- if (!theRefs.empty() && isSendError) {
- Events_Error::send(
- "Feature '" + theFeature->data()->name() + "' is used and can not be deleted");
- }
-}
-
-void Model_Document::removeFeature(FeaturePtr theFeature/*, const bool theCheck*/)
+ std::set<std::shared_ptr<ModelAPI_Feature> >& theRefs, const bool isSendError)
{
- std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theFeature->data());
- if (aData) {
- TDF_Label aFeatureLabel = aData->label().Father();
- if (myObjs.IsBound(aFeatureLabel))
- myObjs.UnBind(aFeatureLabel);
- else
- return; // not found feature => do not remove
-
- // checking that the sub-element of composite feature is removed: if yes, inform the owner
- std::set<std::shared_ptr<ModelAPI_Feature> > aRefs;
- refsToFeature(theFeature, aRefs, false);
- std::set<std::shared_ptr<ModelAPI_Feature> >::iterator aRefIter = aRefs.begin();
- for(; aRefIter != aRefs.end(); aRefIter++) {
- std::shared_ptr<ModelAPI_CompositeFeature> aComposite =
- std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aRefIter);
- if (aComposite.get()) {
- aComposite->removeFeature(theFeature);
- }
- }
-
- // erase fields
- theFeature->erase();
- static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- ModelAPI_EventCreator::get()->sendUpdated(theFeature, EVENT_DISP);
- // erase all attributes under the label of feature
- aFeatureLabel.ForgetAllAttributes();
- // remove it from the references array
- if (theFeature->isInHistory()) {
- RemoveFromRefArray(featuresLabel(), aFeatureLabel);
- }
- // event: feature is deleted
- ModelAPI_EventCreator::get()->sendDeleted(theFeature->document(), ModelAPI_Feature::group());
- // the redisplay signal should be flushed in order to erase the feature presentation in the viewer
- Events_Loop::loop()->flush(EVENT_DISP);
- }
+ myObjs->refsToFeature(theFeature, theRefs, isSendError);
}
-void Model_Document::addToHistory(const std::shared_ptr<ModelAPI_Object> theObject)
+void Model_Document::removeFeature(FeaturePtr theFeature)
{
- TDF_Label aFeaturesLab = featuresLabel();
- std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theObject->data());
- if (!aData) {
- return; // not found feature => do not remove
- }
- TDF_Label aFeatureLabel = aData->label().Father();
- // store feature in the history of features array
- if (theObject->isInHistory()) {
- AddToRefArray(aFeaturesLab, aFeatureLabel);
- } else {
- RemoveFromRefArray(aFeaturesLab, aFeatureLabel);
+ // if this feature is current, make the current the previous feature
+ if (theFeature == currentFeature(false)) {
+ FeaturePtr aPrev = myObjs->nextFeature(theFeature, true);
+ setCurrentFeature(aPrev, false);
}
+ myObjs->removeFeature(theFeature);
}
-FeaturePtr Model_Document::feature(TDF_Label& theLabel) const
+void Model_Document::updateHistory(const std::shared_ptr<ModelAPI_Object> theObject)
{
- if (myObjs.IsBound(theLabel))
- return myObjs.Find(theLabel);
- return FeaturePtr(); // not found
+ myObjs->updateHistory(theObject);
}
-ObjectPtr Model_Document::object(TDF_Label theLabel)
+void Model_Document::updateHistory(const std::string theGroup)
{
- // try feature by label
- FeaturePtr aFeature = feature(theLabel);
- if (aFeature)
- return feature(theLabel);
- TDF_Label aFeatureLabel = theLabel.Father().Father(); // let's suppose it is result
- aFeature = feature(aFeatureLabel);
- if (aFeature) {
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.cbegin();
- for (; aRIter != aResults.cend(); aRIter++) {
- std::shared_ptr<Model_Data> aResData = std::dynamic_pointer_cast<Model_Data>(
- (*aRIter)->data());
- if (aResData->label().Father().IsEqual(theLabel))
- return *aRIter;
- }
- }
- return FeaturePtr(); // not found
+ myObjs->updateHistory(theGroup);
}
std::shared_ptr<ModelAPI_Document> Model_Document::subDocument(std::string theDocID)
const std::set<std::string> Model_Document::subDocuments(const bool theActivatedOnly) const
{
std::set<std::string> aResult;
- // comment must be in any feature: it is kind
- int anIndex = 0;
- TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter.More(); aLabIter.Next()) {
- TDF_Label aFLabel = aLabIter.Value()->Label();
- FeaturePtr aFeature = feature(aFLabel);
- if (aFeature.get()) { // if document is closed the feature may be not in myObjs map
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- if ((*aRIter)->groupName() != ModelAPI_ResultPart::group()) continue;
- if ((*aRIter)->isInHistory()) {
- ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aRIter);
- if (aPart && (!theActivatedOnly || aPart->isActivated()))
- aResult.insert(aPart->data()->name());
- }
- }
- }
+ std::list<ResultPtr> aPartResults;
+ myObjs->allResults(ModelAPI_ResultPart::group(), aPartResults);
+ std::list<ResultPtr>::iterator aPartRes = aPartResults.begin();
+ for(; aPartRes != aPartResults.end(); aPartRes++) {
+ ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aPartRes);
+ if (aPart && (!theActivatedOnly || aPart->isActivated()))
+ aResult.insert(aPart->data()->name());
}
return aResult;
}
Model_Application::getApplication()->getDocument(theDocID));
}
-ObjectPtr Model_Document::object(const std::string& theGroupID, const int theIndex,
- const bool theHidden)
+ObjectPtr Model_Document::object(const std::string& theGroupID, const int theIndex)
{
- if (theGroupID == ModelAPI_Feature::group()) {
- if (theHidden) {
- int anIndex = 0;
- TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter.More(); aLabIter.Next()) {
- if (theIndex == anIndex) {
- TDF_Label aFLabel = aLabIter.Value()->Label();
- return feature(aFLabel);
- }
- anIndex++;
- }
- } else {
- Handle(TDataStd_ReferenceArray) aRefs;
- if (!featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
- return ObjectPtr();
- if (aRefs->Lower() > theIndex || aRefs->Upper() < theIndex)
- return ObjectPtr();
- TDF_Label aFeatureLabel = aRefs->Value(theIndex);
- return feature(aFeatureLabel);
- }
- } else {
- // comment must be in any feature: it is kind
- int anIndex = 0;
- TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter.More(); aLabIter.Next()) {
- TDF_Label aFLabel = aLabIter.Value()->Label();
- FeaturePtr aFeature = feature(aFLabel);
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- if ((*aRIter)->groupName() != theGroupID) continue;
- bool isIn = theHidden && (*aRIter)->isInHistory();
- if (!isIn && (*aRIter)->isInHistory()) { // check that there is nobody references this result
- isIn = !(*aRIter)->isConcealed();
- }
- if (isIn) {
- if (anIndex == theIndex)
- return *aRIter;
- anIndex++;
- }
- }
- }
- }
- // not found
- return ObjectPtr();
+ return myObjs->object(theGroupID, theIndex);
}
std::shared_ptr<ModelAPI_Object> Model_Document::objectByName(
const std::string& theGroupID, const std::string& theName)
{
- if (theGroupID == ModelAPI_Feature::group()) {
- int anIndex = 0;
- TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter.More(); aLabIter.Next()) {
- TDF_Label aFLabel = aLabIter.Value()->Label();
- FeaturePtr aFeature = feature(aFLabel);
- if (aFeature && aFeature->name() == theName)
- return aFeature;
- }
- } else {
- // comment must be in any feature: it is kind
- int anIndex = 0;
- TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter.More(); aLabIter.Next()) {
- TDF_Label aFLabel = aLabIter.Value()->Label();
- FeaturePtr aFeature = feature(aFLabel);
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- if ((*aRIter)->groupName() == theGroupID && (*aRIter)->data()->name() == theName)
- return *aRIter;
- }
- }
- }
- // not found
- return ObjectPtr();
+ return myObjs->objectByName(theGroupID, theName);
}
-int Model_Document::size(const std::string& theGroupID, const bool theHidden)
+const int Model_Document::index(std::shared_ptr<ModelAPI_Object> theObject)
{
- int aResult = 0;
- if (theGroupID == ModelAPI_Feature::group()) {
- if (theHidden) {
- return myObjs.Size();
- } else {
- Handle(TDataStd_ReferenceArray) aRefs;
- if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
- return aRefs->Length();
- }
- } else {
- // comment must be in any feature: it is kind
- TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter.More(); aLabIter.Next()) {
- TDF_Label aFLabel = aLabIter.Value()->Label();
- FeaturePtr aFeature = feature(aFLabel);
- if (!aFeature) // may be on close
- continue;
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- if ((*aRIter)->groupName() != theGroupID) continue;
- bool isIn = theHidden;
- if (!isIn && (*aRIter)->isInHistory()) { // check that there is nobody references this result
- isIn = !(*aRIter)->isConcealed();
- }
- if (isIn)
- aResult++;
- }
- }
- }
- // group is not found
- return aResult;
+ return myObjs->index(theObject);
}
-TDF_Label Model_Document::featuresLabel() const
+int Model_Document::size(const std::string& theGroupID)
{
- return myDoc->Main().FindChild(TAG_OBJECTS);
+ return myObjs->size(theGroupID);
}
-void Model_Document::setUniqueName(FeaturePtr theFeature)
+std::shared_ptr<ModelAPI_Feature> Model_Document::currentFeature(const bool theVisible)
{
- if (!theFeature->data()->name().empty())
- return; // not needed, name is already defined
- std::string aName; // result
- // first count all objects of such kind to start with index = count + 1
- int aNumObjects = 0;
- NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFIter(myObjs);
- for (; aFIter.More(); aFIter.Next()) {
- if (aFIter.Value()->getKind() == theFeature->getKind())
- aNumObjects++;
- }
- // generate candidate name
- std::stringstream aNameStream;
- aNameStream << theFeature->getKind() << "_" << aNumObjects + 1;
- aName = aNameStream.str();
- // check this is unique, if not, increase index by 1
- for (aFIter.Initialize(myObjs); aFIter.More();) {
- FeaturePtr aFeature = aFIter.Value();
- bool isSameName = aFeature->data()->name() == aName;
- if (!isSameName) { // check also results to avoid same results names (actual for Parts)
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- isSameName = (*aRIter)->data()->name() == aName;
+ TDF_Label aRefLab = generalLabel().FindChild(TAG_CURRENT_FEATURE);
+ Handle(TDF_Reference) aRef;
+ if (aRefLab.FindAttribute(TDF_Reference::GetID(), aRef)) {
+ TDF_Label aLab = aRef->Get();
+ FeaturePtr aResult = myObjs->feature(aLab);
+ if (theVisible) { // get nearest visible (in history) going up
+ while(aResult.get() && !aResult->isInHistory()) {
+ aResult = myObjs->nextFeature(aResult, true);
}
}
- if (isSameName) {
- aNumObjects++;
- std::stringstream aNameStream;
- aNameStream << theFeature->getKind() << "_" << aNumObjects + 1;
- aName = aNameStream.str();
- // reinitialize iterator to make sure a new name is unique
- aFIter.Initialize(myObjs);
- } else
- aFIter.Next();
- }
- theFeature->data()->setName(aName);
-}
-
-void Model_Document::initData(ObjectPtr theObj, TDF_Label theLab, const int theTag)
-{
- std::shared_ptr<ModelAPI_Document> aThis = Model_Application::getApplication()->getDocument(
- myID);
- std::shared_ptr<Model_Data> aData(new Model_Data);
- aData->setLabel(theLab.FindChild(theTag));
- aData->setObject(theObj);
- theObj->setDoc(aThis);
- theObj->setData(aData);
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
- if (aFeature) {
- setUniqueName(aFeature); // must be before "initAttributes" because duplicate part uses name
+ return aResult;
}
- theObj->initAttributes();
+ return std::shared_ptr<ModelAPI_Feature>(); // null feature means the higher than first
}
-void Model_Document::synchronizeFeatures(
- const bool theMarkUpdated, const bool theUpdateReferences, const bool theFlush)
+void Model_Document::setCurrentFeature(std::shared_ptr<ModelAPI_Feature> theCurrent,
+ const bool theVisible)
{
- std::shared_ptr<ModelAPI_Document> aThis =
- Model_Application::getApplication()->getDocument(myID);
- // after all updates, sends a message that groups of features were created or updated
- Events_Loop* aLoop = Events_Loop::loop();
- static Events_ID aDispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- static Events_ID aCreateEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
- static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
- static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- static Events_ID aDeleteEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
- static Events_ID aToHideEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- aLoop->activateFlushes(false);
-
- // update all objects by checking are they on labels or not
- std::set<FeaturePtr> aNewFeatures, aKeptFeatures;
- TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter.More(); aLabIter.Next()) {
- TDF_Label aFeatureLabel = aLabIter.Value()->Label();
- FeaturePtr aFeature;
- if (!myObjs.IsBound(aFeatureLabel)) { // a new feature is inserted
- // create a feature
- aFeature = std::dynamic_pointer_cast<Model_Session>(ModelAPI_Session::get())->createFeature(
- TCollection_AsciiString(Handle(TDataStd_Comment)::DownCast(aLabIter.Value())->Get())
- .ToCString(), this);
- if (!aFeature) { // somethig is wrong, most probably, the opened document has invalid structure
- Events_Error::send("Invalid type of object in the document");
- aLabIter.Value()->Label().ForgetAllAttributes();
- continue;
+ TDF_Label aRefLab = generalLabel().FindChild(TAG_CURRENT_FEATURE);
+ CompositeFeaturePtr aMain; // main feature that may nest the new current
+ if (theCurrent.get()) {
+ /*
+ if (theVisible) { // make features below which are not in history also enabled: sketch subs
+ FeaturePtr aNext = myObjs->nextFeature(theCurrent);
+ for (; aNext.get(); aNext = myObjs->nextFeature(theCurrent)) {
+ if (aNext->isInHistory()) {
+ break; // next in history is not needed
+ } else { // next not in history is good for making current
+ theCurrent = aNext;
+ }
}
- // this must be before "setData" to redo the sketch line correctly
- myObjs.Bind(aFeatureLabel, aFeature);
- aNewFeatures.insert(aFeature);
- initData(aFeature, aFeatureLabel, TAG_FEATURE_ARGUMENTS);
-
- // event: model is updated
- ModelAPI_EventCreator::get()->sendUpdated(aFeature, aCreateEvent);
- } else { // nothing is changed, both iterators are incremented
- aFeature = myObjs.Find(aFeatureLabel);
- aKeptFeatures.insert(aFeature);
- if (theMarkUpdated) {
- ModelAPI_EventCreator::get()->sendUpdated(aFeature, anUpdateEvent);
+ }*/
+ aMain = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theCurrent);
+ if (!aMain.get()) {
+ // if feature nests into compisite feature, make the composite feature as current
+ const std::set<AttributePtr>& aRefsToMe = theCurrent->data()->refsToMe();
+ std::set<AttributePtr>::const_iterator aRefToMe = aRefsToMe.begin();
+ for(; aRefToMe != aRefsToMe.end(); aRefToMe++) {
+ CompositeFeaturePtr aComposite =
+ std::dynamic_pointer_cast<ModelAPI_CompositeFeature>((*aRefToMe)->owner());
+ if (aComposite.get() && aComposite->isSub(theCurrent)) {
+ aMain = aComposite;
+ break;
+ }
}
}
- }
- // update results of the features (after features created because they may be connected, like sketch and sub elements)
- std::list<FeaturePtr> aComposites; // composites must be updated after their subs (issue 360)
- TDF_ChildIDIterator aLabIter2(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter2.More(); aLabIter2.Next()) {
- TDF_Label aFeatureLabel = aLabIter2.Value()->Label();
- if (myObjs.IsBound(aFeatureLabel)) { // a new feature is inserted
- FeaturePtr aFeature = myObjs.Find(aFeatureLabel);
- if (std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeature).get())
- aComposites.push_back(aFeature);
- updateResults(aFeature);
- }
- }
- std::list<FeaturePtr>::iterator aComposite = aComposites.begin();
- for(; aComposite != aComposites.end(); aComposite++) {
- updateResults(*aComposite);
- }
- // check all features are checked: if not => it was removed
- NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFIter(myObjs);
- while (aFIter.More()) {
- if (aKeptFeatures.find(aFIter.Value()) == aKeptFeatures.end()
- && aNewFeatures.find(aFIter.Value()) == aNewFeatures.end()) {
- FeaturePtr aFeature = aFIter.Value();
- // event: model is updated
- //if (aFeature->isInHistory()) {
- ModelAPI_EventCreator::get()->sendDeleted(aThis, ModelAPI_Feature::group());
- //}
- // results of this feature must be redisplayed (hided)
- // redisplay also removed feature (used for sketch and AISObject)
- ModelAPI_EventCreator::get()->sendUpdated(aFeature, aRedispEvent);
- aFeature->erase();
- // unbind after the "erase" call: on abort sketch is removes sub-objects that corrupts aFIter
- myObjs.UnBind(aFIter.Key());
- // reinitialize iterator because unbind may corrupt the previous order in the map
- aFIter.Initialize(myObjs);
- } else
- aFIter.Next();
- }
-
- if (theUpdateReferences) {
- synchronizeBackRefs();
- }
-
- myExecuteFeatures = false;
- aLoop->activateFlushes(true);
-
- if (theFlush) {
- aLoop->flush(aCreateEvent);
- aLoop->flush(aDeleteEvent);
- aLoop->flush(anUpdateEvent);
- aLoop->flush(aRedispEvent);
- aLoop->flush(aToHideEvent);
- }
- myExecuteFeatures = true;
-}
+ std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theCurrent->data());
+ if (!aData.get()) return; // unknown case
+ TDF_Label aFeatureLabel = aData->label().Father();
-void Model_Document::synchronizeBackRefs()
-{
- std::shared_ptr<ModelAPI_Document> aThis =
- Model_Application::getApplication()->getDocument(myID);
- // keeps the concealed flags of result to catch the change and create created/deleted events
- std::list<std::pair<ResultPtr, bool> > aConcealed;
- // first cycle: erase all data about back-references
- NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFeatures(myObjs);
- for(; aFeatures.More(); aFeatures.Next()) {
- FeaturePtr aFeature = aFeatures.Value();
- std::shared_ptr<Model_Data> aFData =
- std::dynamic_pointer_cast<Model_Data>(aFeature->data());
- if (aFData) {
- aFData->eraseBackReferences();
- }
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- std::shared_ptr<Model_Data> aResData =
- std::dynamic_pointer_cast<Model_Data>((*aRIter)->data());
- if (aResData) {
- aConcealed.push_back(std::pair<ResultPtr, bool>(*aRIter, (*aRIter)->isConcealed()));
- aResData->eraseBackReferences();
- }
+ Handle(TDF_Reference) aRef;
+ if (aRefLab.FindAttribute(TDF_Reference::GetID(), aRef)) {
+ aRef->Set(aFeatureLabel);
+ } else {
+ aRef = TDF_Reference::Set(aRefLab, aFeatureLabel);
}
+ } else { // remove reference for the null feature
+ aRefLab.ForgetAttribute(TDF_Reference::GetID());
}
+ // make all features after this feature disabled in reversed order (to remove results without deps)
+ static Events_Loop* aLoop = Events_Loop::loop();
+ static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- // second cycle: set new back-references: only features may have reference, iterate only them
- ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
- for(aFeatures.Initialize(myObjs); aFeatures.More(); aFeatures.Next()) {
- FeaturePtr aFeature = aFeatures.Value();
- std::shared_ptr<Model_Data> aFData =
- std::dynamic_pointer_cast<Model_Data>(aFeature->data());
- if (aFData) {
- std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
- aFData->referencesToObjects(aRefs);
- std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator
- aRefsIter = aRefs.begin();
- for(; aRefsIter != aRefs.end(); aRefsIter++) {
- std::list<ObjectPtr>::iterator aRefTo = aRefsIter->second.begin();
- for(; aRefTo != aRefsIter->second.end(); aRefTo++) {
- if (*aRefTo) {
- std::shared_ptr<Model_Data> aRefData =
- std::dynamic_pointer_cast<Model_Data>((*aRefTo)->data());
- aRefData->addBackReference(aFeature, aRefsIter->first); // here the Concealed flag is updated
- }
- }
- }
- }
- }
- std::list<std::pair<ResultPtr, bool> >::iterator aCIter = aConcealed.begin();
- for(; aCIter != aConcealed.end(); aCIter++) {
- if (aCIter->first->isConcealed() != aCIter->second) { // somethign is changed => produce event
- if (aCIter->second) { // was concealed become not => creation event
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
- 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);
- }
+ bool aPassed = false; // flag that the current object is already passed in cycle
+ FeaturePtr anIter = myObjs->lastFeature();
+ for(; anIter.get(); anIter = myObjs->nextFeature(anIter, true)) {
+ // check this before passed become enabled: the current feature is enabled!
+ if (anIter == theCurrent) aPassed = true;
+
+ bool aDisabledFlag = !aPassed;
+ if (aMain.get() && aMain->isSub(anIter))
+ aDisabledFlag = false;
+ if (anIter->setDisabled(aDisabledFlag)) {
+ // state of feature is changed => so feature become updated
+ static Events_ID anUpdateEvent = aLoop->eventByName(EVENT_OBJECT_UPDATED);
+ ModelAPI_EventCreator::get()->sendUpdated(anIter, anUpdateEvent);
+ // flush is in the end of this method
+ ModelAPI_EventCreator::get()->sendUpdated(anIter, aRedispEvent /*, false*/);
}
}
+ aLoop->flush(aRedispEvent);
}
-TDF_Label Model_Document::resultLabel(
- const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theResultIndex)
-{
- const std::shared_ptr<Model_Data>& aData =
- std::dynamic_pointer_cast<Model_Data>(theFeatureData);
- return aData->label().Father().FindChild(TAG_FEATURE_RESULTS).FindChild(theResultIndex + 1);
-}
-
-void Model_Document::storeResult(std::shared_ptr<ModelAPI_Data> theFeatureData,
- std::shared_ptr<ModelAPI_Result> theResult,
- const int theResultIndex)
+TDF_Label Model_Document::generalLabel() const
{
- std::shared_ptr<ModelAPI_Document> aThis =
- Model_Application::getApplication()->getDocument(myID);
- theResult->setDoc(aThis);
- initData(theResult, resultLabel(theFeatureData, theResultIndex), TAG_FEATURE_ARGUMENTS);
- if (theResult->data()->name().empty()) { // if was not initialized, generate event and set a name
- std::stringstream aNewName;
- aNewName<<theFeatureData->name();
- if (theResultIndex > 0) // if there are several results, add unique prefix starting from second
- aNewName<<"_"<<theResultIndex + 1;
- theResult->data()->setName(aNewName.str());
- }
+ return myDoc->Main().FindChild(TAG_GENERAL);
}
std::shared_ptr<ModelAPI_ResultConstruction> Model_Document::createConstruction(
const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
{
- TDF_Label aLab = resultLabel(theFeatureData, theIndex);
- TDataStd_Comment::Set(aLab, ModelAPI_ResultConstruction::group().c_str());
- ObjectPtr anOldObject = object(aLab);
- std::shared_ptr<ModelAPI_ResultConstruction> aResult;
- if (anOldObject) {
- aResult = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(anOldObject);
- }
- if (!aResult) {
- aResult = std::shared_ptr<ModelAPI_ResultConstruction>(new Model_ResultConstruction);
- storeResult(theFeatureData, aResult, theIndex);
- }
- return aResult;
+ return myObjs->createConstruction(theFeatureData, theIndex);
}
std::shared_ptr<ModelAPI_ResultBody> Model_Document::createBody(
const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
{
- TDF_Label aLab = resultLabel(theFeatureData, theIndex);
- TDataStd_Comment::Set(aLab, ModelAPI_ResultBody::group().c_str());
- ObjectPtr anOldObject = object(aLab);
- std::shared_ptr<ModelAPI_ResultBody> aResult;
- if (anOldObject) {
- aResult = std::dynamic_pointer_cast<ModelAPI_ResultBody>(anOldObject);
- }
- if (!aResult) {
- aResult = std::shared_ptr<ModelAPI_ResultBody>(new Model_ResultBody);
- storeResult(theFeatureData, aResult, theIndex);
- }
- return aResult;
+ return myObjs->createBody(theFeatureData, theIndex);
}
std::shared_ptr<ModelAPI_ResultPart> Model_Document::createPart(
const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
{
- TDF_Label aLab = resultLabel(theFeatureData, theIndex);
- TDataStd_Comment::Set(aLab, ModelAPI_ResultPart::group().c_str());
- ObjectPtr anOldObject = object(aLab);
- std::shared_ptr<ModelAPI_ResultPart> aResult;
- if (anOldObject) {
- aResult = std::dynamic_pointer_cast<ModelAPI_ResultPart>(anOldObject);
- }
- if (!aResult) {
- aResult = std::shared_ptr<ModelAPI_ResultPart>(new Model_ResultPart);
- storeResult(theFeatureData, aResult, theIndex);
- }
- return aResult;
+ return myObjs->createPart(theFeatureData, theIndex);
}
std::shared_ptr<ModelAPI_ResultGroup> Model_Document::createGroup(
const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
{
- TDF_Label aLab = resultLabel(theFeatureData, theIndex);
- TDataStd_Comment::Set(aLab, ModelAPI_ResultGroup::group().c_str());
- ObjectPtr anOldObject = object(aLab);
- std::shared_ptr<ModelAPI_ResultGroup> aResult;
- if (anOldObject) {
- aResult = std::dynamic_pointer_cast<ModelAPI_ResultGroup>(anOldObject);
- }
- if (!aResult) {
- aResult = std::shared_ptr<ModelAPI_ResultGroup>(new Model_ResultGroup(theFeatureData));
- storeResult(theFeatureData, aResult, theIndex);
- }
- return aResult;
+ return myObjs->createGroup(theFeatureData, theIndex);
}
std::shared_ptr<ModelAPI_ResultParameter> Model_Document::createParameter(
const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
{
- TDF_Label aLab = resultLabel(theFeatureData, theIndex);
- TDataStd_Comment::Set(aLab, ModelAPI_ResultParameter::group().c_str());
- ObjectPtr anOldObject = object(aLab);
- std::shared_ptr<ModelAPI_ResultParameter> aResult;
- if (anOldObject) {
- aResult = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(anOldObject);
- }
- if (!aResult) {
- aResult = std::shared_ptr<ModelAPI_ResultParameter>(new Model_ResultParameter);
- storeResult(theFeatureData, aResult, theIndex);
- }
- return aResult;
+ return myObjs->createParameter(theFeatureData, theIndex);
}
std::shared_ptr<ModelAPI_Feature> Model_Document::feature(
std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theResult->data());
if (aData) {
TDF_Label aFeatureLab = aData->label().Father().Father().Father();
- return feature(aFeatureLab);
+ return myObjs->feature(aFeatureLab);
}
return FeaturePtr();
}
-void Model_Document::updateResults(FeaturePtr theFeature)
-{
- // for not persistent is will be done by parametric updater automatically
- //if (!theFeature->isPersistentResult()) return;
- // check the existing results and remove them if there is nothing on the label
- std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
- while(aResIter != theFeature->results().cend()) {
- ResultPtr aBody = std::dynamic_pointer_cast<ModelAPI_Result>(*aResIter);
- if (aBody) {
- if (!aBody->data()->isValid()) {
- // found a disappeared result => remove it
- theFeature->removeResult(aBody);
- // start iterate from beginning because iterator is corrupted by removing
- aResIter = theFeature->results().cbegin();
- continue;
- }
- }
- 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());
- for(; aLabIter.More(); aLabIter.Next()) {
- // here must be GUID of the feature
- int aResIndex = aLabIter.Value().Tag() - 1;
- ResultPtr aNewBody;
- if (aResSize <= aResIndex) {
- TDF_Label anArgLab = aLabIter.Value();
- Handle(TDataStd_Comment) aGroup;
- if (anArgLab.FindAttribute(TDataStd_Comment::GetID(), aGroup)) {
- if (aGroup->Get() == ModelAPI_ResultBody::group().c_str()) {
- aNewBody = createBody(theFeature->data(), aResIndex);
- } else if (aGroup->Get() == ModelAPI_ResultPart::group().c_str()) {
- aNewBody = createPart(theFeature->data(), aResIndex);
- } else if (aGroup->Get() == ModelAPI_ResultConstruction::group().c_str()) {
- theFeature->execute(); // construction shapes are needed for sketch solver
- break;
- } else if (aGroup->Get() == ModelAPI_ResultGroup::group().c_str()) {
- aNewBody = createGroup(theFeature->data(), aResIndex);
- } else if (aGroup->Get() == ModelAPI_ResultParameter::group().c_str()) {
- theFeature->attributeChanged("expression"); // just produce a value
- break;
- } else {
- Events_Error::send(std::string("Unknown type of result is found in the document:") +
- TCollection_AsciiString(aGroup->Get()).ToCString());
- }
- }
- if (aNewBody) {
- theFeature->setResult(aNewBody, aResIndex);
- }
- }
- }
-}
-
Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper)
{
return TDF_LabelMapHasher::HashCode(theLab, theUpper);
ResultPtr Model_Document::findByName(const std::string theName)
{
- NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator anObjIter(myObjs);
- for(; anObjIter.More(); anObjIter.Next()) {
- FeaturePtr& aFeature = anObjIter.ChangeValue();
- if (!aFeature) // may be on close
- continue;
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- if (aRIter->get() && (*aRIter)->data() && (*aRIter)->data()->isValid() &&
- (*aRIter)->data()->name() == theName) {
- return *aRIter;
- }
- }
- }
- // not found
- return ResultPtr();
+ return myObjs->findByName(theName);
}
#include <ModelAPI_ResultParameter.h>
#include <TDocStd_Document.hxx>
-#include <NCollection_DataMap.hxx>
-#include <TDF_Label.hxx>
#include <map>
#include <set>
class Handle_Model_Document;
-
-// for TDF_Label map usage
-static Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper);
-static Standard_Boolean IsEqual(const TDF_Label& theLab1, const TDF_Label& theLab2);
+class Model_Objects;
/**\class Model_Document
* \ingroup DataModel
//! Loads the OCAF document from the file.
//! \param theFileName full name of the file to load
+ //! \param theThis the common shared pointer to the document to manage with it later
//! \returns true if file was loaded successfully
- MODEL_EXPORT virtual bool load(const char* theFileName);
+ MODEL_EXPORT virtual bool load(const char* theFileName, DocumentPtr theThis);
//! Saves the OCAF document to the file.
//! \param theFileName full name of the file to store
//! Adds to the document the new feature of the given feature id
//! \param theID creates feature and puts it in the document
- MODEL_EXPORT virtual FeaturePtr addFeature(std::string theID);
+ //! \param theMakeCurrent to make current this new feature in this document
+ MODEL_EXPORT virtual FeaturePtr addFeature(std::string theID, const bool theMakeCurrent = true);
//! Return a list of features, which refers to the feature
//! \param theFeature a feature
//! \param theFeature a removed feature
MODEL_EXPORT virtual void removeFeature(FeaturePtr theFeature);
- //! Returns the existing feature by the label
- //! \param theLabel base label of the feature
- MODEL_EXPORT virtual FeaturePtr feature(TDF_Label& theLabel) const;
-
- //! Returns the existing object: result or feature
- //! \param theLabel base label of the object
- MODEL_EXPORT virtual ObjectPtr object(TDF_Label theLabel);
-
//! Returns the first found object in the group by the object name
//! \param theGroupID group that contains an object
//! \param theName name of the object to search
MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Object> objectByName(
const std::string& theGroupID, const std::string& theName);
+ //! Returns the object index in the group. Object must be visible. Otherwise returns -1.
+ //! \param theObject object of this document
+ //! \returns index started from zero, or -1 if object is invisible or belongs to another document
+ MODEL_EXPORT virtual const int index(std::shared_ptr<ModelAPI_Object> theObject);
//! Adds a new sub-document by the identifier, or returns existing one if it is already exist
MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Document> subDocument(std::string theDocID);
//! Returns the feature in the group by the index (started from zero)
//! \param theGroupID group that contains a feature
//! \param theIndex zero-based index of feature in the group
- //! \param theHidden if it is true, it counts also the features that are not in tree
- MODEL_EXPORT virtual ObjectPtr object(const std::string& theGroupID, const int theIndex,
- const bool theHidden = false);
+ MODEL_EXPORT virtual ObjectPtr object(const std::string& theGroupID, const int theIndex);
//! Returns the number of features in the group
- //! If theHidden is true, it counts also the features that are not in tree
- MODEL_EXPORT virtual int size(const std::string& theGroupID, const bool theHidden = false);
+ MODEL_EXPORT virtual int size(const std::string& theGroupID);
+
+ //! Returns the feature that is currently edited in this document, normally
+ //! this is the latest created feature
+ //! \param theVisible use visible features only: flag is true for Object Browser functionality
+ //! \returns null if next created feature must be the first
+ MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Feature> currentFeature(const bool theVisible);
+
+ //! Sets the current feature: all features below will be disabled, new features
+ //! will be appended after this one.
+ //! \param theCurrent the selected feature as current: blow it everythin become disabled
+ //! \param theVisible use visible features only: flag is true for Object Browser functionality
+ MODEL_EXPORT virtual void setCurrentFeature(std::shared_ptr<ModelAPI_Feature> theCurrent,
+ const bool theVisible);
/// Creates a construction cresults
MODEL_EXPORT virtual std::shared_ptr<ModelAPI_ResultConstruction> createConstruction(
///! Returns true if parametric updater need to execute feature on recomputartion
///! On abort, undo or redo it is not necessary: results in document are updated automatically
- bool executeFeatures() {return myExecuteFeatures;}
+ bool& executeFeatures() {return myExecuteFeatures;}
//! Registers the name of the shape for the topological naming needs
void addNamingName(const TDF_Label theLabel, std::string theName);
ResultPtr findByName(const std::string theName);
protected:
-
- //! Returns (creates if needed) the features label
- TDF_Label featuresLabel() const;
-
- //! Initializes feature with a unique name in this group (unique name is generated as
- //! feature type + "_" + index
- void setUniqueName(FeaturePtr theFeature);
-
- //! Synchronizes myFeatures list with the updated document
- //! \param theMarkUpdated causes the "update" event for all features
- //! \param theUpdateReferences causes the update of back-references
- //! \param theFlush makes flush all events in the end of all modifications of this method
- void synchronizeFeatures(const bool theMarkUpdated, const bool theUpdateReferences,
- const bool theFlush);
- //! Synchronizes the BackReferences list in Data of Features and Results
- void synchronizeBackRefs();
+ //! Returns (creates if needed) the general label
+ TDF_Label generalLabel() const;
//! Creates new document with binary file format
Model_Document(const std::string theID, const std::string theKind);
//! \returns true if resulting transaction is not empty and can be undoed
void compactNested();
- //! Initializes the data fields of the feature
- void initData(ObjectPtr theObj, TDF_Label theLab, const int theTag);
-
- //! Allows to store the result in the data tree of the document (attaches 'data' of result to tree)
- MODEL_EXPORT virtual void storeResult(std::shared_ptr<ModelAPI_Data> theFeatureData,
- std::shared_ptr<ModelAPI_Result> theResult,
- const int theResultIndex = 0);
-
- //! returns the label of result by index; creates this label if it was not created before
- TDF_Label resultLabel(const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theResultIndex);
-
- //! Updates the results list of the feature basing on the current data tree
- void updateResults(FeaturePtr theFeature);
-
//! Returns all sub documents
const std::set<std::string> subDocuments(const bool theActivatedOnly) const;
std::list<std::string> redoList() const;
/// Internally makes document know that feature was removed or added in history after creation
- MODEL_EXPORT virtual void addToHistory(const std::shared_ptr<ModelAPI_Object> theObject);
+ virtual void updateHistory(const std::shared_ptr<ModelAPI_Object> theObject);
+ /// Internally makes document know that feature was removed or added in history after creation
+ virtual void updateHistory(const std::string theGroup);
/// Returns true if the document is root module document
bool isRoot() const;
+ /// Sets shared pointer to this
+ void setThis(DocumentPtr theDoc);
+
+ /// Returns the objects manager
+ Model_Objects* objects() {return myObjs;}
+
friend class Model_Application;
friend class Model_Session;
friend class Model_Update;
friend class Model_AttributeReference;
+ friend class Model_AttributeRefAttr;
+ friend class Model_AttributeRefList;
friend class DFBrowser;
private:
std::string myKind; ///< kind of the document in the application
Handle_TDocStd_Document myDoc; ///< OCAF document
+ Model_Objects *myObjs; ///< data manager of this document
+
/// counter value of transaction on the last "save" call, used for "IsModified" method
int myTransactionSave;
/// number of nested transactions performed (list becasue may be nested inside of nested)
std::list<Transaction> myTransactions;
/// list of info about transactions undone (first is oldest undone)
std::list<Transaction> myRedos;
- /// All features managed by this document (not only in history of OB)
- /// For optimization mapped by labels
- NCollection_DataMap<TDF_Label, FeaturePtr> myObjs;
+
/// Optimization for finding the shape-label by topological naming names
std::map<std::string, TDF_Label> myNamingNames;
/// If it is true, features are not executed on update (on abort, undo, redo)
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: Model_Objects.cxx
+// Created: 15 May 2015
+// Author: Mikhail PONIKAROV
+
+#include <Model_Objects.h>
+#include <Model_Data.h>
+#include <Model_Document.h>
+#include <Model_Events.h>
+#include <Model_Session.h>
+#include <Model_ResultPart.h>
+#include <Model_ResultConstruction.h>
+#include <Model_ResultBody.h>
+#include <Model_ResultGroup.h>
+#include <Model_ResultParameter.h>
+#include <ModelAPI_Validator.h>
+#include <ModelAPI_CompositeFeature.h>
+
+#include <Events_Loop.h>
+#include <Events_Error.h>
+
+#include <TDataStd_Integer.hxx>
+#include <TDataStd_Comment.hxx>
+#include <TDF_ChildIDIterator.hxx>
+#include <TDataStd_ReferenceArray.hxx>
+#include <TDataStd_HLabelArray1.hxx>
+#include <TDataStd_Name.hxx>
+#include <TDF_Reference.hxx>
+#include <TDF_ChildIDIterator.hxx>
+#include <TDF_LabelMapHasher.hxx>
+
+static const int TAG_OBJECTS = 2; // tag of the objects sub-tree (features, results)
+
+// feature sub-labels
+static const int TAG_FEATURE_ARGUMENTS = 1; ///< where the arguments are located
+static const int TAG_FEATURE_RESULTS = 2; ///< where the results are located
+
+///
+/// 0:1:2 - where features are located
+/// 0:1:2:N:1 - data of the feature N
+/// 0:1:2:N:2:K:1 - data of the K result of the feature N
+
+Model_Objects::Model_Objects(TDF_Label theMainLab) : myMain(theMainLab)
+{
+}
+
+void Model_Objects::setOwner(DocumentPtr theDoc)
+{
+ myDoc = theDoc;
+ // update all fields and recreate features and result objects if needed
+ synchronizeFeatures(false, true, true);
+ myHistory.clear();
+}
+
+Model_Objects::~Model_Objects()
+{
+ // delete all features of this document
+ Events_Loop* aLoop = Events_Loop::loop();
+ NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFeaturesIter(myFeatures);
+ for(; aFeaturesIter.More(); aFeaturesIter.Next()) {
+ FeaturePtr aFeature = aFeaturesIter.Value();
+ static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ ModelAPI_EventCreator::get()->sendDeleted(myDoc, ModelAPI_Feature::group());
+ ModelAPI_EventCreator::get()->sendUpdated(aFeature, EVENT_DISP);
+ aFeature->eraseResults();
+ aFeature->erase();
+ }
+ myFeatures.Clear();
+ aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
+ aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+
+}
+
+/// Appends to the array of references a new referenced label
+static void AddToRefArray(TDF_Label& theArrayLab, TDF_Label& theReferenced, TDF_Label& thePrevLab)
+{
+ Handle(TDataStd_ReferenceArray) aRefs;
+ if (!theArrayLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+ aRefs = TDataStd_ReferenceArray::Set(theArrayLab, 0, 0);
+ aRefs->SetValue(0, theReferenced);
+ } else { // extend array by one more element
+ Handle(TDataStd_HLabelArray1) aNewArray = new TDataStd_HLabelArray1(aRefs->Lower(),
+ aRefs->Upper() + 1);
+ int aPassedPrev = 0; // prev feature is found and passed
+ if (thePrevLab.IsNull()) { // null means that inserted feature must be the first
+ aNewArray->SetValue(aRefs->Lower(), theReferenced);
+ aPassedPrev = 1;
+ }
+ for (int a = aRefs->Lower(); a <= aRefs->Upper(); a++) {
+ aNewArray->SetValue(a + aPassedPrev, aRefs->Value(a));
+ if (!aPassedPrev && aRefs->Value(a).IsEqual(thePrevLab)) {
+ aPassedPrev = 1;
+ aNewArray->SetValue(a + 1, theReferenced);
+ }
+ }
+ if (!aPassedPrev) // not found: unknown situation
+ aNewArray->SetValue(aRefs->Upper() + 1, theReferenced);
+ aRefs->SetInternalArray(aNewArray);
+ }
+}
+
+void Model_Objects::addFeature(FeaturePtr theFeature, const FeaturePtr theAfterThis)
+{
+ if (!theFeature->isAction()) { // do not add action to the data model
+ TDF_Label aFeaturesLab = featuresLabel();
+ TDF_Label aFeatureLab = aFeaturesLab.NewChild();
+ initData(theFeature, aFeatureLab, TAG_FEATURE_ARGUMENTS);
+ // keep the feature ID to restore document later correctly
+ TDataStd_Comment::Set(aFeatureLab, theFeature->getKind().c_str());
+ myFeatures.Bind(aFeatureLab, theFeature);
+ // store feature in the features array
+ TDF_Label aPrevFeateureLab;
+ if (theAfterThis.get()) { // searching for the previous feature label
+ std::shared_ptr<Model_Data> aPrevData =
+ std::dynamic_pointer_cast<Model_Data>(theAfterThis->data());
+ if (aPrevData.get()) {
+ aPrevFeateureLab = aPrevData->label().Father();
+ }
+ }
+ AddToRefArray(aFeaturesLab, aFeatureLab, aPrevFeateureLab);
+ // event: feature is added
+ static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
+ ModelAPI_EventCreator::get()->sendUpdated(theFeature, anEvent);
+ theFeature->setDisabled(false); // by default created feature is enabled
+ updateHistory(ModelAPI_Feature::group());
+ }
+}
+
+/// Appends to the array of references a new referenced label.
+/// If theIndex is not -1, removes element at this index, not theReferenced.
+/// \returns the index of removed element
+static int RemoveFromRefArray(TDF_Label theArrayLab, TDF_Label theReferenced,
+ const int theIndex = -1)
+{
+ int aResult = -1; // no returned
+ Handle(TDataStd_ReferenceArray) aRefs;
+ if (theArrayLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+ if (aRefs->Length() == 1) { // just erase an array
+ if ((theIndex == -1 && aRefs->Value(0) == theReferenced) || theIndex == 0) {
+ theArrayLab.ForgetAttribute(TDataStd_ReferenceArray::GetID());
+ }
+ aResult = 0;
+ } else { // reduce the array
+ Handle(TDataStd_HLabelArray1) aNewArray = new TDataStd_HLabelArray1(aRefs->Lower(),
+ aRefs->Upper() - 1);
+ int aCount = aRefs->Lower();
+ for (int a = aCount; a <= aRefs->Upper(); a++, aCount++) {
+ if ((theIndex == -1 && aRefs->Value(a) == theReferenced) || theIndex == a) {
+ aCount--;
+ aResult = a;
+ } else {
+ aNewArray->SetValue(aCount, aRefs->Value(a));
+ }
+ }
+ aRefs->SetInternalArray(aNewArray);
+ }
+ }
+ return aResult;
+}
+
+void Model_Objects::refsToFeature(FeaturePtr theFeature,
+ std::set<std::shared_ptr<ModelAPI_Feature> >& theRefs, const bool isSendError)
+{
+ // check the feature: it must have no depended objects on it
+ // the dependencies can be in the feature results
+ std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
+ for(; aResIter != theFeature->results().cend(); aResIter++) {
+ ResultPtr aResult = (*aResIter);
+ std::shared_ptr<Model_Data> aData =
+ std::dynamic_pointer_cast<Model_Data>(aResult->data());
+ if (aData.get() != NULL) {
+ const std::set<AttributePtr>& aRefs = aData->refsToMe();
+ std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin(), aRefLast = aRefs.end();
+ for(; aRefIt != aRefLast; aRefIt++) {
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIt)->owner());
+ if (aFeature.get() != NULL)
+ theRefs.insert(aFeature);
+ }
+ }
+ }
+ // the dependencies can be in the feature itself
+ std::shared_ptr<Model_Data> aData =
+ std::dynamic_pointer_cast<Model_Data>(theFeature->data());
+ if (aData && !aData->refsToMe().empty()) {
+ const std::set<AttributePtr>& aRefs = aData->refsToMe();
+ std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin(), aRefLast = aRefs.end();
+ for(; aRefIt != aRefLast; aRefIt++) {
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIt)->owner());
+ if (aFeature.get() != NULL)
+ theRefs.insert(aFeature);
+ }
+ }
+
+ if (!theRefs.empty() && isSendError) {
+ Events_Error::send(
+ "Feature '" + theFeature->data()->name() + "' is used and can not be deleted");
+ }
+}
+
+void Model_Objects::removeFeature(FeaturePtr theFeature)
+{
+ std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theFeature->data());
+ if (aData) {
+ TDF_Label aFeatureLabel = aData->label().Father();
+ if (myFeatures.IsBound(aFeatureLabel))
+ myFeatures.UnBind(aFeatureLabel);
+ else
+ return; // not found feature => do not remove
+
+ clearHistory(theFeature);
+ // checking that the sub-element of composite feature is removed: if yes, inform the owner
+ std::set<std::shared_ptr<ModelAPI_Feature> > aRefs;
+ refsToFeature(theFeature, aRefs, false);
+ std::set<std::shared_ptr<ModelAPI_Feature> >::iterator aRefIter = aRefs.begin();
+ for(; aRefIter != aRefs.end(); aRefIter++) {
+ std::shared_ptr<ModelAPI_CompositeFeature> aComposite =
+ std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aRefIter);
+ if (aComposite.get()) {
+ aComposite->removeFeature(theFeature);
+ }
+ }
+ // erase fields
+ theFeature->erase();
+ static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ ModelAPI_EventCreator::get()->sendUpdated(theFeature, EVENT_DISP);
+ // erase all attributes under the label of feature
+ aFeatureLabel.ForgetAllAttributes();
+ // remove it from the references array
+ RemoveFromRefArray(featuresLabel(), aFeatureLabel);
+ // event: feature is deleted
+ ModelAPI_EventCreator::get()->sendDeleted(theFeature->document(), ModelAPI_Feature::group());
+ // the redisplay signal should be flushed in order to erase the feature presentation in the viewer
+ Events_Loop::loop()->flush(EVENT_DISP);
+ updateHistory(ModelAPI_Feature::group());
+ }
+}
+
+void Model_Objects::clearHistory(ObjectPtr theObj)
+{
+ if (theObj) {
+ const std::string aGroup = theObj->groupName();
+ std::map<std::string, std::vector<ObjectPtr> >::iterator aHIter = myHistory.find(aGroup);
+ if (aHIter != myHistory.end())
+ myHistory.erase(aHIter); // erase from map => this means that it is not synchronized
+ if (theObj->groupName() == ModelAPI_Feature::group()) { // clear results group of the feature
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
+ if (aFeature->firstResult().get())
+ clearHistory(aFeature->firstResult());
+ }
+ }
+}
+
+void Model_Objects::createHistory(const std::string& theGroupID)
+{
+ std::map<std::string, std::vector<ObjectPtr> >::iterator aHIter = myHistory.find(theGroupID);
+ if (aHIter == myHistory.end()) {
+ myHistory[theGroupID] = std::vector<ObjectPtr>();
+ std::vector<ObjectPtr>& aResult = myHistory[theGroupID];
+ // iterate the array of references and get feature by feature from the array
+ bool isFeature = theGroupID == ModelAPI_Feature::group();
+ Handle(TDataStd_ReferenceArray) aRefs;
+ if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+ for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) {
+ FeaturePtr aFeature = feature(aRefs->Value(a));
+ if (aFeature.get()) {
+ if (isFeature) { // here may be also disabled features
+ if (aFeature->isInHistory()) {
+ aResult.push_back(aFeature);
+ }
+ } else if (!aFeature->isDisabled()) { // iterate all results of not-disabled feature
+ const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+ std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+ for (; aRIter != aResults.cend(); aRIter++) {
+ ResultPtr aRes = *aRIter;
+ if (aRes->groupName() != theGroupID) break; // feature have only same group results
+ if (!aRes->isDisabled() && aRes->isInHistory() && !aRes->isConcealed()) {
+ aResult.push_back(*aRIter);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void Model_Objects::updateHistory(const std::shared_ptr<ModelAPI_Object> theObject)
+{
+ clearHistory(theObject);
+}
+
+void Model_Objects::updateHistory(const std::string theGroup)
+{
+ std::map<std::string, std::vector<ObjectPtr> >::iterator aHIter = myHistory.find(theGroup);
+ if (aHIter != myHistory.end())
+ myHistory.erase(aHIter); // erase from map => this means that it is not synchronized
+}
+
+FeaturePtr Model_Objects::feature(TDF_Label theLabel) const
+{
+ if (myFeatures.IsBound(theLabel))
+ return myFeatures.Find(theLabel);
+ return FeaturePtr(); // not found
+}
+
+ObjectPtr Model_Objects::object(TDF_Label theLabel)
+{
+ // try feature by label
+ FeaturePtr aFeature = feature(theLabel);
+ if (aFeature)
+ return feature(theLabel);
+ TDF_Label aFeatureLabel = theLabel.Father().Father(); // let's suppose it is result
+ aFeature = feature(aFeatureLabel);
+ if (aFeature) {
+ const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+ std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.cbegin();
+ for (; aRIter != aResults.cend(); aRIter++) {
+ std::shared_ptr<Model_Data> aResData = std::dynamic_pointer_cast<Model_Data>(
+ (*aRIter)->data());
+ if (aResData->label().Father().IsEqual(theLabel))
+ return *aRIter;
+ }
+ }
+ return FeaturePtr(); // not found
+}
+
+ObjectPtr Model_Objects::object(const std::string& theGroupID, const int theIndex)
+{
+ createHistory(theGroupID);
+ return myHistory[theGroupID][theIndex];
+}
+
+std::shared_ptr<ModelAPI_Object> Model_Objects::objectByName(
+ const std::string& theGroupID, const std::string& theName)
+{
+ createHistory(theGroupID);
+ std::vector<ObjectPtr>& allObjs = myHistory[theGroupID];
+ std::vector<ObjectPtr>::iterator anObjIter = allObjs.begin();
+ for(; anObjIter != allObjs.end(); anObjIter++) {
+ if ((*anObjIter)->data()->name() == theName)
+ return *anObjIter;
+ }
+ // not found
+ return ObjectPtr();
+}
+
+const int Model_Objects::index(std::shared_ptr<ModelAPI_Object> theObject)
+{
+ std::string aGroup = theObject->groupName();
+ createHistory(aGroup);
+ std::vector<ObjectPtr>& allObjs = myHistory[aGroup];
+ std::vector<ObjectPtr>::iterator anObjIter = allObjs.begin(); // iterate to search object
+ for(int anIndex = 0; anObjIter != allObjs.end(); anObjIter++, anIndex++) {
+ if ((*anObjIter) == theObject)
+ return anIndex;
+ }
+ // not found
+ return -1;
+}
+
+int Model_Objects::size(const std::string& theGroupID)
+{
+ createHistory(theGroupID);
+ return myHistory[theGroupID].size();
+}
+
+void Model_Objects::allResults(const std::string& theGroupID, std::list<ResultPtr>& theResults)
+{
+ // iterate the array of references and get feature by feature from the array
+ Handle(TDataStd_ReferenceArray) aRefs;
+ if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+ for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) {
+ FeaturePtr aFeature = feature(aRefs->Value(a));
+ if (aFeature.get()) {
+ const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+ std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+ for (; aRIter != aResults.cend(); aRIter++) {
+ ResultPtr aRes = *aRIter;
+ if (aRes->groupName() != theGroupID) break; // feature have only same group results
+ if (aRes->isInHistory() && !aRes->isConcealed()) {
+ theResults.push_back(*aRIter);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+TDF_Label Model_Objects::featuresLabel() const
+{
+ return myMain.FindChild(TAG_OBJECTS);
+}
+
+void Model_Objects::setUniqueName(FeaturePtr theFeature)
+{
+ if (!theFeature->data()->name().empty())
+ return; // not needed, name is already defined
+ std::string aName; // result
+ // first count all features of such kind to start with index = count + 1
+ int aNumObjects = 0;
+ NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFIter(myFeatures);
+ for (; aFIter.More(); aFIter.Next()) {
+ if (aFIter.Value()->getKind() == theFeature->getKind())
+ aNumObjects++;
+ }
+ // generate candidate name
+ std::stringstream aNameStream;
+ aNameStream << theFeature->getKind() << "_" << aNumObjects + 1;
+ aName = aNameStream.str();
+ // check this is unique, if not, increase index by 1
+ for (aFIter.Initialize(myFeatures); aFIter.More();) {
+ FeaturePtr aFeature = aFIter.Value();
+ bool isSameName = aFeature->data()->name() == aName;
+ if (!isSameName) { // check also results to avoid same results names (actual for Parts)
+ const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+ std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+ for (; aRIter != aResults.cend(); aRIter++) {
+ isSameName = (*aRIter)->data()->name() == aName;
+ }
+ }
+ if (isSameName) {
+ aNumObjects++;
+ std::stringstream aNameStream;
+ aNameStream << theFeature->getKind() << "_" << aNumObjects + 1;
+ aName = aNameStream.str();
+ // reinitialize iterator to make sure a new name is unique
+ aFIter.Initialize(myFeatures);
+ } else
+ aFIter.Next();
+ }
+ theFeature->data()->setName(aName);
+}
+
+void Model_Objects::initData(ObjectPtr theObj, TDF_Label theLab, const int theTag)
+{
+ std::shared_ptr<Model_Data> aData(new Model_Data);
+ aData->setLabel(theLab.FindChild(theTag));
+ aData->setObject(theObj);
+ theObj->setDoc(myDoc);
+ theObj->setData(aData);
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
+ if (aFeature) {
+ setUniqueName(aFeature); // must be before "initAttributes" because duplicate part uses name
+ }
+ theObj->initAttributes();
+}
+
+void Model_Objects::synchronizeFeatures(
+ const bool theMarkUpdated, const bool theUpdateReferences, const bool theFlush)
+{
+ Model_Document* anOwner = std::dynamic_pointer_cast<Model_Document>(myDoc).get();
+ if (!anOwner) // this may happen on creation of document: nothing there, so nothing to synchronize
+ return;
+ // after all updates, sends a message that groups of features were created or updated
+ Events_Loop* aLoop = Events_Loop::loop();
+ static Events_ID aDispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ static Events_ID aCreateEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
+ static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+ static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ static Events_ID aDeleteEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
+ static Events_ID aToHideEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ aLoop->activateFlushes(false);
+
+ // update all objects by checking are they on labels or not
+ std::set<FeaturePtr> aNewFeatures, aKeptFeatures;
+ TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
+ for (; aLabIter.More(); aLabIter.Next()) {
+ TDF_Label aFeatureLabel = aLabIter.Value()->Label();
+ FeaturePtr aFeature;
+ if (!myFeatures.IsBound(aFeatureLabel)) { // a new feature is inserted
+ // create a feature
+ aFeature = std::dynamic_pointer_cast<Model_Session>(ModelAPI_Session::get())->createFeature(
+ TCollection_AsciiString(Handle(TDataStd_Comment)::DownCast(aLabIter.Value())->Get())
+ .ToCString(), anOwner);
+ if (!aFeature) { // somethig is wrong, most probably, the opened document has invalid structure
+ Events_Error::send("Invalid type of object in the document");
+ aLabIter.Value()->Label().ForgetAllAttributes();
+ continue;
+ }
+ // this must be before "setData" to redo the sketch line correctly
+ myFeatures.Bind(aFeatureLabel, aFeature);
+ aNewFeatures.insert(aFeature);
+ initData(aFeature, aFeatureLabel, TAG_FEATURE_ARGUMENTS);
+ updateHistory(aFeature);
+ aFeature->setDisabled(false); // by default created feature is enabled (this allows to recreate the results before "setCurrent" is called)
+
+ // event: model is updated
+ ModelAPI_EventCreator::get()->sendUpdated(aFeature, aCreateEvent);
+ } else { // nothing is changed, both iterators are incremented
+ aFeature = myFeatures.Find(aFeatureLabel);
+ aKeptFeatures.insert(aFeature);
+ if (theMarkUpdated) {
+ ModelAPI_EventCreator::get()->sendUpdated(aFeature, anUpdateEvent);
+ }
+ }
+ }
+ // update results of the features (after features created because they may be connected, like sketch and sub elements)
+ std::list<FeaturePtr> aComposites; // composites must be updated after their subs (issue 360)
+ TDF_ChildIDIterator aLabIter2(featuresLabel(), TDataStd_Comment::GetID());
+ for (; aLabIter2.More(); aLabIter2.Next()) {
+ TDF_Label aFeatureLabel = aLabIter2.Value()->Label();
+ if (myFeatures.IsBound(aFeatureLabel)) { // a new feature is inserted
+ FeaturePtr aFeature = myFeatures.Find(aFeatureLabel);
+ if (std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeature).get())
+ aComposites.push_back(aFeature);
+ updateResults(aFeature);
+ }
+ }
+ std::list<FeaturePtr>::iterator aComposite = aComposites.begin();
+ for(; aComposite != aComposites.end(); aComposite++) {
+ updateResults(*aComposite);
+ }
+
+ // check all features are checked: if not => it was removed
+ NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFIter(myFeatures);
+ while (aFIter.More()) {
+ if (aKeptFeatures.find(aFIter.Value()) == aKeptFeatures.end()
+ && aNewFeatures.find(aFIter.Value()) == aNewFeatures.end()) {
+ FeaturePtr aFeature = aFIter.Value();
+ // event: model is updated
+ //if (aFeature->isInHistory()) {
+ ModelAPI_EventCreator::get()->sendDeleted(myDoc, ModelAPI_Feature::group());
+ //}
+ // results of this feature must be redisplayed (hided)
+ // redisplay also removed feature (used for sketch and AISObject)
+ ModelAPI_EventCreator::get()->sendUpdated(aFeature, aRedispEvent);
+ updateHistory(aFeature);
+ aFeature->erase();
+ // unbind after the "erase" call: on abort sketch is removes sub-objects that corrupts aFIter
+ myFeatures.UnBind(aFIter.Key());
+ // reinitialize iterator because unbind may corrupt the previous order in the map
+ aFIter.Initialize(myFeatures);
+ } else
+ aFIter.Next();
+ }
+
+ if (theUpdateReferences) {
+ synchronizeBackRefs();
+ }
+ if (theMarkUpdated) { // this means there is no control what was modified => remove history cash
+ myHistory.clear();
+ }
+
+ anOwner->executeFeatures() = false;
+ aLoop->activateFlushes(true);
+
+ if (theFlush) {
+ aLoop->flush(aCreateEvent);
+ aLoop->flush(aDeleteEvent);
+ aLoop->flush(anUpdateEvent);
+ aLoop->flush(aRedispEvent);
+ aLoop->flush(aToHideEvent);
+ }
+ anOwner->executeFeatures() = true;
+}
+
+void Model_Objects::synchronizeBackRefs()
+{
+ // keeps the concealed flags of result to catch the change and create created/deleted events
+ std::list<std::pair<ResultPtr, bool> > aConcealed;
+ // first cycle: erase all data about back-references
+ NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFeatures(myFeatures);
+ for(; aFeatures.More(); aFeatures.Next()) {
+ FeaturePtr aFeature = aFeatures.Value();
+ std::shared_ptr<Model_Data> aFData =
+ std::dynamic_pointer_cast<Model_Data>(aFeature->data());
+ if (aFData) {
+ aFData->eraseBackReferences();
+ }
+ const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+ std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+ for (; aRIter != aResults.cend(); aRIter++) {
+ std::shared_ptr<Model_Data> aResData =
+ std::dynamic_pointer_cast<Model_Data>((*aRIter)->data());
+ if (aResData) {
+ aConcealed.push_back(std::pair<ResultPtr, bool>(*aRIter, (*aRIter)->isConcealed()));
+ aResData->eraseBackReferences();
+ }
+ }
+ }
+
+ // second cycle: set new back-references: only features may have reference, iterate only them
+ ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
+ for(aFeatures.Initialize(myFeatures); aFeatures.More(); aFeatures.Next()) {
+ FeaturePtr aFeature = aFeatures.Value();
+ std::shared_ptr<Model_Data> aFData =
+ std::dynamic_pointer_cast<Model_Data>(aFeature->data());
+ if (aFData) {
+ std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
+ aFData->referencesToObjects(aRefs);
+ std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator
+ aRefsIter = aRefs.begin();
+ for(; aRefsIter != aRefs.end(); aRefsIter++) {
+ std::list<ObjectPtr>::iterator aRefTo = aRefsIter->second.begin();
+ for(; aRefTo != aRefsIter->second.end(); aRefTo++) {
+ if (*aRefTo) {
+ std::shared_ptr<Model_Data> aRefData =
+ std::dynamic_pointer_cast<Model_Data>((*aRefTo)->data());
+ aRefData->addBackReference(aFeature, aRefsIter->first); // here the Concealed flag is updated
+ // update enable/disable status: the nested status must be equal to the composite
+ CompositeFeaturePtr aComp =
+ std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeature);
+ if (aComp.get()) {
+ FeaturePtr aReferenced = std::dynamic_pointer_cast<ModelAPI_Feature>(*aRefTo);
+ if (aReferenced.get()) {
+ aReferenced->setDisabled(aComp->isDisabled());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ std::list<std::pair<ResultPtr, bool> >::iterator aCIter = aConcealed.begin();
+ for(; aCIter != aConcealed.end(); aCIter++) {
+ if (aCIter->first->isConcealed() != aCIter->second) { // somethign is changed => produce event
+ if (aCIter->second) { // was concealed become not => creation event
+ static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
+ ModelAPI_EventCreator::get()->sendUpdated(aCIter->first, anEvent);
+ } else { // was not concealed become concealed => delete event
+ ModelAPI_EventCreator::get()->sendDeleted(myDoc, 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);
+ }
+ }
+ }
+}
+
+TDF_Label Model_Objects::resultLabel(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theResultIndex)
+{
+ const std::shared_ptr<Model_Data>& aData =
+ std::dynamic_pointer_cast<Model_Data>(theFeatureData);
+ return aData->label().Father().FindChild(TAG_FEATURE_RESULTS).FindChild(theResultIndex + 1);
+}
+
+void Model_Objects::storeResult(std::shared_ptr<ModelAPI_Data> theFeatureData,
+ std::shared_ptr<ModelAPI_Result> theResult,
+ const int theResultIndex)
+{
+ theResult->setDoc(myDoc);
+ initData(theResult, resultLabel(theFeatureData, theResultIndex), TAG_FEATURE_ARGUMENTS);
+ if (theResult->data()->name().empty()) { // if was not initialized, generate event and set a name
+ std::stringstream aNewName;
+ aNewName<<theFeatureData->name();
+ if (theResultIndex > 0) // if there are several results, add unique prefix starting from second
+ aNewName<<"_"<<theResultIndex + 1;
+ theResult->data()->setName(aNewName.str());
+ }
+}
+
+std::shared_ptr<ModelAPI_ResultConstruction> Model_Objects::createConstruction(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
+{
+ TDF_Label aLab = resultLabel(theFeatureData, theIndex);
+ TDataStd_Comment::Set(aLab, ModelAPI_ResultConstruction::group().c_str());
+ ObjectPtr anOldObject = object(aLab);
+ std::shared_ptr<ModelAPI_ResultConstruction> aResult;
+ if (anOldObject) {
+ aResult = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(anOldObject);
+ }
+ if (!aResult) {
+ aResult = std::shared_ptr<ModelAPI_ResultConstruction>(new Model_ResultConstruction);
+ storeResult(theFeatureData, aResult, theIndex);
+ }
+ return aResult;
+}
+
+std::shared_ptr<ModelAPI_ResultBody> Model_Objects::createBody(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
+{
+ TDF_Label aLab = resultLabel(theFeatureData, theIndex);
+ TDataStd_Comment::Set(aLab, ModelAPI_ResultBody::group().c_str());
+ ObjectPtr anOldObject = object(aLab);
+ std::shared_ptr<ModelAPI_ResultBody> aResult;
+ if (anOldObject) {
+ aResult = std::dynamic_pointer_cast<ModelAPI_ResultBody>(anOldObject);
+ }
+ if (!aResult) {
+ aResult = std::shared_ptr<ModelAPI_ResultBody>(new Model_ResultBody);
+ storeResult(theFeatureData, aResult, theIndex);
+ }
+ return aResult;
+}
+
+std::shared_ptr<ModelAPI_ResultPart> Model_Objects::createPart(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
+{
+ TDF_Label aLab = resultLabel(theFeatureData, theIndex);
+ TDataStd_Comment::Set(aLab, ModelAPI_ResultPart::group().c_str());
+ ObjectPtr anOldObject = object(aLab);
+ std::shared_ptr<ModelAPI_ResultPart> aResult;
+ if (anOldObject) {
+ aResult = std::dynamic_pointer_cast<ModelAPI_ResultPart>(anOldObject);
+ }
+ if (!aResult) {
+ aResult = std::shared_ptr<ModelAPI_ResultPart>(new Model_ResultPart);
+ storeResult(theFeatureData, aResult, theIndex);
+ }
+ return aResult;
+}
+
+std::shared_ptr<ModelAPI_ResultGroup> Model_Objects::createGroup(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
+{
+ TDF_Label aLab = resultLabel(theFeatureData, theIndex);
+ TDataStd_Comment::Set(aLab, ModelAPI_ResultGroup::group().c_str());
+ ObjectPtr anOldObject = object(aLab);
+ std::shared_ptr<ModelAPI_ResultGroup> aResult;
+ if (anOldObject) {
+ aResult = std::dynamic_pointer_cast<ModelAPI_ResultGroup>(anOldObject);
+ }
+ if (!aResult) {
+ aResult = std::shared_ptr<ModelAPI_ResultGroup>(new Model_ResultGroup(theFeatureData));
+ storeResult(theFeatureData, aResult, theIndex);
+ }
+ return aResult;
+}
+
+std::shared_ptr<ModelAPI_ResultParameter> Model_Objects::createParameter(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
+{
+ TDF_Label aLab = resultLabel(theFeatureData, theIndex);
+ TDataStd_Comment::Set(aLab, ModelAPI_ResultParameter::group().c_str());
+ ObjectPtr anOldObject = object(aLab);
+ std::shared_ptr<ModelAPI_ResultParameter> aResult;
+ if (anOldObject) {
+ aResult = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(anOldObject);
+ }
+ if (!aResult) {
+ aResult = std::shared_ptr<ModelAPI_ResultParameter>(new Model_ResultParameter);
+ storeResult(theFeatureData, aResult, theIndex);
+ }
+ return aResult;
+}
+
+std::shared_ptr<ModelAPI_Feature> Model_Objects::feature(
+ const std::shared_ptr<ModelAPI_Result>& theResult)
+{
+ std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theResult->data());
+ if (aData) {
+ TDF_Label aFeatureLab = aData->label().Father().Father().Father();
+ return feature(aFeatureLab);
+ }
+ return FeaturePtr();
+}
+
+void Model_Objects::updateResults(FeaturePtr theFeature)
+{
+ // for not persistent is will be done by parametric updater automatically
+ //if (!theFeature->isPersistentResult()) return;
+ // check the existing results and remove them if there is nothing on the label
+ std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
+ while(aResIter != theFeature->results().cend()) {
+ ResultPtr aBody = std::dynamic_pointer_cast<ModelAPI_Result>(*aResIter);
+ if (aBody) {
+ if (!aBody->data()->isValid()) {
+ // found a disappeared result => remove it
+ theFeature->removeResult(aBody);
+ // start iterate from beginning because iterator is corrupted by removing
+ aResIter = theFeature->results().cbegin();
+ continue;
+ }
+ }
+ aResIter++;
+ }
+ // it may be on undo
+ if (!theFeature->data() || !theFeature->data()->isValid() || theFeature->isDisabled())
+ return;
+ // check that results are presented on all labels
+ int aResSize = theFeature->results().size();
+ TDF_ChildIterator aLabIter(resultLabel(theFeature->data(), 0).Father());
+ for(; aLabIter.More(); aLabIter.Next()) {
+ // here must be GUID of the feature
+ int aResIndex = aLabIter.Value().Tag() - 1;
+ ResultPtr aNewBody;
+ if (aResSize <= aResIndex) {
+ TDF_Label anArgLab = aLabIter.Value();
+ Handle(TDataStd_Comment) aGroup;
+ if (anArgLab.FindAttribute(TDataStd_Comment::GetID(), aGroup)) {
+ if (aGroup->Get() == ModelAPI_ResultBody::group().c_str()) {
+ aNewBody = createBody(theFeature->data(), aResIndex);
+ } else if (aGroup->Get() == ModelAPI_ResultPart::group().c_str()) {
+ //aNewBody = createPart(theFeature->data(), aResIndex);
+ theFeature->execute(); // create the part result
+ break;
+ } else if (aGroup->Get() == ModelAPI_ResultConstruction::group().c_str()) {
+ theFeature->execute(); // construction shapes are needed for sketch solver
+ break;
+ } else if (aGroup->Get() == ModelAPI_ResultGroup::group().c_str()) {
+ aNewBody = createGroup(theFeature->data(), aResIndex);
+ } else if (aGroup->Get() == ModelAPI_ResultParameter::group().c_str()) {
+ theFeature->attributeChanged("expression"); // just produce a value
+ break;
+ } else {
+ Events_Error::send(std::string("Unknown type of result is found in the document:") +
+ TCollection_AsciiString(aGroup->Get()).ToCString());
+ }
+ }
+ if (aNewBody) {
+ theFeature->setResult(aNewBody, aResIndex);
+ }
+ }
+ }
+}
+
+ResultPtr Model_Objects::findByName(const std::string theName)
+{
+ NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator anObjIter(myFeatures);
+ for(; anObjIter.More(); anObjIter.Next()) {
+ FeaturePtr& aFeature = anObjIter.ChangeValue();
+ if (!aFeature.get() || aFeature->isDisabled()) // may be on close
+ continue;
+ const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+ std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+ for (; aRIter != aResults.cend(); aRIter++) {
+ ResultPtr aRes = *aRIter;
+ if (aRes.get() && aRes->data() && aRes->data()->isValid() && !aRes->isDisabled() &&
+ aRes->data()->name() == theName) {
+ return aRes;
+ }
+ }
+ }
+ // not found
+ return ResultPtr();
+}
+
+FeaturePtr Model_Objects::nextFeature(FeaturePtr theCurrent, const bool theReverse)
+{
+ std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theCurrent->data());
+ if (aData) {
+ TDF_Label aFeatureLabel = aData->label().Father();
+ Handle(TDataStd_ReferenceArray) aRefs;
+ if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+ for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) { // iterate all existing features
+ if (aRefs->Value(a).IsEqual(aFeatureLabel)) {
+ a += theReverse ? -1 : 1;
+ if (a >= aRefs->Lower() && a <= aRefs->Upper())
+ return feature(aRefs->Value(a));
+ break; // finish iiteration: it's last feature
+ }
+ }
+ }
+ }
+ return FeaturePtr(); // not found, last, or something is wrong
+}
+
+FeaturePtr Model_Objects::firstFeature()
+{
+ Handle(TDataStd_ReferenceArray) aRefs;
+ if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+ return feature(aRefs->Value(aRefs->Lower()));
+ }
+ return FeaturePtr(); // no features at all
+}
+
+FeaturePtr Model_Objects::lastFeature()
+{
+ Handle(TDataStd_ReferenceArray) aRefs;
+ if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+ return feature(aRefs->Value(aRefs->Upper()));
+ }
+ return FeaturePtr(); // no features at all
+}
+
+Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper)
+{
+ return TDF_LabelMapHasher::HashCode(theLab, theUpper);
+
+}
+Standard_Boolean IsEqual(const TDF_Label& theLab1, const TDF_Label& theLab2)
+{
+ return TDF_LabelMapHasher::IsEqual(theLab1, theLab2);
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: Model_Objects.h
+// Created: 15 May 2015
+// Author: Mikhail PONIKAROV
+
+#ifndef Model_Objects_H_
+#define Model_Objects_H_
+
+#include <Model.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Result.h>
+#include <ModelAPI_ResultParameter.h>
+
+#include <TDocStd_Document.hxx>
+#include <NCollection_DataMap.hxx>
+#include <TDF_Label.hxx>
+#include <map>
+#include <set>
+#include <vector>
+
+// for TDF_Label map usage
+static Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper);
+static Standard_Boolean IsEqual(const TDF_Label& theLab1, const TDF_Label& theLab2);
+
+/**\class Model_Objects
+ * \ingroup DataModel
+ * \brief Manager of objects of the document. Normally one this class corresponds to
+ * one document and just helper to manage objects (ModelAPI_Objects) inside of the document
+ * on the level of data storage.
+ */
+class Model_Objects
+{
+ public:
+ //! Registers the fieature in the data structure
+ //! \param theFeature feature that must be added to the data structure
+ //! \param theAfterThis the feature will be added after this feature;
+ //! if it is null, the added feature will be the first
+ void addFeature(FeaturePtr theFeature, const FeaturePtr theAfterThis);
+
+ //! Return a list of features, which refers to the feature
+ //! \param theFeature a feature
+ //! \param theRefs a list of reference features
+ //! \param isSendError a flag whether the error message should be send
+ void refsToFeature(FeaturePtr theFeature,
+ std::set<FeaturePtr>& theRefs,
+ const bool isSendError = true);
+
+ //! Removes the feature from the document (with result)
+ //! \param theFeature a removed feature
+ void removeFeature(FeaturePtr theFeature);
+
+ //! Returns the existing feature by the label
+ //! \param theLabel base label of the feature
+ FeaturePtr feature(TDF_Label theLabel) const;
+
+ //! Returns the existing object: result or feature
+ //! \param theLabel base label of the object
+ ObjectPtr object(TDF_Label theLabel);
+
+ //! Returns the first found object in the group by the object name
+ //! \param theGroupID group that contains an object
+ //! \param theName name of the object to search
+ //! \returns null if such object is not found
+ std::shared_ptr<ModelAPI_Object> objectByName(
+ const std::string& theGroupID, const std::string& theName);
+
+ //! Returns the result by the result name
+ ResultPtr Model_Objects::findByName(const std::string theName);
+
+
+ //! Returns the object index in the group. Object must be visible. Otherwise returns -1.
+ //! \param theObject object of this document
+ //! \returns index started from zero, or -1 if object is invisible or belongs to another document
+ const int index(std::shared_ptr<ModelAPI_Object> theObject);
+
+ //! Returns the feature in the group by the index (started from zero)
+ //! \param theGroupID group that contains a feature
+ //! \param theIndex zero-based index of feature in the group
+ ObjectPtr object(const std::string& theGroupID, const int theIndex);
+
+ //! Returns the number of features in the group
+ int size(const std::string& theGroupID);
+
+ ///! Returns all (and disabled) results of the given type. Not fast method (iterates all features).
+ void allResults(const std::string& theGroupID, std::list<ResultPtr>& theResults);
+
+ /// Creates a construction cresults
+ std::shared_ptr<ModelAPI_ResultConstruction> createConstruction(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
+ /// Creates a body results
+ std::shared_ptr<ModelAPI_ResultBody> createBody(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
+ /// Creates a part results
+ std::shared_ptr<ModelAPI_ResultPart> createPart(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
+ /// Creates a group results
+ std::shared_ptr<ModelAPI_ResultGroup> createGroup(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
+
+ std::shared_ptr<ModelAPI_ResultParameter> createParameter(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
+
+ //! Returns a feature by result (owner of result)
+ std::shared_ptr<ModelAPI_Feature>
+ feature(const std::shared_ptr<ModelAPI_Result>& theResult);
+
+ //! Sets the owner of this manager
+ void setOwner(DocumentPtr theDoc);
+
+ //! Returns the owner of this manager
+ DocumentPtr owner() {return myDoc;}
+
+ //! Deletes all managed features wit hemmitting of corresponded signal
+ ~Model_Objects();
+
+ protected:
+
+ //! Returns (creates if needed) the features label
+ TDF_Label featuresLabel() const;
+
+ //! Initializes feature with a unique name in this group (unique name is generated as
+ //! feature type + "_" + index
+ void setUniqueName(FeaturePtr theFeature);
+
+ //! Synchronizes myFeatures list with the updated document
+ //! \param theMarkUpdated causes the "update" event for all features
+ //! \param theUpdateReferences causes the update of back-references
+ //! \param theFlush makes flush all events in the end of all modifications of this method
+ void synchronizeFeatures(const bool theMarkUpdated, const bool theUpdateReferences,
+ const bool theFlush);
+ //! Synchronizes the BackReferences list in Data of Features and Results
+ void synchronizeBackRefs();
+
+ //! Creates manager on the OCAF document main label
+ Model_Objects(TDF_Label theMainLab);
+
+ //! Initializes the data fields of the feature
+ void initData(ObjectPtr theObj, TDF_Label theLab, const int theTag);
+
+ //! Allows to store the result in the data tree of the document (attaches 'data' of result to tree)
+ void storeResult(std::shared_ptr<ModelAPI_Data> theFeatureData,
+ std::shared_ptr<ModelAPI_Result> theResult,
+ const int theResultIndex = 0);
+
+ //! returns the label of result by index; creates this label if it was not created before
+ TDF_Label resultLabel(const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theResultIndex);
+
+ //! Updates the results list of the feature basing on the current data tree
+ void updateResults(FeaturePtr theFeature);
+
+ /// Internally makes document know that feature was removed or added in history after creation
+ void updateHistory(const std::shared_ptr<ModelAPI_Object> theObject);
+
+ /// Internally makes document know that feature was removed or added in history after creation
+ void updateHistory(const std::string theGroup);
+
+ /// Clears the history arrays related to this object
+ void clearHistory(ObjectPtr theObj);
+
+ /// Creates the history: up to date with the current state
+ void createHistory(const std::string& theGroupID);
+
+ /// Returns to the next (from the history point of view) feature, any: invisible or disabled
+ /// \param theReverse if it is true, iterates in reverced order (next becomes previous)
+ FeaturePtr nextFeature(FeaturePtr theCurrent, const bool theReverse = false);
+ /// Returns to the first (from the history point of view) feature, any: invisible or disabled
+ FeaturePtr firstFeature();
+ /// Returns to the last (from the history point of view) feature, any: invisible or disabled
+ FeaturePtr lastFeature();
+
+ private:
+ TDF_Label myMain; ///< main label of the data storage
+
+ DocumentPtr myDoc; ///< doc,ument, owner of this objects manager: needed for events creation
+
+ /// All managed features (not only in history of OB)
+ /// For optimization mapped by labels
+ NCollection_DataMap<TDF_Label, FeaturePtr> myFeatures;
+
+ /// Map from group id to the array that contains all objects located in history.
+ /// Each array is updated by demand from scratch, by browing all the features in the history.
+ std::map<std::string, std::vector<ObjectPtr> > myHistory;
+
+ friend class Model_Document;
+ friend class Model_Session;
+ friend class Model_Update;
+ friend class Model_AttributeReference;
+ friend class Model_AttributeRefAttr;
+ friend class Model_AttributeRefList;
+};
+
+#endif
#include <ModelAPI_AttributeIntArray.h>
#include <TNaming_Builder.hxx>
#include <TNaming_NamedShape.hxx>
+#include <TNaming_Iterator.hxx>
#include <TDataStd_Name.hxx>
+#include <TDataStd_Integer.hxx>
#include <TopoDS.hxx>
-#include <TopoDS_Shape.hxx>
#include <TopoDS_Face.hxx>
#include <TDF_ChildIterator.hxx>
#include <TopTools_MapOfShape.hxx>
}
void Model_ResultBody::colorConfigInfo(std::string& theSection, std::string& theName,
- std::string& theDefault)
+ std::string& theDefault)
{
theSection = "Visualization";
theName = "result_body_color";
theDefault = DEFAULT_COLOR();
}
+// Converts evolution of naming shape to selection evelution and back to avoid
+// naming support on the disabled results. Deeply in the labels tree, recursively.
+static void EvolutionToSelection(TDF_Label theLab, const bool theFlag) {
+ std::list<std::pair<TopoDS_Shape, TopoDS_Shape> > aShapePairs; // to store old and new shapes
+ Handle(TNaming_NamedShape) aName;
+ int anEvolution = -1;
+ if (theLab.FindAttribute(TNaming_NamedShape::GetID(), aName)) {
+ anEvolution = (int)(aName->Evolution());
+ for(TNaming_Iterator anIter(aName); anIter.More(); anIter.Next()) {
+ aShapePairs.push_back(std::pair<TopoDS_Shape, TopoDS_Shape>
+ (anIter.OldShape(), anIter.NewShape()));
+ }
+ }
+ // remove old
+ theLab.ForgetAttribute(TNaming_NamedShape::GetID());
+ // create new
+ TNaming_Builder aBuilder(theLab);
+ TNaming_Evolution anEvol = (TNaming_Evolution)(anEvolution);
+ std::list<std::pair<TopoDS_Shape, TopoDS_Shape> >::iterator aPairsIter = aShapePairs.begin();
+ for(; aPairsIter != aShapePairs.end(); aPairsIter++) {
+ if (theFlag) { // disabled => make selection
+ aBuilder.Select(aPairsIter->first, aPairsIter->second);
+ } else if (anEvol == TNaming_GENERATED) {
+ aBuilder.Generated(aPairsIter->first, aPairsIter->second);
+ } else if (anEvol == TNaming_MODIFY) {
+ aBuilder.Modify(aPairsIter->first, aPairsIter->second);
+ } else if (anEvol == TNaming_DELETE) {
+ aBuilder.Delete(aPairsIter->first);
+ } else if (anEvol == TNaming_PRIMITIVE) {
+ aBuilder.Generated(aPairsIter->first, aPairsIter->second);
+ }
+ }
+ // recursive call for all sub-labels
+ TDF_ChildIterator anIter(theLab, Standard_False);
+ for(; anIter.More(); anIter.Next()) {
+ EvolutionToSelection(anIter.Value(), theFlag);
+ }
+}
+
+bool Model_ResultBody::setDisabled(std::shared_ptr<ModelAPI_Result> theThis, const bool theFlag)
+{
+ bool aChanged = ModelAPI_ResultBody::setDisabled(theThis, theFlag);
+ if (aChanged) { // state is changed, so modifications are needed
+ std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
+ if (!aData) // unknown case
+ return aChanged;
+ TDF_Label& aShapeLab = aData->shapeLab();
+ EvolutionToSelection(aShapeLab, theFlag);
+ }
+ return aChanged;
+}
+
void Model_ResultBody::store(const std::shared_ptr<GeomAPI_Shape>& theShape)
{
std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
return; // null shape inside
aBuilder.Generated(aShape);
- // register name
- if(!aBuilder.NamedShape()->IsEmpty()) {
- Handle(TDataStd_Name) anAttr;
- if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
- std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
- if(!aName.empty()) {
+ // register name
+ if(!aBuilder.NamedShape()->IsEmpty()) {
+ Handle(TDataStd_Name) anAttr;
+ if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
+ std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
+ if(!aName.empty()) {
std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(document());
aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName);
- }
- }
- }
+ }
+ }
+ }
}
}
if (aShapeNew.IsNull())
return; // null shape inside
aBuilder.Generated(aShapeBasis, aShapeNew);
- // register name
- if(!aBuilder.NamedShape()->IsEmpty()) {
- Handle(TDataStd_Name) anAttr;
- if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
- std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
- if(!aName.empty()) {
+ // register name
+ if(!aBuilder.NamedShape()->IsEmpty()) {
+ Handle(TDataStd_Name) anAttr;
+ if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
+ std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
+ if(!aName.empty()) {
std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(document());
aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName);
- }
- }
- }
+ }
+ }
+ }
}
}
TopoDS_Shape aShapeNew = theNewShape->impl<TopoDS_Shape>();
if (aShapeNew.IsNull())
return; // null shape inside
- aBuilder.Modify(aShapeOld, aShapeNew);
+ aBuilder.Modify(aShapeOld, aShapeNew);
}
}
ListOfShape aList;
std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
aRShape->setImpl((new TopoDS_Shape(aRoot)));
- theMS->modified(aRShape, aList);
+ theMS->modified(aRShape, aList);
std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator anIt = aList.begin(), aLast = aList.end();
for (; anIt != aLast; anIt++) {
TopoDS_Shape aNewShape = (*anIt)->impl<TopoDS_Shape>();
}
if (!aRoot.IsSame (aNewShape)) {
builder(theTag)->Modify(aRoot,aNewShape);
- if(!isBuilt)
- buildName(theTag, theName);
- }
+ if(!isBuilt)
+ buildName(theTag, theName);
+ }
}
}
}
}
if (!aRoot.IsSame (aNewShape)) {
builder(theTag)->Generated(aRoot,aNewShape);
- if(!isBuilt)
- buildName(theTag, theName);
- }
+ if(!isBuilt)
+ buildName(theTag, theName);
+ }
}
}
}
//=======================================================================
int getDangleShapes(const TopoDS_Shape& theShapeIn,
- const TopAbs_ShapeEnum theGeneratedFrom,
- TopTools_DataMapOfShapeShape& theDangles)
+ const TopAbs_ShapeEnum theGeneratedFrom,
+ TopTools_DataMapOfShapeShape& theDangles)
{
theDangles.Clear();
TopTools_IndexedDataMapOfShapeListOfShape subShapeAndAncestors;
//=======================================================================
void loadGeneratedDangleShapes(
- const TopoDS_Shape& theShapeIn,
- const TopAbs_ShapeEnum theGeneratedFrom,
- TNaming_Builder * theBuilder)
+ const TopoDS_Shape& theShapeIn,
+ const TopAbs_ShapeEnum theGeneratedFrom,
+ TNaming_Builder * theBuilder)
{
TopTools_DataMapOfShapeShape dangles;
if (!getDangleShapes(theShapeIn, theGeneratedFrom, dangles)) return;
TopTools_DataMapIteratorOfDataMapOfShapeShape itr(dangles);
for (; itr.More(); itr.Next())
- theBuilder->Generated(itr.Key(), itr.Value());
+ theBuilder->Generated(itr.Key(), itr.Value());
}
//=======================================================================
void Model_ResultBody::loadNextLevels(std::shared_ptr<GeomAPI_Shape> theShape,
- const std::string& theName, int& theTag)
+ const std::string& theName, int& theTag)
{
if(theShape->isNull()) return;
TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
if (aShape.ShapeType() == TopAbs_SOLID) {
TopExp_Explorer expl(aShape, TopAbs_FACE);
for (; expl.More(); expl.Next()) {
- builder(theTag)->Generated(expl.Current());
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
- }
+ builder(theTag)->Generated(expl.Current());
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
+ }
}
else if (aShape.ShapeType() == TopAbs_SHELL || aShape.ShapeType() == TopAbs_FACE) {
// load faces and all the free edges
if (Faces.Extent() > 1 || (aShape.ShapeType() == TopAbs_SHELL && Faces.Extent() == 1)) {
TopExp_Explorer expl(aShape, TopAbs_FACE);
for (; expl.More(); expl.Next()) {
- builder(theTag)->Generated(expl.Current());
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
- }
- }
+ builder(theTag)->Generated(expl.Current());
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
+ }
+ }
TopTools_IndexedDataMapOfShapeListOfShape anEdgeAndNeighbourFaces;
TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, anEdgeAndNeighbourFaces);
for (Standard_Integer i = 1; i <= anEdgeAndNeighbourFaces.Extent(); i++)
- {
+ {
const TopTools_ListOfShape& aLL = anEdgeAndNeighbourFaces.FindFromIndex(i);
if (aLL.Extent() < 2) {
- if (BRep_Tool::Degenerated(TopoDS::Edge(anEdgeAndNeighbourFaces.FindKey(i))))
+ if (BRep_Tool::Degenerated(TopoDS::Edge(anEdgeAndNeighbourFaces.FindKey(i))))
continue;
- builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i));
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
+ builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i));
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
} else {
- TopTools_ListIteratorOfListOfShape anIter(aLL);
- const TopoDS_Face& aFace = TopoDS::Face(anIter.Value());
- anIter.Next();
- if(aFace.IsEqual(anIter.Value())) {
- builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i));
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
- }
- }
- }
+ TopTools_ListIteratorOfListOfShape anIter(aLL);
+ const TopoDS_Face& aFace = TopoDS::Face(anIter.Value());
+ anIter.Next();
+ if(aFace.IsEqual(anIter.Value())) {
+ builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i));
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
+ }
+ }
+ }
} else if (aShape.ShapeType() == TopAbs_WIRE) {
TopTools_IndexedMapOfShape Edges;
BRepTools::Map3DEdges(aShape, Edges);
if (Edges.Extent() == 1) {
- builder(++theTag)->Generated(Edges.FindKey(1));
+ builder(++theTag)->Generated(Edges.FindKey(1));
TopExp_Explorer expl(aShape, TopAbs_VERTEX);
for (; expl.More(); expl.Next()) {
- builder(theTag)->Generated(expl.Current());
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
- }
- } else {
+ builder(theTag)->Generated(expl.Current());
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
+ }
+ } else {
TopExp_Explorer expl(aShape, TopAbs_EDGE);
for (; expl.More(); expl.Next()) {
- builder(theTag)->Generated(expl.Current());
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
- }
+ builder(theTag)->Generated(expl.Current());
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
+ }
// and load generated vertices.
TopTools_DataMapOfShapeShape generated;
if (getDangleShapes(aShape, TopAbs_EDGE, generated))
- {
- TNaming_Builder* pBuilder = builder(theTag++);
- loadGeneratedDangleShapes(aShape, TopAbs_EDGE, pBuilder);
- }
- }
+ {
+ TNaming_Builder* pBuilder = builder(theTag++);
+ loadGeneratedDangleShapes(aShape, TopAbs_EDGE, pBuilder);
+ }
+ }
} else if (aShape.ShapeType() == TopAbs_EDGE) {
TopExp_Explorer expl(aShape, TopAbs_VERTEX);
for (; expl.More(); expl.Next()) {
- builder(theTag)->Generated(expl.Current());
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
- }
+ builder(theTag)->Generated(expl.Current());
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
+ }
}
}
//=======================================================================
int findAmbiguities(const TopoDS_Shape& theShapeIn,
- TopTools_ListOfShape& theList)
+ TopTools_ListOfShape& theList)
{
int aNumEdges(0);
theList.Clear();
for (Standard_Integer i = 1; i <= subShapeAndAncestors.Extent(); i++) {
const TopoDS_Shape& aKeyEdge1 = subShapeAndAncestors.FindKey(i);
const TopTools_ListOfShape& ancestors1 = subShapeAndAncestors.FindFromIndex(i);
- aMap1.Clear();
+ aMap1.Clear();
TopTools_ListIteratorOfListOfShape it(ancestors1);
- for(;it.More();it.Next()) aMap1.Add(it.Value()); // fill map with key ancestors => aKey1
- for (Standard_Integer j = 1; j <= subShapeAndAncestors.Extent(); j++) {
- if (i == j) continue;
+ for(;it.More();it.Next()) aMap1.Add(it.Value()); // fill map with key ancestors => aKey1
+ for (Standard_Integer j = 1; j <= subShapeAndAncestors.Extent(); j++) {
+ if (i == j) continue;
const TopoDS_Shape& aKeyEdge2 = subShapeAndAncestors.FindKey(j);
const TopTools_ListOfShape& ancestors2 = subShapeAndAncestors.FindFromIndex(j);
- if(ancestors1.Extent() == ancestors2.Extent() && ancestors1.Extent() > 1) {
- int aNum (ancestors2.Extent());
- TopTools_ListIteratorOfListOfShape it(ancestors2);
- for(;it.More();it.Next())
- if(aMap1.Contains(it.Value())) aNum--;
- if(aNum == 0) {
- if(aMap2.Add(aKeyEdge1))
- aKeyList.Append(aKeyEdge1);
- if(aMap2.Add(aKeyEdge2))
- aKeyList.Append(aKeyEdge2);
- }
- }
- } // at the end ==> List of edges to be named in addition
+ if(ancestors1.Extent() == ancestors2.Extent() && ancestors1.Extent() > 1) {
+ int aNum (ancestors2.Extent());
+ TopTools_ListIteratorOfListOfShape it(ancestors2);
+ for(;it.More();it.Next())
+ if(aMap1.Contains(it.Value())) aNum--;
+ if(aNum == 0) {
+ if(aMap2.Add(aKeyEdge1))
+ aKeyList.Append(aKeyEdge1);
+ if(aMap2.Add(aKeyEdge2))
+ aKeyList.Append(aKeyEdge2);
+ }
+ }
+ } // at the end ==> List of edges to be named in addition
}
aNumEdges = aKeyList.Extent();
if(aNumEdges)
- theList.Assign(aKeyList);
+ theList.Assign(aKeyList);
return aNumEdges;
}
//=======================================================================
void Model_ResultBody::loadFirstLevel(
- std::shared_ptr<GeomAPI_Shape> theShape, const std::string& theName, int& theTag)
+ std::shared_ptr<GeomAPI_Shape> theShape, const std::string& theName, int& theTag)
{
if(theShape->isNull()) return;
TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
if (aShape.ShapeType() == TopAbs_COMPOUND || aShape.ShapeType() == TopAbs_COMPSOLID) {
TopoDS_Iterator itr(aShape);
for (; itr.More(); itr.Next(),theTag++) {
- builder(theTag)->Generated(itr.Value());
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- if(!theName.empty()) buildName(theTag, aName);
+ builder(theTag)->Generated(itr.Value());
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ if(!theName.empty()) buildName(theTag, aName);
if (itr.Value().ShapeType() == TopAbs_COMPOUND ||
- itr.Value().ShapeType() == TopAbs_COMPSOLID)
- {
- std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
+ itr.Value().ShapeType() == TopAbs_COMPSOLID)
+ {
+ std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
itrShape->setImpl(new TopoDS_Shape(itr.Value()));
- loadFirstLevel(itrShape, theName, theTag);
+ loadFirstLevel(itrShape, theName, theTag);
} else {
- std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
+ std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
itrShape->setImpl(new TopoDS_Shape(itr.Value()));
- loadNextLevels(itrShape, theName, theTag);
- }
+ loadNextLevels(itrShape, theName, theTag);
+ }
}
} else {
std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
itrShape->setImpl(new TopoDS_Shape(aShape));
- loadNextLevels(itrShape, theName, theTag);
+ loadNextLevels(itrShape, theName, theTag);
}
TopTools_ListOfShape aList;
if(findAmbiguities(aShape, aList)) {
- TopTools_ListIteratorOfListOfShape it(aList);
+ TopTools_ListIteratorOfListOfShape it(aList);
for (; it.More(); it.Next(),theTag++) {
- builder(theTag)->Generated(it.Value());
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- }
+ builder(theTag)->Generated(it.Value());
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ }
}
}
//=======================================================================
void Model_ResultBody::loadDisconnectedEdges(
- std::shared_ptr<GeomAPI_Shape> theShape, const std::string& theName, int& theTag)
+ std::shared_ptr<GeomAPI_Shape> theShape, const std::string& theName, int& theTag)
{
if(theShape->isNull()) return;
TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
Standard_Boolean faceIsNew = Standard_True;
TopTools_ListIteratorOfListOfShape itrF(edgeNaborFaces.Find(anEdge));
for (; itrF.More(); itrF.Next()) {
- if (itrF.Value().IsSame(aFace)) {
- faceIsNew = Standard_False;
- break;
- }
- }
+ if (itrF.Value().IsSame(aFace)) {
+ faceIsNew = Standard_False;
+ break;
+ }
+ }
if (faceIsNew)
- edgeNaborFaces.ChangeFind(anEdge).Append(aFace);
- }
+ edgeNaborFaces.ChangeFind(anEdge).Append(aFace);
+ }
}
-/* TopTools_IndexedDataMapOfShapeListOfShape aDM;
+ /* TopTools_IndexedDataMapOfShapeListOfShape aDM;
TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, aDM);
for(int i=1; i <= aDM.Extent(); i++) {
- if(aDM.FindFromIndex(i).Extent() > 1) continue;
- if (BRep_Tool::Degenerated(TopoDS::Edge(aDM.FindKey(i))))
- continue;
- builder(theTag)->Generated(aDM.FindKey(i));
- TCollection_AsciiString aStr(theTag);
- std::string aName = theName + aStr.ToCString();
- buildName(theTag, aName);
-#ifdef DEB_IMPORT
- aName += + ".brep";
- BRepTools::Write(aDM.FindKey(i), aName.c_str());
-#endif
- theTag++;
+ if(aDM.FindFromIndex(i).Extent() > 1) continue;
+ if (BRep_Tool::Degenerated(TopoDS::Edge(aDM.FindKey(i))))
+ continue;
+ builder(theTag)->Generated(aDM.FindKey(i));
+ TCollection_AsciiString aStr(theTag);
+ std::string aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ #ifdef DEB_IMPORT
+ aName += + ".brep";
+ BRepTools::Write(aDM.FindKey(i), aName.c_str());
+ #endif
+ theTag++;
}
-*/
+ */
TopTools_MapOfShape anEdgesToDelete;
TopExp_Explorer anEx(aShape,TopAbs_EDGE);
std::string aName;
if (aList1.Extent()<2) continue;
TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itr(edgeNaborFaces);
for (; itr.More(); itr.Next()) {
- TopoDS_Shape anEdge2 = itr.Key();
- if(anEdgesToDelete.Contains(anEdge2)) continue;
- if (anEdge1.IsSame(anEdge2)) continue;
- const TopTools_ListOfShape& aList2 = itr.Value();
- // compare lists of the neighbour faces of edge1 and edge2
- if (aList1.Extent() == aList2.Extent()) {
- Standard_Integer aMatches = 0;
- for(TopTools_ListIteratorOfListOfShape aLIter1(aList1);aLIter1.More();aLIter1.Next())
- for(TopTools_ListIteratorOfListOfShape aLIter2(aList2);aLIter2.More();aLIter2.Next())
- if (aLIter1.Value().IsSame(aLIter2.Value())) aMatches++;
- if (aMatches == aList1.Extent()) {
- aC0=Standard_True;
- builder(theTag)->Generated(anEdge2);
- anEdgesToDelete.Add(anEdge2);
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
- }
- }
- }
+ TopoDS_Shape anEdge2 = itr.Key();
+ if(anEdgesToDelete.Contains(anEdge2)) continue;
+ if (anEdge1.IsSame(anEdge2)) continue;
+ const TopTools_ListOfShape& aList2 = itr.Value();
+ // compare lists of the neighbour faces of edge1 and edge2
+ if (aList1.Extent() == aList2.Extent()) {
+ Standard_Integer aMatches = 0;
+ for(TopTools_ListIteratorOfListOfShape aLIter1(aList1);aLIter1.More();aLIter1.Next())
+ for(TopTools_ListIteratorOfListOfShape aLIter2(aList2);aLIter2.More();aLIter2.Next())
+ if (aLIter1.Value().IsSame(aLIter2.Value())) aMatches++;
+ if (aMatches == aList1.Extent()) {
+ aC0=Standard_True;
+ builder(theTag)->Generated(anEdge2);
+ anEdgesToDelete.Add(anEdge2);
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
+ }
+ }
+ }
TopTools_MapIteratorOfMapOfShape itDelete(anEdgesToDelete);
for(;itDelete.More();itDelete.Next())
- edgeNaborFaces.UnBind(itDelete.Key());
+ edgeNaborFaces.UnBind(itDelete.Key());
edgeNaborFaces.UnBind(anEdge1);
- }
+ }
if (aC0) {
- builder(theTag)->Generated(anEdge1);
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
- }
+ builder(theTag)->Generated(anEdge1);
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
+ }
}
}
for (; itr.More(); itr.Next()) {
const TopTools_ListOfShape& naborEdges = itr.Value();
if (naborEdges.Extent() < 2) {
- builder(theTag)->Generated(itr.Key());
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
- }
+ builder(theTag)->Generated(itr.Key());
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
+ }
}
}
/// default color for a result body
inline static const std::string& DEFAULT_COLOR()
{
- static const std::string RESULT_BODY_COLOR("#E0A01B");
+ static const std::string RESULT_BODY_COLOR("150,150,180");
return RESULT_BODY_COLOR;
}
/// Request for initialization of data model of the result: adding all attributes
virtual void initAttributes();
- // Retuns the parameters of color definition in the resources config manager
+ /// Returns the parameters of color definition in the resources config manager
MODEL_EXPORT virtual void colorConfigInfo(std::string& theSection, std::string& theName,
std::string& theDefault);
+ /// Disables the result body: keeps the resulting shape as selection, but erases the underlaying
+ /// naming data structure if theFlag if false. Or restores everything on theFlag is true.
+ MODEL_EXPORT virtual bool setDisabled(std::shared_ptr<ModelAPI_Result> theThis,
+ const bool theFlag);
+
/// Stores the shape (called by the execution method).
MODEL_EXPORT virtual void store(const std::shared_ptr<GeomAPI_Shape>& theShape);
/// builds name for the shape kept at the specified tag
void buildName(const int theTag, const std::string& theName);
- friend class Model_Document;
+ friend class Model_Objects;
};
#endif
/// default color for a result construction
inline static const std::string& DEFAULT_COLOR()
{
- static const std::string RESULT_CONSTRUCTION_COLOR("#000000");
+ static const std::string RESULT_CONSTRUCTION_COLOR("120,120,120");
return RESULT_CONSTRUCTION_COLOR;
}
/// Makes a body on the given feature
Model_ResultConstruction();
- friend class Model_Document;
+ friend class Model_Objects;
};
#endif
/// default color for a result body
inline static const std::string& DEFAULT_COLOR()
{
- static const std::string RESULT_GROUP_COLOR("#E0A01B");
+ static const std::string RESULT_GROUP_COLOR("150,150,180");
return RESULT_GROUP_COLOR;
}
/// Request for initialization of data model of the result: adding all attributes
/// Makes a body on the given feature data
Model_ResultGroup(std::shared_ptr<ModelAPI_Data> theOwnerData);
- friend class Model_Document;
+ friend class Model_Objects;
};
#endif
protected:
Model_ResultParameter();
- friend class Model_Document;
+ friend class Model_Objects;
};
#endif
/// Returns true if document is activated (loaded into the memory)
virtual bool isActivated();
- friend class Model_Document;
+ friend class Model_Objects;
};
#endif
#include <ModelAPI_Plugin.h>
#include <Model_Data.h>
#include <Model_Document.h>
+#include <Model_Objects.h>
#include <Model_Application.h>
#include <Model_Events.h>
#include <Model_Validator.h>
bool Model_Session::load(const char* theFileName)
{
- bool aRes = ROOT_DOC->load(theFileName);
+ bool aRes = ROOT_DOC->load(theFileName, ROOT_DOC);
return aRes;
}
void Model_Session::closeAll()
{
- ROOT_DOC->close(true);
Model_Application::getApplication()->deleteAllDocuments();
+ ROOT_DOC->close(true);
}
void Model_Session::startOperation(const std::string& theId)
if (aDoc.get()) {
bool aWasChecked = myCheckTransactions;
setCheckTransactions(false);
- aDoc->synchronizeFeatures(false, true, true);
+ aDoc->objects()->synchronizeFeatures(false, true, true);
if (aWasChecked)
setCheckTransactions(true);
}
return aResult;
}
+bool Model_Session::isLoadByDemand(const std::string theDocID)
+{
+ return Model_Application::getApplication()->isLoadByDemand(theDocID);
+}
+
std::shared_ptr<ModelAPI_Document> Model_Session::copy(
std::shared_ptr<ModelAPI_Document> theSource, std::string theID)
{
aRT->SetRelocation(aSourceRoot, aTargetRoot);
TDF_CopyTool::Copy(aDS, aRT);
- aNew->synchronizeFeatures(false, true, true);
+ aNew->objects()->synchronizeFeatures(false, true, true);
return aNew;
}
/// Returns all the opened documents of the session (without postponed)
MODEL_EXPORT virtual std::list<std::shared_ptr<ModelAPI_Document> > allOpenedDocuments();
+ /// Returns true if document is not loaded yet
+ MODEL_EXPORT virtual bool isLoadByDemand(const std::string theDocID);
+
/// Registers the plugin that creates features.
/// It is obligatory for each plugin to call this function on loading to be found by
/// the plugin manager on call of the feature)
FeaturePtr createFeature(std::string theFeatureID, Model_Document* theDocOwner);
friend class Model_Document;
+ friend class Model_Objects;
};
#endif
#include <Model_Update.h>
#include <Model_Document.h>
#include <Model_Data.h>
+#include <Model_Objects.h>
#include <ModelAPI_Feature.h>
#include <ModelAPI_Data.h>
#include <ModelAPI_Document.h>
#include <ModelAPI_AttributeSelection.h>
#include <ModelAPI_AttributeSelectionList.h>
#include <ModelAPI_Result.h>
+#include <ModelAPI_ResultPart.h>
#include <ModelAPI_Validator.h>
#include <ModelAPI_CompositeFeature.h>
#include <ModelAPI_Session.h>
static const Events_ID kOpFinishEvent = aLoop->eventByName("FinishOperation");
static const Events_ID kOpAbortEvent = aLoop->eventByName("AbortOperation");
static const Events_ID kOpStartEvent = aLoop->eventByName("StartOperation");
- bool isAutomaticChanged = false;
+ bool isOperationChanged = false;
if (theMessage->eventID() == kChangedEvent) { // automatic and manual rebuild flag is changed
bool aPropVal =
Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true";
- if (aPropVal == myIsAutomatic)
- return; // nothing is changed, so nithing to do
- myIsAutomatic = aPropVal;
- if (!myIsAutomatic)
- return; // less automatization => nothing to do
- } else if (theMessage->eventID() == kRebuildEvent) { // the rebuild command
- if (myIsAutomatic == false) {
- isAutomaticChanged = true;
- myIsAutomatic = true;
+ if (aPropVal != myIsAutomatic) { // something is changed
+ myIsAutomatic = aPropVal;
+ if (myIsAutomatic) // higher level of automatization => to rebuild
+ processOperation(false);
}
+ } else if (theMessage->eventID() == kRebuildEvent) { // the rebuild command
+ processOperation(true);
} else if (theMessage->eventID() == kCreatedEvent || theMessage->eventID() == kUpdatedEvent ||
theMessage->eventID() == kMovedEvent) {
std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aMsg =
const std::set<ObjectPtr>& anObjs = aMsg->objects();
std::set<ObjectPtr>::const_iterator anObjIter = anObjs.cbegin();
for(; anObjIter != anObjs.cend(); anObjIter++) {
- myJustCreatedOrUpdated.insert(*anObjIter);
// created objects are always must be up to date (python box feature)
// and updated not in internal uptation chain
- if (!myIsExecuted || theMessage->eventID() == kCreatedEvent)
- myInitial.insert(*anObjIter);
- // TODO(mpv): check the next line. Came into dev 0.6.1 from BR_PYTHON_PLUGIN
- // (*anObjIter)->data()->mustBeUpdated(true); // object must be updated because it was changed
+ if (theMessage->eventID() == kCreatedEvent) {
+ myJustCreated.insert(*anObjIter);
+ } else if (myJustCreated.find(*anObjIter) == myJustCreated.end()) { // moved and updated
+ myJustUpdated.insert(*anObjIter);
+ }
}
- if (theMessage->eventID() == kMovedEvent)
- return; // this event is for solver update, not here
+ // this event is for solver update, not here, do not react immideately
+ if (!(theMessage->eventID() == kMovedEvent))
+ processOperation(false);
} else if (theMessage->eventID() == kOpStartEvent) {
- myJustCreatedOrUpdated.clear();
- myInitial.clear();
- return; // we don't need the update only on operation start (caused problems in PartSet_Listener::processEvent)
+ // we don't need the update only on operation start (caused problems in PartSet_Listener::processEvent)
+ isOperationChanged = true;
} else if (theMessage->eventID() == kOpFinishEvent || theMessage->eventID() == kOpAbortEvent) {
- if (myIsAutomatic == false) { // Apply button now works as "Rebuild"
- isAutomaticChanged = true;
- myIsAutomatic = true;
+ processOperation(true);
+ isOperationChanged = true;
+ }
+ if (isOperationChanged) {
+ // remove all macros before clearing all created
+ std::set<ObjectPtr>::iterator aCreatedIter = myJustCreated.begin();
+ for(; aCreatedIter != myJustCreated.end(); aCreatedIter++) {
+ FeaturePtr aFeature =
+ std::dynamic_pointer_cast<ModelAPI_Feature>(*aCreatedIter);
+ if (aFeature.get()) {
+ // execute not-previewed feature on "apply"
+ if (!aFeature->isPreviewNeeded() && (myJustCreated.find(aFeature) != myJustCreated.end() ||
+ myJustUpdated.find(aFeature) != myJustUpdated.end())) {
+ static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
+ if (aFactory->validate(aFeature)) {
+ executeFeature(aFeature);
+ }
+ }
+ // remove macro on apply
+ if (aFeature->isMacro()) {
+ aFeature->document()->removeFeature(aFeature);
+ }
+ }
}
- // the hardcode (DBC asked): hide the sketch referenced by extrusion on apply
- if (theMessage->eventID() == kOpFinishEvent) {
- std::set<std::shared_ptr<ModelAPI_Object> >::iterator aFIter;
- for(aFIter = myJustCreatedOrUpdated.begin(); aFIter != myJustCreatedOrUpdated.end(); aFIter++)
- {
- FeaturePtr aF = std::dynamic_pointer_cast<ModelAPI_Feature>(*aFIter);
- if (aF && aF->data().get() && aF->getKind() == "Extrusion") {
- AttributeSelectionListPtr aBase = aF->selectionList("base");
- if (aBase.get()) {
- for(int a = aBase->size() - 1; a >= 0; a--) {
- ResultPtr aSketchRes = aBase->value(a)->context();
- if (aSketchRes) {
- static Events_ID HIDE_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TOHIDE);
- ModelAPI_EventCreator::get()->sendUpdated(aSketchRes, HIDE_DISP);
- }
- }
+ myJustCreated.clear();
+ myJustUpdated.clear();
+ }
+}
+
+void Model_Update::processOperation(const bool theTotalUpdate)
+{
+ // the hardcode (DBC asked): hide the sketch referenced by extrusion on apply
+ std::set<std::shared_ptr<ModelAPI_Object> >::iterator aFIter;
+ for(aFIter = myJustCreated.begin(); aFIter != myJustCreated.end(); aFIter++)
+ {
+ FeaturePtr aF = std::dynamic_pointer_cast<ModelAPI_Feature>(*aFIter);
+ if (aF && aF->data().get() && aF->getKind() == "Extrusion") {
+ AttributeSelectionListPtr aBase = aF->selectionList("base");
+ if (aBase.get()) {
+ for(int a = aBase->size() - 1; a >= 0; a--) {
+ ResultPtr aSketchRes = aBase->value(a)->context();
+ if (aSketchRes) {
+ aSketchRes->setDisplayed(false);
}
}
}
}
}
+ // perform update of everything if needed
+ if (!myIsExecuted) {
+ myIsExecuted = true;
+
+ bool isAutomaticChanged = false;
- if (myIsExecuted)
- return; // nothing to do: it is executed now
+ if (theTotalUpdate && !myIsAutomatic) { // Apply button now works as "Rebuild"
+ isAutomaticChanged = true;
+ myIsAutomatic = true;
+ }
- //Events_LongOp::start(this);
- myIsExecuted = true;
- // iterate all documents: features in Root first, then - subs
- updateInDoc(ModelAPI_Session::get()->moduleDocument());
+ updateInDoc(ModelAPI_Session::get()->moduleDocument());
- myUpdated.clear();
- // flush to update display
- static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- aLoop->flush(EVENT_DISP);
- //Events_LongOp::end(this);
- if (isAutomaticChanged) myIsAutomatic = false;
+ if (isAutomaticChanged) myIsAutomatic = false;
+ myIsExecuted = false;
- if (theMessage->eventID() == kOpFinishEvent || theMessage->eventID() == kOpAbortEvent) {
- myJustCreatedOrUpdated.clear();
- myInitial.clear();
+ // flush to update display
+ static Events_Loop* aLoop = Events_Loop::loop();
+ static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ aLoop->flush(EVENT_DISP);
}
-
- myIsExecuted = false;
}
void Model_Update::updateInDoc(std::shared_ptr<ModelAPI_Document> theDoc)
{
+ std::set<FeaturePtr> alreadyProcessed; // features that are processed before others
// 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<ModelAPI_Feature>(
- theDoc->object(ModelAPI_Feature::group(), aFIndex, true));
- if (aFeature)
- updateFeature(aFeature);
- }
- // all sub-documents one by one
- std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(theDoc);
- if (aDoc) {
- const std::set<std::string> aSubs = aDoc->subDocuments(true);
- for(std::set<std::string>::iterator aSub = aSubs.begin(); aSub != aSubs.end(); aSub++) {
- DocumentPtr aSubDoc = theDoc->subDocument(*aSub);
- if (aSubDoc) {
- updateInDoc(aSubDoc);
+ Model_Objects* anObjs = std::dynamic_pointer_cast<Model_Document>(theDoc)->objects();
+ if (!anObjs) return;
+ FeaturePtr aFeatureIter = anObjs->firstFeature();
+ for (; aFeatureIter.get(); aFeatureIter = anObjs->nextFeature(aFeatureIter)) {
+ if (aFeatureIter && alreadyProcessed.find(aFeatureIter) == alreadyProcessed.end()) {
+ // update selection and parameters attributes first, before sub-features analysis (sketch plane)
+ updateArguments(aFeatureIter);
+ // composite feature must be executed after sub-features execution
+ CompositeFeaturePtr aComposite =
+ std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeatureIter);
+ if (aComposite) {
+ // number of subs can be changed in execution: like fillet
+ for(int a = 0; a < aComposite->numberOfSubs(); a++) {
+ FeaturePtr aSub = aComposite->subFeature(a);
+ updateFeature(aSub);
+ alreadyProcessed.insert(aSub);
+ }
+ }
+
+ updateFeature(aFeatureIter);
+ // update the document results recursively
+ const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeatureIter->results();
+ std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+ for (; aRIter != aResults.cend(); aRIter++) {
+ ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aRIter);
+ if (aPart.get()) {
+ if (!aPart->isDisabled() && aPart->isActivated()) {
+ updateInDoc(aPart->partDoc());
+ }
+ }
}
}
}
for (; aRIter != aResults.cend(); aRIter++) {
std::shared_ptr<ModelAPI_Result> aRes = *aRIter;
aRes->data()->execState(theState);
- myUpdated[aRes] = true;
+ myJustUpdated.insert(aRes);
ModelAPI_EventCreator::get()->sendUpdated(aRes, EVENT_DISP);
}
// to redisplay "presentable" feature (for ex. distance constraint)
return theCurrent;
}
-bool Model_Update::updateFeature(FeaturePtr theFeature)
-{
- // check it is already processed
- if (myUpdated.find(theFeature) != myUpdated.end())
- return myUpdated[theFeature];
- // check all features this feature depended on (recursive call of updateFeature)
- 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()->execState() != ModelAPI_StateDone)
- aMustbeUpdated = true;
-
- ModelAPI_ExecState aState = ModelAPI_StateDone;
+void Model_Update::updateArguments(FeaturePtr theFeature) {
+ static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
- // check the parameters: values can be changed
- std::list<AttributePtr> aDoubles =
- theFeature->data()->attributes(ModelAPI_AttributeDouble::typeId());
- std::list<AttributePtr>::iterator aDoubleIter = aDoubles.begin();
- for(; aDoubleIter != aDoubles.end(); aDoubleIter++) {
- AttributeDoublePtr aDouble =
- std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(*aDoubleIter);
- if (aDouble.get() && !aDouble->text().empty()) {
- double aNewVal;
- if (ModelAPI_Tools::findVariable(aDouble->text(), aNewVal)) {
- if (aNewVal != aDouble->value()) {
- aDouble->setValue(aNewVal);
- aMustbeUpdated = true;
- }
- } else {
- aState = ModelAPI_StateInvalidArgument;
+ if (theFeature->isDisabled()) // nothing to do with disabled feature
+ return;
+ bool aJustUpdated = false;
+ ModelAPI_ExecState aState = ModelAPI_StateDone;
+ // check the parameters: values can be changed
+ std::list<AttributePtr> aDoubles =
+ theFeature->data()->attributes(ModelAPI_AttributeDouble::typeId());
+ std::list<AttributePtr>::iterator aDoubleIter = aDoubles.begin();
+ for(; aDoubleIter != aDoubles.end(); aDoubleIter++) {
+ AttributeDoublePtr aDouble =
+ std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(*aDoubleIter);
+ if (aDouble.get() && !aDouble->text().empty()) {
+ double aNewVal;
+ if (ModelAPI_Tools::findVariable(aDouble->text(), aNewVal)) {
+ if (aNewVal != aDouble->value()) {
+ aDouble->setValue(aNewVal);
+ aJustUpdated = true;
}
+ } else {
+ aState = ModelAPI_StateInvalidArgument;
}
}
+ }
- // composite feature must be executed after sub-features execution
- CompositeFeaturePtr aComposite =
- std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
- if (aComposite) {
- // number of subs can be changed in execution: like fillet
- for(int a = 0; a < aComposite->numberOfSubs(); a++) {
- if (updateFeature(aComposite->subFeature(a)))
- aMustbeUpdated = true;
+ if (aState == ModelAPI_StateDone) {// all referenced objects are ready to be used
+ //std::cout<<"Execute feature "<<theFeature->getKind()<<std::endl;
+ // before execution update the selection attributes if any
+ list<AttributePtr> aRefs =
+ theFeature->data()->attributes(ModelAPI_AttributeSelection::typeId());
+ list<AttributePtr>::iterator aRefsIter = aRefs.begin();
+ for (; aRefsIter != aRefs.end(); aRefsIter++) {
+ std::shared_ptr<ModelAPI_AttributeSelection> aSel =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*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)) &&
+ aFactory->isCase(theFeature, theFeature->data()->id(aSel)))
+ aState = ModelAPI_StateInvalidArgument;
}
}
+ aRefs = theFeature->data()->attributes(ModelAPI_AttributeSelectionList::typeId());
+ for (aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) {
+ std::shared_ptr<ModelAPI_AttributeSelectionList> aSel =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*aRefsIter);
+ for(int a = aSel->size() - 1; a >= 0; a--) {
+ std::shared_ptr<ModelAPI_AttributeSelection> aSelAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(aSel->value(a));
+ if (aSelAttr) {
+ if (!aSelAttr->update()) {
+ if (!aFactory->isNotObligatory(
+ theFeature->getKind(), theFeature->data()->id(aSel)) &&
+ aFactory->isCase(theFeature, theFeature->data()->id(aSel)))
+ aState = ModelAPI_StateInvalidArgument;
+ }
+ }
+ }
+ }
+ }
+ if (aJustUpdated && myJustCreated.find(theFeature) == myJustCreated.end())
+ myJustUpdated.insert(theFeature);
+ if (aState != ModelAPI_StateDone)
+ theFeature->data()->execState(aState);
+}
+
+void Model_Update::updateFeature(FeaturePtr theFeature)
+{
+ // check all features this feature depended on (recursive call of updateFeature)
+ static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
+
+ if (theFeature->isDisabled()) // nothing to do with disabled feature
+ return;
+ bool aJustUpdated = false;
+
+ if (theFeature) {
+ if (theFeature->data()->execState() != ModelAPI_StateDone)
+ aJustUpdated = 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<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
for(; aRef != aRefs.end(); aRef++) {
std::list<ObjectPtr>::iterator aRefObj = aRef->second.begin();
for(; aRefObj != aRef->second.end(); aRefObj++) {
- if (updateObject(*aRefObj)) {
- aMustbeUpdated = true;
+ if (myJustCreated.find(*aRefObj) != myJustCreated.end() ||
+ myJustUpdated.find(*aRefObj) != myJustUpdated.end()) {
+ aJustUpdated = true;
}
aState = stateByReference(*aRefObj, aState);
}
}
+ // some arguments were changed, so, this feature must be updated
+ if (myJustCreated.find(theFeature) != myJustCreated.end()) {
+ aJustUpdated = true;
+ } else {
+ if (aJustUpdated) {
+ if (myJustUpdated.find(theFeature) == myJustUpdated.end())
+ myJustUpdated.insert(theFeature);
+ } else {
+ aJustUpdated = myJustUpdated.find(theFeature) != myJustUpdated.end();
+ }
+ }
//std::cout<<"Update feature "<<theFeature->getKind()<<" must be updated = "<<aMustbeUpdated<<std::endl;
// execute feature if it must be updated
- if (aMustbeUpdated) {
- if (std::dynamic_pointer_cast<Model_Document>(theFeature->document())->executeFeatures() ||
- !theFeature->isPersistentResult()) {
+ if (aJustUpdated) {
+ if ((std::dynamic_pointer_cast<Model_Document>(theFeature->document())->executeFeatures() ||
+ !theFeature->isPersistentResult()) && theFeature->isPreviewNeeded()) {
if (aFactory->validate(theFeature)) {
if (myIsAutomatic ||
- (myJustCreatedOrUpdated.find(theFeature) != myJustCreatedOrUpdated.end()) ||
- !theFeature->isPersistentResult() /* execute quick, not persistent results */)
+ (myJustCreated.find(theFeature) != myJustCreated.end() ||
+ (myJustUpdated.find(theFeature) != myJustUpdated.end() &&
+ theFeature == theFeature->document()->currentFeature(false)) || // currently edited
+ !theFeature->isPersistentResult() /* execute quick, not persistent results */))
{
- if (aState == ModelAPI_StateDone) {// all referenced objects are ready to be used
- //std::cout<<"Execute feature "<<theFeature->getKind()<<std::endl;
- // before execution update the selection attributes if any
- list<AttributePtr> aRefs =
- theFeature->data()->attributes(ModelAPI_AttributeSelection::typeId());
- list<AttributePtr>::iterator aRefsIter = aRefs.begin();
- for (; aRefsIter != aRefs.end(); aRefsIter++) {
- std::shared_ptr<ModelAPI_AttributeSelection> aSel =
- std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*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)) &&
- aFactory->isCase(theFeature, theFeature->data()->id(aSel)))
- aState = ModelAPI_StateInvalidArgument;
- }
- }
- aRefs = theFeature->data()->attributes(ModelAPI_AttributeSelectionList::typeId());
- for (aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) {
- std::shared_ptr<ModelAPI_AttributeSelectionList> aSel =
- std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*aRefsIter);
- for(int a = aSel->size() - 1; a >= 0; a--) {
- std::shared_ptr<ModelAPI_AttributeSelection> aSelAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(aSel->value(a));
- if (aSelAttr) {
- if (!aSelAttr->update()) {
- if (!aFactory->isNotObligatory(
- theFeature->getKind(), theFeature->data()->id(aSel)) &&
- aFactory->isCase(theFeature, 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) {
- // number of subs can be changed in execution: like fillet
- for(int a = 0; a < aComposite->numberOfSubs(); 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 < aComposite->numberOfSubs(); a++) {
- if (aComposite->subFeature(a) && aFactory->validate(aComposite->subFeature(a)))
- aComposite->subFeature(a)->execute();
- }
- }
+ if (aState == ModelAPI_StateDone || aState == ModelAPI_StateMustBeUpdated) {
+ executeFeature(theFeature);
}
-
- // execute in try-catch to avoid internal problems of the feature
- 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, aState);
} else { // must be updatet, but not updated yet
theFeature->data()->execState(ModelAPI_StateMustBeUpdated);
const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
} else { // for automatically updated features (on abort, etc) it is necessary to redisplay anyway
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<std::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- if (myInitial.find(*aRIter) != myInitial.end()) {
- aMustbeUpdated = true;
- break;
- }
- }
}
}
- myUpdated[theFeature] = aMustbeUpdated;
- return aMustbeUpdated;
}
-bool Model_Update::updateObject(std::shared_ptr<ModelAPI_Object> theObject, const bool theCyclic)
+void Model_Update::executeFeature(FeaturePtr theFeature)
{
- if (myUpdated.find(theObject) != myUpdated.end())
- return myUpdated[theObject]; // already processed
-
- /*
- if (theCyclic) { // algorithm for update of all features by dependencies tree
- if (!theObject)
- return false;
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
- if (aFeature) { // for feature just call update Feature
- return updateFeature(aFeature);
- }
- // check general object, possible just a result
- if (myUpdated.find(theObject) != myUpdated.end())
- return myUpdated[theObject]; // already processed
- // check the feature of this object must be executed
- ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
- if (aResult) {
- FeaturePtr aResFeature = aResult->document()->feature(aResult);
- if (aResFeature) {
- return updateFeature(aResFeature);
- }
+ // execute in try-catch to avoid internal problems of the feature
+ ModelAPI_ExecState aState = ModelAPI_StateDone;
+ theFeature->data()->execState(ModelAPI_StateDone);
+ try {
+ theFeature->execute();
+ if (theFeature->data()->execState() != ModelAPI_StateDone) {
+ aState = ModelAPI_StateExecFailed;
+ } else {
+ aState = ModelAPI_StateDone;
}
+ } catch(...) {
+ aState = ModelAPI_StateExecFailed;
+ Events_Error::send(
+ "Feature " + theFeature->getKind() + " has failed during the execution");
}
- */
- return myInitial.find(theObject) != myInitial.end();
+ if (aState != ModelAPI_StateDone) {
+ theFeature->eraseResults();
+ }
+ redisplayWithResults(theFeature, aState);
}
+
*/
class Model_Update : public Events_Listener
{
- /// initial set of updated features that must be processed: caused by external changes, not
- /// by sequence of update of this class
- std::set<std::shared_ptr<ModelAPI_Object> > myInitial;
- /// already updated and processed features and modificated feature flag
- std::map<std::shared_ptr<ModelAPI_Object>, bool> myUpdated;
+ /// created features during this transaction: must be updated all the time
+ std::set<std::shared_ptr<ModelAPI_Object> > myJustCreated;
+ /// updated features during this transaction: must be updated in the end of transaction
+ std::set<std::shared_ptr<ModelAPI_Object> > myJustUpdated;
/// to know that all next updates are caused by this execution
bool myIsExecuted;
/// to know execute or not automatically all update
bool myIsAutomatic;
- /// just created features: they must be updated immideately even in not-automatic mode for
- /// preview; cleared on commit operations
- std::set<std::shared_ptr<ModelAPI_Object> > myJustCreatedOrUpdated;
public:
/// Is called only once, on startup of the application
void updateInDoc(std::shared_ptr<ModelAPI_Document> theDoc);
/// Recoursively checks and updates the feature if needed (calls the execute method)
/// Returns true if feature was updated.
- bool updateFeature(std::shared_ptr<ModelAPI_Feature> theFeature);
+ void updateFeature(std::shared_ptr<ModelAPI_Feature> theFeature);
+
+ /// Updates the selection and parametrical arguments before the later feature analysis
+ void updateArguments(std::shared_ptr<ModelAPI_Feature> theFeature);
- /// Recoursively checks and updates the object (result or feature) if needed (calls updateFeature)
- /// Returns true if object was updated.
- bool updateObject(std::shared_ptr<ModelAPI_Object> theObject, const bool theCyclic = true);
/// Sends the redisplay events for feature and results, updates the updated status
void redisplayWithResults(std::shared_ptr<ModelAPI_Feature> theFeature,
const ModelAPI_ExecState theState);
+
+ /// On operation start/end/abort the "Just" fileds must be cleared and processed in the right way
+ /// \param theTotalUpdate force to updates everything that has been changed in this operation
+ void processOperation(const bool theTotalUpdate);
+
+ /// Performs the feature execution
+ /// \returns the status of execution
+ void executeFeature(std::shared_ptr<ModelAPI_Feature> theFeature);
};
#endif
%template(modelAPI_ResultConstruction) shared_ptr_cast<ModelAPI_ResultConstruction, ModelAPI_Result>;
%template(modelAPI_ResultBody) shared_ptr_cast<ModelAPI_ResultBody, ModelAPI_Result>;
%template(modelAPI_ResultPart) shared_ptr_cast<ModelAPI_ResultPart, ModelAPI_Result>;
+%template(modelAPI_ResultParameter) shared_ptr_cast<ModelAPI_ResultParameter, ModelAPI_Result>;
%template(modelAPI_ResultGroup) shared_ptr_cast<ModelAPI_ResultPart, ModelAPI_ResultGroup>;
// Attribute casts
MODELAPI_EXPORT virtual std::string attributeType();
/// Returns a textual string of the selection
- virtual std::string namingName() = 0;
+ /// \param theDefaultValue a value, which is used if the naming name can not be obtained
+ virtual std::string namingName(const std::string& theDefaultValue = "") = 0;
/// Returns an id of the selection
virtual int Id() = 0;
protected:
/// Objects are created for features automatically
ModelAPI_Data();
+
+ /// Returns true if "is in history" custom behaviors is defined for the feature
+ virtual bool isInHistory() = 0;
+
+ /// Defines the custom "is in history" behavior
+ virtual void setIsInHistory(const bool theFlag) = 0;
+
+ /// Returns true if object must be displayed in the viewer: flag is stored in the
+ /// data model, so on undo/redo, open/save or recreation of object by history-playing it keeps
+ /// the original state i nthe current transaction.
+ virtual bool isDisplayed() = 0;
+
+ /// Sets the displayed/hidden state of the object. If it is changed, sends the "redisplay"
+ /// signal.
+ virtual void setDisplayed(const bool theDisplay) = 0;
+
+ friend class ModelAPI_Object;
};
typedef std::shared_ptr<ModelAPI_Data> DataPtr;
//! Adds to the document the new feature of the given feature id
//! \param theID creates feature and puts it in the document (if it is not action)
- virtual std::shared_ptr<ModelAPI_Feature> addFeature(std::string theID) = 0;
+ //! \param theMakeCurrent to make current this new feature in this document
+ virtual std::shared_ptr<ModelAPI_Feature> addFeature(std::string theID,
+ const bool theMakeCurrent = true) = 0;
//! Return a list of features, which refers to the feature
//! \param theFeature a feature
//! Returns the object in the group by the index (started from zero)
//! \param theGroupID group that contains an object
//! \param theIndex zero-based index of feature in the group
- //! \param theHidden if it is true, it counts also the features that are not in tree
virtual std::shared_ptr<ModelAPI_Object> object(const std::string& theGroupID,
- const int theIndex,
- const bool theHidden = false) = 0;
+ const int theIndex) = 0;
//! Returns the first found object in the group by the object name
//! \param theGroupID group that contains an object
virtual std::shared_ptr<ModelAPI_Object> objectByName(const std::string& theGroupID,
const std::string& theName) = 0;
+ //! Returns the object index in the group. Object must be visible. Otherwise returns -1.
+ //! \param theObject object of this document
+ //! \returns index started from zero, or -1 if object is invisible or belongs to another document
+ virtual const int index(std::shared_ptr<ModelAPI_Object> theObject) = 0;
+
//! Returns the number of objects in the group of objects
- //! If theHidden is true, it counts also the features that are not in tree
- virtual int size(const std::string& theGroupID, const bool theHidden = false) = 0;
+ virtual int size(const std::string& theGroupID) = 0;
+
+ //! Returns the feature that is currently edited in this document, normally
+ //! this is the latest created feature
+ //! \param theVisible use visible features only: flag is true for Object Browser functionality
+ //! \returns null if next created feature must be the first
+ virtual std::shared_ptr<ModelAPI_Feature> currentFeature(const bool theVisible) = 0;
+
+ //! Sets the current feature: all features below will be disabled, new features
+ //! will be appended after this one.
+ //! \param theCurrent the selected feature as current: blow it everythin become disabled
+ //! \param theVisible use visible features only: flag is true for Object Browser functionality
+ virtual void setCurrentFeature(std::shared_ptr<ModelAPI_Feature> theCurrent,
+ const bool theVisible) = 0;
/// To virtually destroy the fields of successors
MODELAPI_EXPORT virtual ~ModelAPI_Document();
MODELAPI_EXPORT ModelAPI_Document();
/// Internally makes document know that feature was removed or added in history after creation
- MODELAPI_EXPORT virtual void addToHistory(const std::shared_ptr<ModelAPI_Object> theObject) = 0;
+ MODELAPI_EXPORT virtual void updateHistory(const std::shared_ptr<ModelAPI_Object> theObject) = 0;
+ /// Internally makes document know that feature was removed or added in history after creation
+ MODELAPI_EXPORT virtual void updateHistory(const std::string theGroup) = 0;
friend class ModelAPI_Object; // to add or remove from the history
+ friend class ModelAPI_Result; // to add or remove from the history
};
//! Pointer on document object
}
-ModelAPI_DocumentCreatedMessage::ModelAPI_DocumentCreatedMessage(const Events_ID theID, const void* theSender)
+ModelAPI_DocumentCreatedMessage::ModelAPI_DocumentCreatedMessage(const Events_ID theID,
+ const void* theSender)
: Events_Message(theID, theSender)
{
{
myDocument = theDocument;
}
+
+ModelAPI_AttributeEvalMessage::ModelAPI_AttributeEvalMessage(const Events_ID theID,
+ const void* theSender)
+: Events_Message(theID, theSender)
+{
+
+}
+
+ModelAPI_AttributeEvalMessage::~ModelAPI_AttributeEvalMessage()
+{
+
+}
+
+AttributePtr ModelAPI_AttributeEvalMessage::attribute() const
+{
+ return myAttribute;
+}
+
+void ModelAPI_AttributeEvalMessage::setAttribute(AttributePtr theDocument)
+{
+ myAttribute = theDocument;
+}
#include <ModelAPI.h>
#include <ModelAPI_Object.h>
#include <ModelAPI_Feature.h>
+#include <ModelAPI_Attribute.h>
#include <Events_MessageGroup.h>
#include <Events_Loop.h>
static const char * EVENT_OPERATION_LAUNCHED = "OperationLaunched";
/// Event ID that plugin is loaded (comes with ModelAPI_ObjectUpdatedMessage)
static const char * EVENT_PLUGIN_LOADED = "PliginLoaded";
-/// Event ID that data of feature has to be shown (comes with ModelAPI_ObjectUpdatedMessage)
-static const char * EVENT_OBJECT_TOSHOW = "ObjectShow";
-/// Event ID that data of feature has to be shown (comes with ModelAPI_ObjectUpdatedMessage)
-static const char * EVENT_OBJECT_TOHIDE = "ObjectHide";
//
static const char * EVENT_DOCUMENT_CHANGED = "CurrentDocumentChanged";
MODELAPI_EXPORT void setDocument(DocumentPtr theDocument);
};
+/// Message that attribute text should be evaluated in the attribute value
+class ModelAPI_AttributeEvalMessage : public Events_Message
+{
+ AttributePtr myAttribute;
+
+ public:
+ /// Creates an empty message
+ MODELAPI_EXPORT ModelAPI_AttributeEvalMessage(const Events_ID theID, const void* theSender = 0);
+ /// The virtual destructor
+ MODELAPI_EXPORT virtual ~ModelAPI_AttributeEvalMessage();
+ /// Static. Returns EventID of the message.
+ MODELAPI_EXPORT static Events_ID eventId()
+ {
+ static const char * MY_ATTRIBUTE_EVALUATION_EVENT_ID("AttributeEvaluationRequest");
+ return Events_Loop::eventByName(MY_ATTRIBUTE_EVALUATION_EVENT_ID);
+ }
+
+ /// Returns a document stored in the message
+ MODELAPI_EXPORT AttributePtr attribute() const;
+ /// Sets a document to the message
+ MODELAPI_EXPORT void setAttribute(AttributePtr theDocument);
+};
+
#endif
void ModelAPI_Feature::setResult(const std::shared_ptr<ModelAPI_Result>& theResult)
{
- if (firstResult() == theResult) { // just updated
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
- ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent);
- return;
- }
- // created
- while (!myResults.empty()) { // remove one by one with messages
- std::shared_ptr<ModelAPI_Result> aRes = *(myResults.begin());
- myResults.erase(myResults.begin());
- ModelAPI_EventCreator::get()->sendDeleted(aRes->document(), aRes->groupName());
+ static Events_Loop* aLoop = Events_Loop::loop();
+ static Events_ID EVENT_UPD = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+ static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
+
+ if (firstResult() == theResult) {
+ // nothing to change
+ } else if (!myResults.empty()) { // all except first become disabled
+ std::list<std::shared_ptr<ModelAPI_Result> >::iterator aResIter = myResults.begin();
+ *aResIter = theResult;
+ aECreator->sendUpdated(theResult, EVENT_UPD);
+ for(aResIter++; aResIter != myResults.end(); aResIter++) {
+ (*aResIter)->setDisabled((*aResIter), true);
+ }
+ } else {
+ myResults.push_back(theResult);
}
- myResults.push_back(theResult);
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
- ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent);
- // Create event for first Feature
- Events_Loop::loop()->flush(anEvent);
+ // in any case result becomes enabled
+ theResult->setDisabled(theResult, false);
+ // flush vidualisation changes
+ static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ aLoop->flush(aRedispEvent);
}
void ModelAPI_Feature::setResult(const std::shared_ptr<ModelAPI_Result>& theResult,
}
if (aResIter == myResults.end()) { // append
myResults.push_back(theResult);
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
- ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent);
- // Create event for first Feature, send it to make "created" earlier than "updated"
- // VSV: Commenting out of this statement causes problems with circle operation for example
- Events_Loop::loop()->flush(anEvent);
} else { // update
*aResIter = theResult;
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
- ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent);
}
+ theResult->setDisabled(theResult, false);
+ // flush visualisation changes
+ static Events_Loop* aLoop = Events_Loop::loop();
+ static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ aLoop->flush(aRedispEvent);
}
void ModelAPI_Feature::removeResult(const std::shared_ptr<ModelAPI_Result>& theResult)
{
- std::list<std::shared_ptr<ModelAPI_Result> >::iterator aResIter = myResults.begin();
- for(; aResIter != myResults.end(); aResIter++) {
- ResultPtr aRes = *aResIter;
- if (aRes == theResult) {
- std::string aGroup = aRes->groupName();
- aRes->data()->erase();
- myResults.erase(aResIter);
-
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
- static Events_Loop* aLoop = Events_Loop::loop();
- static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
- ModelAPI_EventCreator::get()->sendDeleted(document(), aGroup);
- aECreator->sendUpdated(aRes, EVENT_DISP);
- break;
- }
- }
+ theResult->setDisabled(theResult, true);
+ // flush visualisation changes
+ static Events_Loop* aLoop = Events_Loop::loop();
+ static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ aLoop->flush(aRedispEvent);
}
-void ModelAPI_Feature::removeResults(const int theSinceIndex)
+void ModelAPI_Feature::removeResults(const int theSinceIndex, const bool theFlush)
{
- if (theSinceIndex == 0) {
- eraseResults();
- return;
- }
-
std::list<std::shared_ptr<ModelAPI_Result> >::iterator aResIter = myResults.begin();
for(int anIndex = 0; anIndex < theSinceIndex && aResIter != myResults.end(); anIndex++)
aResIter++;
std::list<std::shared_ptr<ModelAPI_Result> >::iterator aNextIter = aResIter;
- for(; aNextIter != myResults.end(); aNextIter++) {
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
+ while( aNextIter != myResults.end()) {
+ // remove previously erased results: to enable later if needed only actual (of history change)
+ if (theSinceIndex == 0 && (*aNextIter)->isDisabled()) {
+ aNextIter = myResults.erase(aNextIter);
+ } else {
+ (*aNextIter)->setDisabled(*aNextIter, true); // just disable results
+ aNextIter++;
+ }
+ }
+ if (theFlush) {
+ // flush visualisation changes
static Events_Loop* aLoop = Events_Loop::loop();
- static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
- ModelAPI_EventCreator::get()->sendDeleted(document(), (*aNextIter)->groupName());
- aECreator->sendUpdated(*aNextIter, EVENT_DISP);
+ static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ aLoop->flush(aRedispEvent);
}
- myResults.erase(aResIter, myResults.end());
}
void ModelAPI_Feature::eraseResults()
{
- if (!myResults.empty()) {
- static Events_Loop* aLoop = Events_Loop::loop();
- static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
-
- std::list<std::shared_ptr<ModelAPI_Result> >::iterator aResIter = myResults.begin();
- for(; aResIter != myResults.end(); aResIter++) {
- (*aResIter)->data()->erase();
- ModelAPI_EventCreator::get()->sendDeleted(document(), (*aResIter)->groupName());
- aECreator->sendUpdated(*aResIter, EVENT_DISP);
- }
- myResults.clear();
- // flush it to avoid left presentations after input of invalid arguments (radius=0)
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
- Events_Loop::loop()->flush(anEvent);
- Events_Loop::loop()->flush(EVENT_DISP);
- }
+ removeResults(0);
}
const std::string& ModelAPI_Feature::documentToAdd()
}
return aFeature;
}
+
+bool ModelAPI_Feature::isMacro() const
+{
+ return false;
+}
+
+bool ModelAPI_Feature::setDisabled(const bool theFlag)
+{
+ if (myIsDisabled != theFlag) {
+ myIsDisabled = theFlag;
+ if (myIsDisabled) {
+ removeResults(0, false); // flush will be in setCurrentFeature
+ } else {
+ // enable all disabled previously results
+ std::list<std::shared_ptr<ModelAPI_Result> >::iterator aResIter = myResults.begin();
+ for(; aResIter != myResults.end(); aResIter++) {
+ (*aResIter)->setDisabled(*aResIter, false);
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+bool ModelAPI_Feature::isDisabled() const
+{
+ return myIsDisabled;
+}
+
+bool ModelAPI_Feature::isPreviewNeeded() const
+{
+ return true;
+}
{
///< list of current results of this feature
std::list<std::shared_ptr<ModelAPI_Result> > myResults;
+ ///< is feature disabled or not
+ bool myIsDisabled;
public:
/// Returns the unique kind of a feature (like "Point")
virtual const std::string& getKind() = 0;
/// removes the result from the feature
MODELAPI_EXPORT void removeResult(const std::shared_ptr<ModelAPI_Result>& theResult);
/// removes all results starting from the gived index (zero-based)
- MODELAPI_EXPORT void removeResults(const int theSinceIndex);
+ /// \param theSinceIndex - index of the deleted result and all after also will be deleted
+ /// \param theFlush - if it is false, REDISPLAY message is not flushed
+ MODELAPI_EXPORT void removeResults(const int theSinceIndex, const bool theFlush = true);
/// removes all results from the feature
MODELAPI_EXPORT void eraseResults();
/// removes all fields from this feature: results, data, etc
return false;
}
+ /// Returns true if this feature is used as macro: creates other features and then removed.
+ /// \returns false by default
+ MODELAPI_EXPORT virtual bool isMacro() const;
+
+ /// Returns true if preview update during the edition needed. Otherwise the update-mechanism
+ /// calls the \a execute function only on "apply" of the operation
+ /// \returns true by default
+ MODELAPI_EXPORT virtual bool isPreviewNeeded() const;
+
/// Must return document where the new feature must be added to
/// By default it is empty: it is added to the document this method is called to
MODELAPI_EXPORT virtual const std::string& documentToAdd();
+ /// Enables/disables the feature. The disabled feature has no results and does not participate in
+ /// any calculation.
+ /// \returns true if state is really changed
+ MODELAPI_EXPORT virtual bool setDisabled(const bool theFlag);
+
+ /// Returns the feature is disabled or not.
+ MODELAPI_EXPORT virtual bool isDisabled() const;
+
/// To virtually destroy the fields of successors
MODELAPI_EXPORT virtual ~ModelAPI_Feature();
#include "ModelAPI_Object.h"
#include "ModelAPI_Document.h"
+#include "ModelAPI_Data.h"
+#include "ModelAPI_Events.h"
+#include <Events_Loop.h>
bool ModelAPI_Object::isInHistory()
{
- return myInHistory;
+ if (myData.get() && myData->isValid()) {
+ return myData->isInHistory();
+ }
+ return true; // default value
}
void ModelAPI_Object::setInHistory(
const std::shared_ptr<ModelAPI_Object> theObject, const bool theFlag)
{
- if (myInHistory != theFlag) {
- myInHistory = theFlag;
- myDoc->addToHistory(theObject);
+ if (isInHistory() != theFlag) {
+ if (myData.get() && myData->isValid()) {
+ myData->setIsInHistory(theFlag);
+ }
+ myDoc->updateHistory(theObject);
}
}
{
}
-ModelAPI_Object::ModelAPI_Object() : myInHistory(true)
+ModelAPI_Object::ModelAPI_Object()
{
}
if (myData) myData->erase();
setData(DataPtr());
}
+
+bool ModelAPI_Object::isDisplayed()
+{
+ return myData->isDisplayed();
+}
+
+void ModelAPI_Object::setDisplayed(const bool theDisplay)
+{
+ myData->setDisplayed(theDisplay);
+}
{
std::shared_ptr<ModelAPI_Data> myData; ///< manager of the data model of a feature
std::shared_ptr<ModelAPI_Document> myDoc; ///< document this object belongs to
- bool myInHistory; ///< keep the information about the presense of the object in the history tree
public:
/// By default object is displayed in the object browser.
MODELAPI_EXPORT virtual bool isInHistory();
/// Request for initialization of data model of the object: adding all attributes
virtual void initAttributes() = 0;
+ /// Returns the feature is disabled or not.
+ virtual bool isDisabled() const = 0;
+
/// Called on change of any argument-attribute of this object
/// \param theID identifier of changed attribute
MODELAPI_EXPORT virtual void attributeChanged(const std::string& theID);
/// To use virtuality for destructors
MODELAPI_EXPORT virtual ~ModelAPI_Object();
+ /// Returns true if object must be displayed in the viewer: flag is stored in the
+ /// data model, so on undo/redo, open/save or recreation of object by history-playing it keeps
+ /// the original state i nthe current transaction.
+ MODELAPI_EXPORT virtual bool isDisplayed();
+
+ /// Sets the displayed/hidden state of the object. If it is changed, sends the "redisplay"
+ /// signal.
+ MODELAPI_EXPORT virtual void setDisplayed(const bool theDisplay);
+
protected:
/// Sets the data manager of an object (document does)
MODELAPI_EXPORT virtual void setData(std::shared_ptr<ModelAPI_Data> theData);
/// removes all fields from this feature
MODELAPI_EXPORT virtual void erase();
- friend class Model_Document;
+ friend class Model_Objects;
};
ModelAPI_Result::~ModelAPI_Result()
{
+}
+bool ModelAPI_Result::setDisabled(std::shared_ptr<ModelAPI_Result> theThis, const bool theFlag)
+{
+ if (myIsDisabled != theFlag) {
+ myIsDisabled = theFlag;
+ // this must be before "updated" message send to have history updated for OB update
+ document()->updateHistory(groupName()); // to update the history cash data in the document
+ // generate related events
+ static Events_Loop* aLoop = Events_Loop::loop();
+ static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
+ if (myIsDisabled) { // disabled result looks like removed
+ aECreator->sendDeleted(document(), groupName());
+ } else { // un-disabled equals to created
+ static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
+ aECreator->sendUpdated(theThis, anEvent /*, false*/); // flush is in setCurrentFeature
+ }
+ static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ aECreator->sendUpdated(theThis, EVENT_DISP/*, false*/); // flush is in setCurrentFeature
+ return true;
+ }
+ return false;
+}
+
+bool ModelAPI_Result::isDisabled() const
+{
+ return myIsDisabled;
}
+void ModelAPI_Result::setIsConcealed(const bool theValue)
+{
+ if (myIsConcealed != theValue) {
+ myIsConcealed = theValue;
+ if (document().get()) // can be on creation of result
+ document()->updateHistory(groupName()); // to update the history cash data in the document
+ }
+}
+
+
std::shared_ptr<GeomAPI_Shape> ModelAPI_Result::shape()
{
return std::shared_ptr<GeomAPI_Shape>();
class ModelAPI_Result : public ModelAPI_Object
{
bool myIsConcealed; ///< the result is concealed from the data tree (referenced by other objects)
+ bool myIsDisabled; ///< the result is disabled: removed for the user, but keeps the general info
public:
- /// Reference to the color of the result
+ /// Reference to the color of the result.
+ /// The integer array is used. It contains tree values for red green and blue values. The values are in
+ /// [0, 255] range
inline static const std::string& COLOR_ID()
{
static const std::string MY_COLOR_ID("Color");
}
/// Returns true if the result is concealed from the data tree (referenced by other objects)
- inline void setIsConcealed(const bool theValue)
- {
- myIsConcealed = theValue;
- }
+ MODELAPI_EXPORT void setIsConcealed(const bool theValue);
+
+ /// Enables/disables the result. The disabled result does not participate in any calculation
+ /// and visualization: like it was removed. But it keeps the general parameters: colors,
+ /// visibility, etc.
+ /// \param theThis pointer to this object, needed to generate all events if it is neccessary
+ /// \param theFlag makes disabled if it is true
+ /// \returns true if state is really changed
+ MODELAPI_EXPORT virtual bool setDisabled(std::shared_ptr<ModelAPI_Result> theThis,
+ const bool theFlag);
+
+ /// Returns the result is disabled or not.
+ MODELAPI_EXPORT virtual bool isDisabled() const;
// Retuns the parameters of color definition in the resources config manager
virtual void colorConfigInfo(std::string& theSection, std::string& theName,
/// Returns all the opened documents of the session (without postponed)
virtual std::list<std::shared_ptr<ModelAPI_Document> > allOpenedDocuments() = 0;
+ /// Returns true if document is not loaded yet
+ virtual bool isLoadByDemand(const std::string theDocID) = 0;
+
/// Copies the document to the new one with the given id
virtual std::shared_ptr<ModelAPI_Document> copy(std::shared_ptr<ModelAPI_Document> theSource,
std::string theID) = 0;
#include <ModelAPI_ResultParameter.h>
#include <list>
+#include <map>
namespace ModelAPI_Tools {
return false;
}
+static std::map<int, std::vector<int> > myColorMap;
+
+void appendValues(std::vector<int>& theRGB, const int theRed, const int theGreen, const int theBlue)
+{
+ theRGB.push_back(theRed);
+ theRGB.push_back(theGreen);
+ theRGB.push_back(theBlue);
+}
+
+bool containsValues(std::map<int, std::vector<int> >& theColorMap, std::vector<int>& theValues)
+{
+ std::map<int, std::vector<int> >::const_iterator anIt = theColorMap.begin(), aLast = theColorMap.end();
+ bool isFound = false;
+ for (; anIt != aLast && !isFound; anIt++) {
+ std::vector<int> aValues = anIt->second;
+ isFound = aValues[0] == theValues[0] &&
+ aValues[1] == theValues[1] &&
+ aValues[2] == theValues[2];
+ }
+ return isFound;
+}
+
+std::vector<int> HSVtoRGB(int theH, int theS, int theV)
+{
+ std::vector<int> aRGB;
+ if (theH < 0 || theH > 360 ||
+ theS < 0 || theS > 100 ||
+ theV < 0 || theV > 100)
+ return aRGB;
+
+ int aHi = (int)theH/60;
+
+ double aV = theV;
+ double aVmin = (100 - theS)*theV/100;
+
+ double anA = (theV - aVmin)* (theH % 60) / 60;
+
+ double aVinc = aVmin + anA;
+ double aVdec = theV - anA;
+
+ double aPercentToValue = 255./100;
+ int aV_int = (int)(aV*aPercentToValue);
+ int aVinc_int = (int)(aVinc*aPercentToValue);
+ int aVmin_int = (int)(aVmin*aPercentToValue);
+ int aVdec_int = (int)(aVdec*aPercentToValue);
+
+ switch(aHi) {
+ case 0: appendValues(aRGB, aV_int, aVinc_int, aVmin_int); break;
+ case 1: appendValues(aRGB, aVdec_int, aV_int, aVmin_int); break;
+ case 2: appendValues(aRGB, aVmin_int, aV_int, aVinc_int); break;
+ case 3: appendValues(aRGB, aVmin_int, aVdec_int, aV_int); break;
+ case 4: appendValues(aRGB, aVinc_int, aVmin_int, aV_int); break;
+ case 5: appendValues(aRGB, aV_int, aVmin_int, aVdec_int); break;
+ default: break;
+ }
+ return aRGB;
+}
+
+
+void fillColorMap()
+{
+ if (!myColorMap.empty())
+ return;
+
+ int i = 0;
+ for (int s = 100; s > 0; s = s - 50)
+ {
+ for (int v = 100; v >= 40; v = v - 20)
+ {
+ for (int h = 0; h < 359 ; h = h + 60)
+ {
+ std::vector<int> aColor = HSVtoRGB(h, s, v);
+ if (containsValues(myColorMap, aColor))
+ continue;
+ myColorMap[i] = aColor;
+ i++;
+ }
+ }
+ }
+}
+
+void findRandomColor(std::vector<int>& theValues)
+{
+ theValues.clear();
+ if (myColorMap.empty()) {
+ fillColorMap();
+ }
+
+ int aSize = myColorMap.size();
+ int anIndex = rand() % aSize;
+ if (myColorMap.find(anIndex) != myColorMap.end()) {
+ theValues = myColorMap.at(anIndex);
+ }
+}
+
} // namespace ModelAPI_Tools
#include <ModelAPI_Result.h>
#include <GeomAPI_Shape.h>
+#include <vector>
+
namespace ModelAPI_Tools {
/// Returns shape from the given Result object
MODELAPI_EXPORT std::shared_ptr<GeomAPI_Shape> shape(const ResultPtr& theResult);
*/
MODELAPI_EXPORT bool findVariable(const std::string& theName, double& outValue);
+/*!
+ * Returns the values of the next random color. The values are in range [0, 255]
+ * \param theValues a container of component of RGB value: red, green, blue
+ */
+MODELAPI_EXPORT void findRandomColor(std::vector<int>& theValues);
+
}
#endif
ModuleBase_IWorkshop.h
ModuleBase_Definitions.h
ModuleBase_SelectionValidator.h
- ModuleBase_ISelection.h
ModuleBase_ViewerPrs.h
ModuleBase_WidgetChoice.h
ModuleBase_WidgetFileSelector.h
ModuleBase_DoubleSpinBox.h
ModuleBase_IPropertyPanel.h
+ ModuleBase_ISelection.h
ModuleBase_IViewer.h
ModuleBase_WidgetLineEdit.h
ModuleBase_WidgetMultiSelector.h
ModuleBase_WidgetValidated.h
ModuleBase_WidgetExprEditor.h
ModuleBase_ParamSpinBox.h
+ ModuleBase_WidgetIntValue.h
+ ModuleBase_IDocumentDataModel.h
)
SET(PROJECT_SOURCES
ModuleBase_FilterValidated.cpp
ModuleBase_Tools.cpp
ModuleBase_IModule.cpp
+ ModuleBase_ISelection.cpp
ModuleBase_IWorkshop.cpp
ModuleBase_Operation.cpp
ModuleBase_OperationDescription.cpp
ModuleBase_WidgetExprEditor.cpp
ModuleBase_ParamSpinBox.cpp
ModuleBase_SelectionValidator.cpp
+ ModuleBase_WidgetIntValue.cpp
)
SET(PROJECT_LIBRARIES
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File: ModuleBase_IDocumentDataModel.h
+// Created: 28 Apr 2015
+// Author: Vitaly SMETANNIKOV
+
+
+#ifndef ModuleBase_IDocumentDataModel_H
+#define ModuleBase_IDocumentDataModel_H
+
+#include "ModuleBase.h"
+#include <QAbstractItemModel>
+#include <ModelAPI_Object.h>
+
+class MODULEBASE_EXPORT ModuleBase_IDocumentDataModel : public QAbstractItemModel
+{
+Q_OBJECT
+public:
+ ModuleBase_IDocumentDataModel(QObject* theParent): QAbstractItemModel(theParent) {}
+
+ //! Returns an object by the given Model index.
+ //! Returns 0 if the given index is not index of an object
+ virtual ObjectPtr object(const QModelIndex& theIndex) const = 0;
+
+ //! Returns index of the object
+ //! \param theObject object to find
+ virtual QModelIndex objectIndex(const ObjectPtr theObject) const = 0;
+
+ //! Clear internal data
+ virtual void clear() {}
+
+ //! Rebuild data tree
+ virtual void rebuildDataTree() {}
+};
+
+#endif
\ No newline at end of file
class ModuleBase_ModelWidget;\r
class ModuleBase_Operation;\r
class ModuleBase_IWorkshop;\r
+class ModuleBase_IDocumentDataModel;\r
\r
/**\r
* \ingroup GUI\r
/// \param theMenu a popup menu to be shown in the viewer\r
/// \param theStdActions a map of standard actions\r
/// \return true if items are added and there is no necessity to provide standard menu\r
- virtual bool addViewerItems(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const { return false; }\r
+ virtual bool addViewerMenu(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const { return false; }\r
\r
/// Add menu atems for object browser into the given menu\r
/// \param theMenu a popup menu to be shown in the object browser\r
- virtual void addObjectBrowserItems(QMenu* theMenu) const {};\r
+ virtual void addObjectBrowserMenu(QMenu* theMenu) const {};\r
\r
/// Called when it is necessary to update a command state (enable or disable it)\r
//virtual bool isFeatureEnabled(const QString& theCmdId) const = 0;\r
/// \returns true if the action is processed\r
virtual bool deleteObjects() { return false; };\r
\r
+ /// Returns data model object for representation of data tree in Object browser\r
+ virtual ModuleBase_IDocumentDataModel* dataModel() const = 0;\r
+\r
+ /// Returns a list of modes, where the AIS objects should be activated\r
+ /// \param theModes a list of modes\r
+ virtual void activeSelectionModes(QIntList& theModes) {}\r
+\r
+ /// This method is called on object browser creation for customisation of module specific features\r
+ /// \param theObjectBrowser a pinter on Object Browser widget\r
+ virtual void customizeObjectBrowser(QWidget* theObjectBrowser) {}\r
+\r
public slots:\r
/// Called on call of command corresponded to a feature\r
void onFeatureTriggered();\r
/// Returns all property panel's widget created by WidgetFactory
virtual const QList<ModuleBase_ModelWidget*>& modelWidgets() const = 0;
+ /// Removes all widgets in the widget area of the property panel
+ virtual void cleanContent() = 0;
+
/// Editing mode depends on mode of current operation. This value is defined by it.
/// \param isEditing state of editing mode flag
virtual void setEditingMode(bool isEditing) { myIsEditing = isEditing; }
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+#include "ModuleBase_ISelection.h"
+
+QList<ModuleBase_ViewerPrs> ModuleBase_ISelection::getViewerPrs(const QObjectPtrList& theObjects)
+{
+ QList<ModuleBase_ViewerPrs> aSelectedPrs;
+ QObjectPtrList::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
+ for (; anIt != aLast; anIt++) {
+ ObjectPtr anObject = *anIt;
+ if (anObject.get() != NULL) {
+ aSelectedPrs.append(ModuleBase_ViewerPrs(anObject, TopoDS_Shape(), NULL));
+ }
+ }
+ return aSelectedPrs;
+}
virtual void selectedShapes(NCollection_List<TopoDS_Shape>& theList,
std::list<ObjectPtr>& theOwners) const = 0;
+ //! Wraps the object list into the viewer prs list
+ //! \param theObjects a list of objects
+ //! \return a list of prs, where only object is not empty
+ static MODULEBASE_EXPORT QList<ModuleBase_ViewerPrs> getViewerPrs(
+ const QObjectPtrList& theObjects);
};
#endif
#include "ModuleBase.h"
#include "ModuleBase_Definitions.h"
#include <ModuleBase_FilterValidated.h>
+#include <ModuleBase_ViewerPrs.h>
#include <ModelAPI_Object.h>
#include <GeomAPI_AISObject.h>
//! Select features clearing previous selection.
//! If the list is empty then selection will be cleared
- virtual void setSelected(const QObjectPtrList& theFeatures) = 0;
+ virtual void setSelected(const QList<ModuleBase_ViewerPrs>& theValues) = 0;
signals:
/// Signal selection chaged.
/// 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)
+ /// \param theValues the wrapped selection values
+ /// \param thePosition an index in the list of values, the values should be get from the index
+ virtual bool setSelection(const QList<ModuleBase_ViewerPrs>& theValues, int& thePosition)
{
return false;
}
bool ModuleBase_Operation::isValid() const
{
- if (!myFeature)
+ if (!myFeature || !myFeature->data().get())
return true; // rename operation
if (myFeature->isAction())
return true;
//Get validators for the Id
SessionPtr aMgr = ModelAPI_Session::get();
ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
- return aFactory->validate(myFeature);
+ bool aValid = aFactory->validate(myFeature);
+
+ // the feature exec state should be checked in order to do not apply features, which result can not
+ // be built. E.g. extrusion on sketch, where the "to" is a perpendicular plane to the sketch
+ bool isDone = myFeature->data()->execState() == ModelAPI_StateDone;
+
+ return aValid && isDone;
}
{
QString anId = getDescription()->operationId();
if (myIsEditing) {
- anId = anId.append(EditSuffix());
+ anId = anId.append(EditSuffix());
}
ModelAPI_Session::get()->startOperation(anId.toStdString());
return;
}
}
+ /// Set current feature and remeber old current feature
+ if (myIsEditing) {
+ SessionPtr aMgr = ModelAPI_Session::get();
+ DocumentPtr aDoc = aMgr->activeDocument();
+ myCurrentFeature = aDoc->currentFeature(true);
+ aDoc->setCurrentFeature(feature(), false);
+ }
startOperation();
emit started();
void ModuleBase_Operation::abort()
{
+ if (myIsEditing) {
+ SessionPtr aMgr = ModelAPI_Session::get();
+ DocumentPtr aDoc = aMgr->activeDocument();
+ aDoc->setCurrentFeature(myCurrentFeature, true);
+ myCurrentFeature = FeaturePtr();
+ }
abortOperation();
emit aborted();
stopOperation();
+ // is is necessary to deactivate current widgets before the model operation is aborted
+ // because abort removes the feature and activated filters should not check it
+ propertyPanel()->cleanContent();
ModelAPI_Session::get()->abortOperation();
emit stopped();
bool ModuleBase_Operation::commit()
{
if (canBeCommitted()) {
+ SessionPtr aMgr = ModelAPI_Session::get();
+ /// Set current feature and remeber old current feature
+ if (myIsEditing) {
+ DocumentPtr aDoc = aMgr->activeDocument();
+ bool aIsOp = aMgr->isOperation();
+ if (!aIsOp)
+ aMgr->startOperation();
+ aDoc->setCurrentFeature(myCurrentFeature, true);
+ if (!aIsOp)
+ aMgr->finishOperation();
+ myCurrentFeature = FeaturePtr();
+ }
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
- if (ModelAPI_Session::get()->isModified())
- ModelAPI_Session::get()->finishOperation();
+ if (aMgr->isModified())
+ aMgr->finishOperation();
else
- ModelAPI_Session::get()->abortOperation();
+ aMgr->abortOperation();
stopOperation();
emit stopped();
ModuleBase_ModelWidget* aWgt, *aFilledWgt = 0;
QList<ModuleBase_ModelWidget*>::const_iterator aWIt;
- QList<ModuleBase_ViewerPrs>::const_iterator aPIt;
bool isSet = false;
// 1. apply the selection to controls
- for (aWIt = aWidgets.constBegin(), aPIt = myPreSelection.constBegin();
- (aWIt != aWidgets.constEnd()) && (aPIt != myPreSelection.constEnd());
- ++aWIt) {
+ int aCurrentPosition = 0;
+ for (aWIt = aWidgets.constBegin(); aWIt != aWidgets.constEnd(); ++aWIt) {
aWgt = (*aWIt);
- ModuleBase_ViewerPrs aValue = (*aPIt);
if (!aWgt->canSetValue())
continue;
- ++aPIt;
- if (!aWgt->setSelection(aValue)) {
+ if (!aWgt->setSelection(myPreSelection, aCurrentPosition/*aValue*/)) {
isSet = false;
break;
} else {
/// before operation feature creating
CompositeFeaturePtr myParentFeature;
+ /// Last current feature before editing operation
+ FeaturePtr myCurrentFeature;
};
#endif
{
const int kCol = 0;
const int kRow = myMainLayout->count();
- myMainLayout->addWidget(theWidget, kRow, kCol, Qt::AlignTop | Qt::AlignLeft);
+ // it seems, that the align on left is not necessary here, but leads to widgets, which are
+ // not extended on full width of the parent page. The case is grouped widgets in
+ // the sketch translation operation
+ myMainLayout->addWidget(theWidget, kRow, kCol, Qt::AlignTop);// | Qt::AlignLeft);
myMainLayout->setRowStretch(kRow, 0);
}
*/
double ModuleBase_ParamSpinBox::valueFromText(const QString& theText) const
{
- if (!hasVariable(theText))
+ if (!hasVariable(theText)) {
return ModuleBase_DoubleSpinBox::valueFromText(theText);
-
- double aValue = 0;
- findVariable(theText, aValue);
- return aValue;
+ }
+ // small hack: return length of the string to iniiate valuesChanged signal
+ return theText.length();
}
QString ModuleBase_ParamSpinBox::textFromValue (double theValue) const
return ModuleBase_DoubleSpinBox::validate(str, pos);
QValidator::State res = QValidator::Invalid;
-
- // Considering the input text as a variable name
- // Applying Python identifier syntax:
- // either a string starting with a letter, or a string starting with
- // an underscore followed by at least one alphanumeric character
if (isAcceptVariables()) {
- QRegExp varNameMask("[_a-zA-Z][a-zA-Z0-9_]*");
- if (varNameMask.exactMatch(str))
- res = QValidator::Acceptable;
-
- if (res == QValidator::Invalid) {
- varNameMask.setPattern("_");
- if (varNameMask.exactMatch(str))
- res = QValidator::Intermediate;
- }
+ res = QValidator::Acceptable;
}
return res;
}
bool ModuleBase_ParamSpinBox::hasVariable(const QString& theText) const
{
- QRegExp varNameMask("([a-z]|[A-Z]|_).*");
- return varNameMask.exactMatch(theText);
+ QRegExp varNameMask("[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?");
+ return !varNameMask.exactMatch(theText);
}
/*!
myPreferences->setItemProperty("image_formats", aImgFiles, bgId);
//Config_PropManager::registerProp("Visualization", "object_default_color", "Object color",
- // Config_Prop::Color, "#ffffff");
+ // Config_Prop::Color, "225,225,225");
Config_PropManager::registerProp("Visualization", "result_body_color", "Body color",
Config_Prop::Color, Model_ResultBody::DEFAULT_COLOR());
void ModuleBase_ResultPrs::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
const Standard_Integer aMode)
{
+ if (aMode > TopAbs_SHAPE)
+ // In order to avoid using custom selection modes
+ return;
+
if (myIsSketchMode) {
if (aMode == TopAbs_FACE) {
BRep_Builder aBuilder;
// Author: Vitaly Smetannikov
#include "ModuleBase_Tools.h"
+#include <ModuleBase_ParamSpinBox.h>
#include <ModelAPI_Result.h>
#include <ModelAPI_Data.h>
#include <ModelAPI_Attribute.h>
#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_ResultParameter.h>
#include <GeomDataAPI_Point2D.h>
#include <Events_Error.h>
return QPixmap::fromImage(aResult);
}
+void setSpinText(ModuleBase_ParamSpinBox* theSpin, const QString& theText)
+{
+ bool isBlocked = theSpin->blockSignals(true);
+ theSpin->setText(theText);
+ theSpin->blockSignals(isBlocked);
+}
+
void setSpinValue(QDoubleSpinBox* theSpin, double theValue)
{
bool isBlocked = theSpin->blockSignals(true);
return TopAbs_SHAPE;
}
+void checkObjects(const QObjectPtrList& theObjects, bool& hasResult, bool& hasFeature, bool& hasParameter)
+{
+ hasResult = false;
+ hasFeature = false;
+ hasParameter = false;
+ foreach(ObjectPtr aObj, theObjects) {
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+ ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+ ResultParameterPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aResult);
+
+ hasResult = (aResult.get() != NULL);
+ hasFeature = (aFeature.get() != NULL);
+ hasParameter = (aConstruction.get() != NULL);
+ if (hasFeature && hasResult && hasParameter)
+ break;
+ }
+}
+
}
#define ModuleBase_Tools_H
#include "ModuleBase.h"
+#include "ModuleBase_Definitions.h"
#include <ModelAPI_Feature.h>
#include <TopAbs_ShapeEnum.hxx>
class QWidget;
class QLayout;
class QDoubleSpinBox;
+class ModuleBase_ParamSpinBox;
namespace ModuleBase_Tools {
/// \param theValue a new value
MODULEBASE_EXPORT void setSpinValue(QDoubleSpinBox* theSpin, double theValue);
+/// Sets programmatically the value to the spin box without emitting any signals(e.g. valueChanged)
+/// \param theSpin an ModuleBase_ParamSpinBox that accepts text
+/// \param theText a new value
+MODULEBASE_EXPORT void setSpinText(ModuleBase_ParamSpinBox* theSpin, const QString& theText);
+
/// Converts the object to the feature or a result and generate information string
/// \param theObj an object
/// \param isUseAttributesInfo a flag whether the attribute values information is used
/// \return TopAbs_ShapeEnum value
MODULEBASE_EXPORT TopAbs_ShapeEnum shapeType(const QString& theType);
+/*!
+Check types of objects which are in the given list
+\param theObjects the list of objects
+\param hasResult will be set to true if list contains Result objects
+\param hasFeature will be set to true if list contains Feature objects
+\param hasParameter will be set to true if list contains Parameter objects
+*/
+MODULEBASE_EXPORT void checkObjects(const QObjectPtrList& theObjects, bool& hasResult, bool& hasFeature, bool& hasParameter);
}
#endif
// Created: 04 June 2014
// Author: Vitaly Smetannikov
-#include <ModuleBase_WidgetDoubleValue.h>
-#include <ModuleBase_ParamSpinBox.h>
-#include <ModuleBase_Tools.h>
-
-#include <ModelAPI_AttributeDouble.h>
-#include <ModelAPI_AttributeString.h>
-#include <ModelAPI_Data.h>
-
#include <Config_Keywords.h>
#include <Config_WidgetAPI.h>
-#include <Events_Loop.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Object.h>
#include <ModelAPI_Events.h>
-#include <QWidget>
+#include <ModuleBase_ParamSpinBox.h>
+#include <ModuleBase_Tools.h>
+#include <ModuleBase_WidgetDoubleValue.h>
+
#include <QFormLayout>
#include <QLabel>
-#include <QEvent>
-#include <QTimer>
+#include <QList>
+#include <QObject>
+#include <QPixmap>
+#include <QString>
-#include <math.h>
+#include <cfloat>
#ifndef DBL_MAX
#define DBL_MAX 1.7976931348623158e+308
mySpinBox->setToolTip(aTTip);
aControlLay->addRow(myLabel, mySpinBox);
- connect(mySpinBox, SIGNAL(valueChanged(double)), this, SIGNAL(valuesChanged()));
+ connect(mySpinBox, SIGNAL(valueChanged(const QString&)), this, SIGNAL(valuesChanged()));
}
ModuleBase_WidgetDoubleValue::~ModuleBase_WidgetDoubleValue()
// reset the value just if there is a default value definition in the XML definition
// if the double value can not be found by the default value, do nothing
if (isOk) {
- ModuleBase_Tools::setSpinValue(mySpinBox, isOk ? aDefValue : 0.0);
+ ModuleBase_Tools::setSpinValue(mySpinBox, aDefValue);
storeValueCustom();
}
}
{
DataPtr aData = myFeature->data();
AttributeDoublePtr aReal = aData->real(attributeID());
- aReal->setValue(mySpinBox->value());
- std::string aTextRepr = aReal->text();
- if (mySpinBox->hasVariable()) {
- aTextRepr = mySpinBox->text().toStdString();
+ if (!mySpinBox->hasVariable()) {
+ aReal->setValue(mySpinBox->value());
+ // In order to synchronize value and text
+ // If it is not synchronized sometimes it could take vale not as a digit but as a string
+ aReal->setText(mySpinBox->text().toStdString());
} else {
- aTextRepr = "";
+ // Here is a text of a real value or an expression.
+ std::string aText = mySpinBox->text().toStdString();
+ aReal->setText(aText);
+ // Send it to evaluator to convert into the double and store in the attribute
+ static Events_ID anId = ModelAPI_AttributeEvalMessage::eventId();
+ std::shared_ptr<ModelAPI_AttributeEvalMessage> aMessage =
+ std::shared_ptr<ModelAPI_AttributeEvalMessage>(new ModelAPI_AttributeEvalMessage(anId, this));
+ aMessage->setAttribute(aData->attribute(attributeID()));
+ Events_Loop::loop()->send(aMessage);
}
- aReal->setText(aTextRepr);
updateObject(myFeature);
return true;
}
AttributeDoublePtr aRef = aData->real(attributeID());
std::string aTextRepr = aRef->text();
if (!aTextRepr.empty()) {
- bool isBlocked = mySpinBox->blockSignals(true);
- mySpinBox->setText(QString::fromStdString(aTextRepr));
- mySpinBox->blockSignals(isBlocked);
+ ModuleBase_Tools::setSpinText(mySpinBox, QString::fromStdString(aTextRepr));
} else {
ModuleBase_Tools::setSpinValue(mySpinBox, aRef->value());
}
#include <GeomDataAPI_Point2D.h>
-#include <QWidget>
-#include <QLineEdit>
-//#include <QTimer>
-#include <QDialog>
-#include <QLayout>
#include <QApplication>
+#include <QLineEdit>
+#include <QMenu>
+#include <QWidget>
+#include <QWidgetAction>
+#include <QRegExp>
+#include <QRegExpValidator>
ModuleBase_WidgetEditor::ModuleBase_WidgetEditor(QWidget* theParent,
const Config_WidgetAPI* theData,
{
}
-double editedValue(double theValue, bool& isDone)
+void editedValue(double& outValue, QString& outText)
{
- QDialog aDlg;
- aDlg.setWindowFlags(Qt::FramelessWindowHint);
- QHBoxLayout* aLay = new QHBoxLayout(&aDlg);
- ModuleBase_Tools::zeroMargins(aLay);
+ QMenu* aPopup = new QMenu();
+
+ QLineEdit* aEditor = new QLineEdit(QString::number(outValue), aPopup);
+ QWidgetAction* aLineEditAction = new QWidgetAction(aPopup);
+ aLineEditAction->setDefaultWidget(aEditor);
+ aPopup->addAction(aLineEditAction);
- QLineEdit* aEditor = new QLineEdit(QString::number(theValue), &aDlg);
+ aEditor->setFocus();
aEditor->selectAll();
- aEditor->setValidator(new QDoubleValidator(aEditor));
- QObject::connect(aEditor, SIGNAL(returnPressed()), &aDlg, SLOT(accept()));
- aLay->addWidget(aEditor);
-
- QPoint aPoint = QCursor::pos();
- aDlg.move(aPoint);
-
- isDone = aDlg.exec() == QDialog::Accepted;
- double aValue = theValue;
- if (isDone)
- aValue = aEditor->text().toDouble();
- return aValue;
+ QString anExpression("([0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)|([_a-zA-Z][a-zA-Z0-9_]*)");
+ aEditor->setValidator(new QRegExpValidator(QRegExp(anExpression), aEditor));
+ QObject::connect(aEditor, SIGNAL(returnPressed()), aLineEditAction, SIGNAL(triggered()));
+ QObject::connect(aLineEditAction, SIGNAL(triggered()), aPopup, SLOT(hide()));
+
+ QAction* aResult = aPopup->exec(QCursor::pos());
+ outText = aEditor->text();
+ bool isDouble;
+ double aValue = outText.toDouble(&isDouble);
+ if (isDouble) {
+ outValue = aValue;
+ // outText = ""; // return empty string, if it's can be converted to a double
+ }
+ aPopup->deleteLater();
}
bool ModuleBase_WidgetEditor::focusTo()
// White while all events will be processed
//QApplication::processEvents();
double aValue = mySpinBox->value();
- bool isDone;
- aValue = editedValue(aValue, isDone);
-
- if (isDone) {
+ QString aText;
+ editedValue(aValue, aText);
+ if (aText.isEmpty()) {
ModuleBase_Tools::setSpinValue(mySpinBox, aValue);
+ } else {
+ ModuleBase_Tools::setSpinText(mySpinBox, aText);
}
emit valuesChanged();
emit focusOutWidget(this);
}
-
-void ModuleBase_WidgetEditor::editFeatureValue(FeaturePtr theFeature,
- const std::string theAttribute)
-{
- DataPtr aData = theFeature->data();
- AttributeDoublePtr aRef = aData->real(theAttribute);
- double aValue = aRef->value();
-
- bool isDone;
- aValue = editedValue(aValue, isDone);
- if (isDone)
- aRef->setValue(aValue);
-}
/// \return the state whether the widget can accept the focus
virtual bool focusTo();
- /// Creates an editor for the real value and set the new value to the feature
- /// \param theFeature the model feature
- /// \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();
#include <ModuleBase_WidgetSwitch.h>
#include <ModuleBase_WidgetShapeSelector.h>
#include <ModuleBase_WidgetDoubleValue.h>
+#include <ModuleBase_WidgetIntValue.h>
#include <ModuleBase_WidgetBoolValue.h>
#include <ModuleBase_WidgetFileSelector.h>
#include <ModuleBase_WidgetChoice.h>
result = new ModuleBase_WidgetLabel(theParent, myWidgetApi, myParentId);
} else if (theType == WDG_DOUBLEVALUE) {
result = new ModuleBase_WidgetDoubleValue(theParent, myWidgetApi, myParentId);
+ } else if (theType == WDG_INTEGERVALUE) {
+ result = new ModuleBase_WidgetIntValue(theParent, myWidgetApi, myParentId);
} else if (theType == WDG_SHAPE_SELECTOR) {
result = new ModuleBase_WidgetShapeSelector(theParent, myWorkshop, myWidgetApi, myParentId);
} else if (theType == WDG_BOOLVALUE) {
#include <Config_WidgetAPI.h>
-#include <QGridLayout>
#include <QFileDialog>
+#include <QGridLayout>
+#include <QLabel>
#include <QLineEdit>
#include <QList>
#include <QObject>
#include <QPushButton>
+#include <QRegExp>
#include <QString>
-#include <QLabel>
#include <memory>
#include <string>
: ModuleBase_ModelWidget(theParent, theData, theParentId)
{
myTitle = QString::fromStdString(theData->getProperty("title"));
+ myType = (theData->getProperty("type") == "save") ? WFS_SAVE : WFS_OPEN;
myDefaultPath = QString::fromStdString(theData->getProperty("path"));
QGridLayout* aMainLay = new QGridLayout(this);
bool ModuleBase_WidgetFileSelector::storeValueCustom() const
{
// A rare case when plugin was not loaded.
- if(!myFeature)
+ if (!myFeature)
return false;
DataPtr aData = myFeature->data();
AttributeStringPtr aStringAttr = aData->string(attributeID());
bool ModuleBase_WidgetFileSelector::restoreValue()
{
// A rare case when plugin was not loaded.
- if(!myFeature)
+ if (!myFeature)
return false;
DataPtr aData = myFeature->data();
AttributeStringPtr aStringAttr = aData->string(attributeID());
bool ModuleBase_WidgetFileSelector::isCurrentPathValid()
{
- QFileInfo aFile (myPathField->text());
+ QFileInfo aFile(myPathField->text());
return aFile.exists();
}
-
void ModuleBase_WidgetFileSelector::onPathSelectionBtn()
{
- QString aFilter = formatsString();
- QString aFileName = QFileDialog::getOpenFileName(this, myTitle, myDefaultPath, aFilter);
+ QString aDefaultPath = myPathField->text().isEmpty()
+ ? myDefaultPath
+ : QFileInfo(myPathField->text()).absolutePath();
+ QString aFilter = filterString();
+ QString aFileName = (myType == WFS_SAVE)
+ ? QFileDialog::getSaveFileName(this, myTitle, aDefaultPath, aFilter, &mySelectedFilter)
+ : QFileDialog::getOpenFileName(this, myTitle, aDefaultPath, aFilter, &mySelectedFilter);
if (!aFileName.isEmpty()) {
myPathField->setText(aFileName);
}
void ModuleBase_WidgetFileSelector::onPathChanged()
{
- if(!isCurrentPathValid())
+ if (myType == WFS_OPEN && !isCurrentPathValid())
return;
storeValue();
emit valuesChanged();
}
-QString ModuleBase_WidgetFileSelector::formatsString() const
+QString ModuleBase_WidgetFileSelector::formatToFilter( const QString & theFormat )
{
- QStringList aResult;
- QStringList aValidatorFormats = getValidatorFormats();
+ if (theFormat.isEmpty() && !theFormat.contains(":"))
+ return QString();
- foreach(QString eachFormat, aValidatorFormats) {
- aResult << QString("%1 files (*.%1)").arg(eachFormat);
- }
- aResult << QString("All files (*.*)");
- return aResult.join(";;");
+ QStringList aExtesionList = theFormat.section(':', 0, 0).split("|");
+ QString aFormat = theFormat.section(':', 1, 1);
+ return QString("%1 files (%2)").arg(aFormat)
+ .arg(QStringList(aExtesionList).replaceInStrings(QRegExp("^(.*)$"), "*.\\1").join(" "));
}
QStringList ModuleBase_WidgetFileSelector::getValidatorFormats() const
{
SessionPtr aMgr = ModelAPI_Session::get();
ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
+
std::list<ModelAPI_Validator*> allValidators;
std::list<std::list<std::string> > allArguments;
aFactory->validators(myFeature->getKind(), myAttributeID, allValidators, allArguments);
- //TODO(sbh): extract as separate method
- if(allArguments.empty())
- return QStringList();
+
+ QStringList aResult;
std::list<std::string> anArgumentList = allArguments.front();
std::list<std::string>::const_iterator it = anArgumentList.begin();
- QStringList aResult;
for (; it != anArgumentList.end(); ++it) {
- std::string anArg = *it;
- int aSepPos = anArg.find(":");
- if (aSepPos == std::string::npos) {
- continue;
- }
- QString aFormat = QString::fromStdString(anArg.substr(0, aSepPos));
- aFormat = aFormat.toUpper();
- aResult.append(aFormat);
+ QString aFormat = QString::fromStdString(*it);
+ if (!aFormat.isEmpty())
+ aResult << aFormat;
}
return aResult;
}
+
+QString ModuleBase_WidgetFileSelector::filterString() const
+{
+ QStringList aResult;
+ QStringList aValidatorFormats = getValidatorFormats();
+
+ foreach(const QString & eachFormat, aValidatorFormats) {
+ aResult << formatToFilter(eachFormat);
+ }
+ if (myType == WFS_OPEN)
+ aResult << QString("All files (*.*)");
+ return aResult.join(";;");
+}
* \code
* <file_selector
* id="import_file_selector"
+* type="open"
* title="Import file"
* path="">
* <validator id="ExchangePlugin_ImportFormat" parameters="BREP:BREPImport,STEP:STEPImport" />
/// \return True in success
virtual bool storeValueCustom() const;
- protected:
- /// Returns string containing formats
- QString formatsString() const;
+protected:
+ /// Converts format to filter string
+ static QString formatToFilter( const QString & theFormat );
- /// Return list of validator formats
+ /// Returns list of validator formats
QStringList getValidatorFormats() const;
- private:
+ /// Returns string containing formats
+ QString filterString() const;
+
+protected:
/// A control for path input
QLineEdit* myPathField;
/// A title of open file dialog box
QString myTitle;
+ /// A current format
+ QString mySelectedFilter;
+
+ /// A title of open file dialog box
+ enum { WFS_OPEN, WFS_SAVE } myType;
+
/// Default path
QString myDefaultPath;
};
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: ModuleBase_Widgets.h
+// Created: 04 June 2014
+// Author: Vitaly Smetannikov
+
+#include <ModuleBase_WidgetIntValue.h>
+#include <ModuleBase_ParamSpinBox.h>
+#include <ModuleBase_Tools.h>
+
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_Data.h>
+
+#include <Config_Keywords.h>
+#include <Config_WidgetAPI.h>
+
+#include <Events_Loop.h>
+#include <ModelAPI_Events.h>
+
+#include <QWidget>
+#include <QFormLayout>
+#include <QLabel>
+#include <QEvent>
+#include <QTimer>
+#include <QSpinBox>
+
+#include <math.h>
+
+#ifndef INT_MAX
+#define INT_MAX 2147483647
+#endif
+
+#ifdef _DEBUG
+#include <iostream>
+#endif
+
+ModuleBase_WidgetIntValue::ModuleBase_WidgetIntValue(QWidget* theParent,
+ const Config_WidgetAPI* theData,
+ const std::string& theParentId)
+ : ModuleBase_ModelWidget(theParent, theData, theParentId)
+{
+ QFormLayout* aControlLay = new QFormLayout(this);
+ ModuleBase_Tools::adjustMargins(aControlLay);
+
+ QString aLabelText = QString::fromStdString(theData->widgetLabel());
+ QString aLabelIcon = QString::fromStdString(theData->widgetIcon());
+ myLabel = new QLabel(aLabelText, this);
+ if (!aLabelIcon.isEmpty())
+ myLabel->setPixmap(QPixmap(aLabelIcon));
+
+ mySpinBox = new QSpinBox(this);
+ QString anObjName = QString::fromStdString(attributeID());
+ mySpinBox->setObjectName(anObjName);
+
+ bool isOk = false;
+ std::string aProp = theData->getProperty(DOUBLE_WDG_MIN);
+ int aMinVal = QString::fromStdString(aProp).toInt(&isOk);
+ if (isOk) {
+ mySpinBox->setMinimum(aMinVal);
+ } else {
+ mySpinBox->setMinimum(-INT_MAX);
+ }
+
+ aProp = theData->getProperty(DOUBLE_WDG_MAX);
+ int aMaxVal = QString::fromStdString(aProp).toInt(&isOk);
+ if (isOk) {
+ mySpinBox->setMaximum(aMaxVal);
+ } else {
+ mySpinBox->setMaximum(INT_MAX);
+ }
+
+ aProp = theData->getProperty(DOUBLE_WDG_STEP);
+ int aStepVal = QString::fromStdString(aProp).toInt(&isOk);
+ if (isOk) {
+ mySpinBox->setSingleStep(aStepVal);
+ }
+
+ int aDefVal = QString::fromStdString(getDefaultValue()).toInt(&isOk);
+ if (isOk) {
+ mySpinBox->setValue(aDefVal);
+ }
+
+ QString aTTip = QString::fromStdString(theData->widgetTooltip());
+ mySpinBox->setToolTip(aTTip);
+
+ aControlLay->addRow(myLabel, mySpinBox);
+ connect(mySpinBox, SIGNAL(valueChanged(int)), this, SIGNAL(valuesChanged()));
+}
+
+ModuleBase_WidgetIntValue::~ModuleBase_WidgetIntValue()
+{
+}
+
+void ModuleBase_WidgetIntValue::reset()
+{
+ if (isComputedDefault()) {
+ return;
+ //if (myFeature->compute(myAttributeID))
+ // restoreValue();
+ } else {
+ bool isOk;
+ int aDefValue = QString::fromStdString(getDefaultValue()).toInt(&isOk);
+ // reset the value just if there is a default value definition in the XML definition
+ // if the double value can not be found by the default value, do nothing
+ if (isOk) {
+ bool isBlocked = mySpinBox->blockSignals(true);
+ mySpinBox->setValue(isOk ? aDefValue : 0);
+ mySpinBox->blockSignals(isBlocked);
+ storeValueCustom();
+ }
+ }
+}
+
+bool ModuleBase_WidgetIntValue::storeValueCustom() const
+{
+ DataPtr aData = myFeature->data();
+ AttributeIntegerPtr aIntVal = aData->integer(attributeID());
+ int aVal = mySpinBox->value();
+ aIntVal->setValue(mySpinBox->value());
+ updateObject(myFeature);
+ return true;
+}
+
+bool ModuleBase_WidgetIntValue::restoreValue()
+{
+ DataPtr aData = myFeature->data();
+ AttributeIntegerPtr aRef = aData->integer(attributeID());
+ bool isBlocked = mySpinBox->blockSignals(true);
+ mySpinBox->setValue(aRef->value());
+ mySpinBox->blockSignals(isBlocked);
+ return true;
+}
+
+QList<QWidget*> ModuleBase_WidgetIntValue::getControls() const
+{
+ QList<QWidget*> aList;
+ aList.append(mySpinBox);
+ return aList;
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: ModuleBase_WidgetIntValue.h
+// Created: 04 June 2014
+// Author: Vitaly Smetannikov
+
+#ifndef ModuleBase_WidgetIntValue_H
+#define ModuleBase_WidgetIntValue_H
+
+#include "ModuleBase.h"
+#include "ModuleBase_ModelWidget.h"
+
+class Config_WidgetAPI;
+class QWidget;
+class QLabel;
+class QTimer;
+class QSpinBox;
+
+/**
+* \ingroup GUI
+* A class of property panel widget for double value input
+* It can be defined with "doublevalue" keyword. For example:
+* \code
+* <doublevalue id="x" label="X:" icon=":pictures/x_point.png" tooltip="X coordinate"/>
+* \endcode
+*/
+class MODULEBASE_EXPORT ModuleBase_WidgetIntValue : public ModuleBase_ModelWidget
+{
+Q_OBJECT
+ public:
+ /// Constructor
+ /// \param theParent the parent object
+ /// \param theData the widget configuation. The attribute of the model widget is obtained from
+ /// \param theParentId is Id of a parent structure (widget, operation, group)
+ ModuleBase_WidgetIntValue(QWidget* theParent, const Config_WidgetAPI* theData,
+ const std::string& theParentId);
+
+ virtual ~ModuleBase_WidgetIntValue();
+
+ /// Fills the widget with default values
+ virtual void reset();
+
+ //! Read value of corresponded attribute from data model to the input control
+ // \return True in success
+ virtual bool restoreValue();
+
+ /// Returns list of widget controls
+ /// \return a control list
+ virtual QList<QWidget*> getControls() const;
+
+
+protected:
+ /// Saves the internal parameters to the given feature
+ /// \return True in success
+ virtual bool storeValueCustom() const;
+
+protected:
+ /// Label of the widget
+ QLabel* myLabel;
+
+ /// Input value control
+ QSpinBox* mySpinBox;
+};
+
+#endif
#include <ModuleBase_IWorkshop.h>
#include <ModuleBase_IViewer.h>
#include <ModuleBase_Tools.h>
+#include <ModuleBase_Definitions.h>
#include <ModelAPI_Data.h>
#include <ModelAPI_Object.h>
const Config_WidgetAPI* theData,
const std::string& theParentId)
: ModuleBase_WidgetValidated(theParent, theData, theParentId),
- myWorkshop(theWorkshop), myIsActive(false)
+ myWorkshop(theWorkshop)
{
QGridLayout* aMainLay = new QGridLayout(this);
ModuleBase_Tools::adjustMargins(aMainLay);
ModuleBase_WidgetMultiSelector::~ModuleBase_WidgetMultiSelector()
{
- myIsActive = false;
- activateShapeSelection();
+ activateShapeSelection(false);
+ activateFilters(myWorkshop, false);
}
//********************************************************************
this, SLOT(onSelectionChanged()),
Qt::UniqueConnection);
- myIsActive = true;
- activateShapeSelection();
+ activateShapeSelection(true);
+
+ // Restore selection in the viewer by the attribute selection list
+ myWorkshop->setSelected(getAttributeSelection());
+
+ activateFilters(myWorkshop, true);
}
//********************************************************************
void ModuleBase_WidgetMultiSelector::deactivate()
{
disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
- myIsActive = false;
- activateShapeSelection();
+ activateShapeSelection(false);
+ activateFilters(myWorkshop, false);
}
//********************************************************************
if (aSelectionListAttr) {
// Restore shape type
- setCurrentShapeType(ModuleBase_Tools::shapeType(aSelectionListAttr->selectionType().c_str()));
+ if (!aSelectionListAttr->selectionType().empty())
+ setCurrentShapeType(ModuleBase_Tools::shapeType(aSelectionListAttr->selectionType().c_str()));
updateSelectionList(aSelectionListAttr);
return true;
}
}
}
+//********************************************************************
+bool ModuleBase_WidgetMultiSelector::setSelection(const QList<ModuleBase_ViewerPrs>& theValues,
+ int& thePosition)
+{
+ if (thePosition < 0)
+ return false;
+
+ QList<ModuleBase_ViewerPrs>::const_iterator anIt = theValues.begin(), aLast = theValues.end();
+ bool isDone = false;
+ for (int i = thePosition; i < theValues.size(); i++) {
+ ModuleBase_ViewerPrs aValue = theValues[i];
+ thePosition++;
+ bool aProcessed = false;
+ if (isValidSelection(aValue)) {
+ aProcessed = setSelectionCustom(aValue);
+ }
+ // if there is at least one set, the result is true
+ isDone = isDone || aProcessed;
+ // when an object, which do not satisfy the validating process, stop set selection
+ if (!aProcessed)
+ break;
+ }
+ if (isDone) {
+ updateObject(myFeature);
+ // this emit is necessary to call store/restore method an restore type of selection
+ emit valuesChanged();
+ }
+ return isDone;
+}
+
//********************************************************************
bool ModuleBase_WidgetMultiSelector::setSelectionCustom(const ModuleBase_ViewerPrs& thePrs)
{
//********************************************************************
void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
{
- activateShapeSelection();
- QObjectPtrList anEmptyList;
+ activateShapeSelection(true);
+ activateFilters(myWorkshop, true);
+ QList<ModuleBase_ViewerPrs> anEmptyList;
// This method will call Selection changed event which will call onSelectionChanged
// To clear mySelection, myListControl and storeValue()
// So, we don't need to call it
aShapeTypeName = myTypeCombo->itemText(idx);
TopAbs_ShapeEnum aRefType = ModuleBase_Tools::shapeType(aShapeTypeName);
if(aRefType == theShapeType && idx != myTypeCombo->currentIndex()) {
- myIsActive = false;
- activateShapeSelection();
+ activateShapeSelection(false);
+ activateFilters(myWorkshop, false);
bool isBlocked = myTypeCombo->blockSignals(true);
myTypeCombo->setCurrentIndex(idx);
- myIsActive = true;
myTypeCombo->blockSignals(isBlocked);
- activateShapeSelection();
+
+ activateShapeSelection(true);
+ activateFilters(myWorkshop, true);
break;
}
}
}
-void ModuleBase_WidgetMultiSelector::activateShapeSelection()
+void ModuleBase_WidgetMultiSelector::activateShapeSelection(const bool isActivated)
{
ModuleBase_IViewer* aViewer = myWorkshop->viewer();
- if (myIsActive) {
+ if (isActivated) {
QString aNewType = myTypeCombo->currentText();
QIntList aList;
aList.append(ModuleBase_Tools::shapeType(aNewType));
} else {
myWorkshop->deactivateSubShapesSelection();
}
+}
- activateFilters(myWorkshop, myIsActive);
+QList<ModuleBase_ViewerPrs> ModuleBase_WidgetMultiSelector::getAttributeSelection() const
+{
+ QList<ModuleBase_ViewerPrs> aSelected;
+ // Restore selection in the viewer by the attribute selection list
+ if(myFeature) {
+ DataPtr aData = myFeature->data();
+ AttributeSelectionListPtr aListAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
+ if (aListAttr) {
+ for (int i = 0; i < aListAttr->size(); i++) {
+ AttributeSelectionPtr anAttr = aListAttr->value(i);
+ ResultPtr anObject = anAttr->context();
+ if (anObject.get()) {
+ TopoDS_Shape aShape;
+ std::shared_ptr<GeomAPI_Shape> aShapePtr = anAttr->value();
+ if (aShapePtr.get()) {
+ aShape = aShapePtr->impl<TopoDS_Shape>();
+ }
+ aSelected.append(ModuleBase_ViewerPrs(anObject, aShape, NULL));
+ }
+ }
+ }
+ }
+ return aSelected;
}
//********************************************************************
/// 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 theValues the wrapped selection values
+ /// \param thePosition an index in the list of values, the values should be get from the index
+ virtual bool setSelection(const QList<ModuleBase_ViewerPrs>& theValues, int& thePosition);
+
/// Fills the attribute with the value of the selected owner
/// \param theOwner a selected owner
virtual bool setSelectionCustom(const ModuleBase_ViewerPrs& thePrs);
void setCurrentShapeType(const TopAbs_ShapeEnum theShapeType);
/// Start shape selection
- void activateShapeSelection();
+ /// \param isActivated a state whether the shape is activated or deactivated in selection
+ void activateShapeSelection(const bool isActivated);
+
+ /// Return the attribute values wrapped in a list of viewer presentations
+ /// \return a list of viewer presentations, which contains an attribute result and
+ /// a shape. If the attribute do not uses the shape, it is empty
+ QList<ModuleBase_ViewerPrs> getAttributeSelection() const;
protected:
/// Update selection list
//TODO: Move into the base of selectors
ModuleBase_IWorkshop* myWorkshop;
- /// If true then local selector has to be activated in context
- bool myIsActive;
-
/// Provides correspondance between Result object and its shape
typedef QPair<ResultPtr, GeomShapePtr> GeomSelection;
const Config_WidgetAPI* theData,
const std::string& theParentId)
: ModuleBase_WidgetValidated(theParent, theData, theParentId),
- myWorkshop(theWorkshop), myIsActive(false)
+ myWorkshop(theWorkshop)
{
QFormLayout* aLayout = new QFormLayout(this);
ModuleBase_Tools::adjustMargins(aLayout);
ModuleBase_WidgetShapeSelector::~ModuleBase_WidgetShapeSelector()
{
activateSelection(false);
+ activateFilters(myWorkshop, false);
}
//********************************************************************
return isChanged;
}
+//********************************************************************
+QList<ModuleBase_ViewerPrs> ModuleBase_WidgetShapeSelector::getAttributeSelection() const
+{
+ QList<ModuleBase_ViewerPrs> aSelected;
+ if(myFeature) {
+ DataPtr aData = myFeature->data();
+ AttributePtr anAttribute = myFeature->attribute(attributeID());
+
+ ObjectPtr anObject = GeomValidators_Tools::getObject(anAttribute);
+ TopoDS_Shape aShape;
+ std::shared_ptr<GeomAPI_Shape> aShapePtr = getShape();
+ if (aShapePtr.get()) {
+ aShape = aShapePtr->impl<TopoDS_Shape>();
+ }
+ ModuleBase_ViewerPrs aPrs(anObject, aShape, NULL);
+ aSelected.append(aPrs);
+ }
+ return aSelected;
+}
+
//********************************************************************
void ModuleBase_WidgetShapeSelector::clearAttribute()
{
//********************************************************************
void ModuleBase_WidgetShapeSelector::onSelectionChanged()
{
- // In order to make reselection possible
- // TODO: check with MPV clearAttribute();
+ // In order to make reselection possible, set empty object and shape should be done
+ setObject(ObjectPtr(), std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape()));
+ bool aHasObject = false;
QList<ModuleBase_ViewerPrs> aSelectedPrs = getSelectedEntitiesOrObjects(myWorkshop->selection());
- if (aSelectedPrs.empty())
- return;
- ModuleBase_ViewerPrs aPrs = aSelectedPrs.first();
- if (aPrs.isEmpty() || !isValidSelection(aPrs))
- return;
-
- if (!aPrs.isEmpty() && isValidSelection(aPrs)) {
- setSelectionCustom(aPrs);
- // the updateObject method should be called to flush the updated sigal. The workshop listens it,
- // calls validators for the feature and, as a result, updates the Apply button state.
- updateObject(myFeature);
- //if (theObj) {
- // raisePanel();
- //}
- //updateSelectionName();
- //emit valuesChanged();
- emit focusOutWidget(this);
+ if (!aSelectedPrs.empty()) {
+ ModuleBase_ViewerPrs aPrs = aSelectedPrs.first();
+ if (!aPrs.isEmpty() && isValidSelection(aPrs)) {
+ setSelectionCustom(aPrs);
+ aHasObject = true;
+ }
}
-
+ // the updateObject method should be called to flush the updated sigal. The workshop listens it,
+ // calls validators for the feature and, as a result, updates the Apply button state.
+ updateObject(myFeature);
+ // the widget loses the focus only if the selected object is set
+ if (aHasObject)
+ emit focusOutWidget(this);
}
-//********************************************************************
-//bool ModuleBase_WidgetShapeSelector::acceptObjectShape(const ObjectPtr theResult) const
-//{
-// ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theResult);
-//
-// // Check that the shape of necessary type
-// std::shared_ptr<GeomAPI_Shape> aShapePtr = ModelAPI_Tools::shape(aResult);
-// if (!aShapePtr)
-// return false;
-// TopoDS_Shape aShape = aShapePtr->impl<TopoDS_Shape>();
-// if (aShape.IsNull())
-// return false;
-//
-// TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
-// if (aShapeType == TopAbs_COMPOUND) {
-// foreach (QString aType,
-// myShapeTypes) {
-// TopExp_Explorer aEx(aShape, shapeType(aType));
-// if (aEx.More())
-// return true;
-// }
-// } else {
-// foreach (QString aType, myShapeTypes) {
-// if (shapeType(aType) == aShapeType)
-// return true;
-// }
-// }
-// return false;
-//}
-
//********************************************************************
bool ModuleBase_WidgetShapeSelector::acceptSubShape(std::shared_ptr<GeomAPI_Shape> theShape) const
{
bool isNameUpdated = false;
AttributeSelectionPtr aSelect = aData->selection(attributeID());
if (aSelect) {
- myTextLine->setText(QString::fromStdString(aSelect->namingName()));
+ myTextLine->setText(QString::fromStdString(aSelect->namingName(getDefaultValue())));
isNameUpdated = true;
}
if (!isNameUpdated) {
myTextLine->setText(QString::fromStdString(aName.str()));
}
}
- else if (myIsActive) {
- myTextLine->setText("");
+ else {
+ myTextLine->setText(getDefaultValue().c_str());
}
}
}
//********************************************************************
void ModuleBase_WidgetShapeSelector::activateSelection(bool toActivate)
{
- if (myIsActive == toActivate)
- return;
- myIsActive = toActivate;
updateSelectionName();
- if (myIsActive) {
+ if (toActivate) {
QIntList aList;
foreach (QString aType, myShapeTypes) {
aList.append(ModuleBase_Tools::shapeType(aType));
} else {
myWorkshop->deactivateSubShapesSelection();
}
-
- activateFilters(myWorkshop, myIsActive);
}
//********************************************************************
{
connect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
activateSelection(true);
+
+ // Restore selection in the viewer by the attribute selection list
+ myWorkshop->setSelected(getAttributeSelection());
+
+ activateFilters(myWorkshop, true);
}
//********************************************************************
void ModuleBase_WidgetShapeSelector::deactivate()
{
activateSelection(false);
+ activateFilters(myWorkshop, false);
disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
}
/// \param theShape a shape
virtual bool acceptSubShape(std::shared_ptr<GeomAPI_Shape> theShape) const;
- // Get the shape from the attribute it the attribute contain a shape, e.g. selection attribute
- /// \return a shape
- GeomShapePtr getShape() const;
-
/// Clear attribute
void clearAttribute();
/// \return true if it is succeed
virtual bool setObject(ObjectPtr theSelectedObject, GeomShapePtr theShape);
+ /// Get the shape from the attribute if the attribute contains a shape, e.g. selection attribute
+ /// \return a shape
+ virtual GeomShapePtr getShape() const;
+
+ /// Return the attribute values wrapped in a list of viewer presentations
+ /// \return a list of viewer presentations, which contains an attribute result and
+ /// a shape. If the attribute do not uses the shape, it is empty
+ QList<ModuleBase_ViewerPrs> getAttributeSelection() const;
+
//----------- Class members -------------
protected:
/// Label of the widget
/// List of accepting shapes types
QStringList myShapeTypes;
- /// Active/inactive flag
- bool myIsActive;
-
/// backup parameters of the model attribute. The class processes three types of attribute:
/// Reference, RefAttr and Selection. Depending on the attribute type, only the attribute parameter
/// values are reserved in the backup
}
//********************************************************************
-bool ModuleBase_WidgetValidated::setSelection(ModuleBase_ViewerPrs theValue)
+bool ModuleBase_WidgetValidated::setSelection(const QList<ModuleBase_ViewerPrs>& theValues, int& thePosition)
{
+ if (thePosition < 0 || thePosition >= theValues.size())
+ return false;
+ ModuleBase_ViewerPrs aValue = theValues[thePosition];
+ thePosition++;
+
bool isDone = false;
- if (isValidSelection(theValue)) {
- isDone = setSelectionCustom(theValue);
+ if (isValidSelection(aValue)) {
+ isDone = setSelectionCustom(aValue);
updateObject(myFeature);
emit valuesChanged();
}
if (aSelectedPrs.empty()) {
// the selection in Object Browser
QObjectPtrList anObjects = theSelection->selectedObjects();
- QObjectPtrList::const_iterator anIt = anObjects.begin(), aLast = anObjects.end();
- for (; anIt != aLast; anIt++) {
- ObjectPtr anObject = *anIt;
- if (anObject.get() != NULL) {
- aSelectedPrs.append(ModuleBase_ViewerPrs(anObject, TopoDS_Shape(), NULL));
- }
- }
+ aSelectedPrs = ModuleBase_ISelection::getViewerPrs(anObjects);
}
return aSelectedPrs;
}
/// This value should be processed in the widget according to the needs
/// The method is called by the current operation to process the operation preselection.
/// It is redefined to check the value validity and if it is, fill the attribute with by value
- /// \param theValue the wrapped widget value
- virtual bool setSelection(ModuleBase_ViewerPrs theValue);
+ /// \param theValues the wrapped selection values
+ /// \param thePosition an index in the list of values, the values should be get from the index
+ virtual bool setSelection(const QList<ModuleBase_ViewerPrs>& theValues, int& thePosition);
protected:
/// Creates a backup of the current values of the attribute
//******************************************************
void NewGeom_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
{
- myWorkshop->contextMenuMgr()->addViewerItems(theMenu);
+ myWorkshop->contextMenuMgr()->addViewerMenu(theMenu);
LightApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
}
QHBoxLayout* aBoxLay = new QHBoxLayout(myButtonFrame);
aBoxLay->setContentsMargins(2, 0, 0, 0);
aBoxLay->setSpacing(1);
+ QSizePolicy aSizePolicy;
+ aSizePolicy.setControlType(QSizePolicy::ToolButton);
+ myButtonFrame->setSizePolicy(aSizePolicy);
myThisButton = new QToolButton(myButtonFrame);
myThisButton->setDefaultAction(this);
#include "NewGeom_SalomeViewer.h"
#include "NewGeom_OCCSelector.h"
-#include <OCCViewer_ViewWindow.h>
#include <OCCViewer_ViewPort3d.h>
#include <OCCViewer_ViewFrame.h>
void NewGeom_SalomeViewer::onViewCreated(SUIT_ViewWindow* theView)
{
myView->setCurrentView(theView);
+
+ OCCViewer_ViewFrame* aView = dynamic_cast<OCCViewer_ViewFrame*>(theView);
+
+ OCCViewer_ViewWindow* aWnd = aView->getView(OCCViewer_ViewFrame::MAIN_VIEW);
+ if (aWnd)
+ connect(aWnd, SIGNAL(vpTransformationFinished(OCCViewer_ViewWindow::OperationType)),
+ this, SLOT(onViewTransformed(OCCViewer_ViewWindow::OperationType)));
+
emit viewCreated(myView);
}
//**********************************************
-void NewGeom_SalomeViewer::onActivated(SUIT_ViewWindow*)
+void NewGeom_SalomeViewer::onActivated(SUIT_ViewWindow* theView)
{
+ myView->setCurrentView(theView);
emit activated(myView);
}
aContext->UpdateCurrentViewer();
}
}
+
+//***************************************
+void NewGeom_SalomeViewer::onViewTransformed(OCCViewer_ViewWindow::OperationType theType)
+{
+ emit viewTransformed((int) theType);
+}
#include <ModuleBase_IViewer.h>
#include <ModuleBase_IViewWindow.h>
+#include <OCCViewer_ViewWindow.h>
+
#include <V3d_View.hxx>
class SUIT_ViewWindow;
void onActivated(SUIT_ViewWindow*);
void onSelectionChanged();
+ void onViewTransformed(OCCViewer_ViewWindow::OperationType);
private:
NewGeom_OCCSelector* mySelector;
INCLUDE(Common)
INCLUDE(FindPython)
+INCLUDE(UnitTest)
SET(PROJECT_HEADERS
ParametersPlugin.h
ParametersPlugin_Parameter.h
ParametersPlugin_PyInterp.h
ParametersPlugin_Validators.h
+ ParametersPlugin_EvalListener.h
)
SET(PROJECT_SOURCES
ParametersPlugin_Parameter.cpp
ParametersPlugin_PyInterp.cpp
ParametersPlugin_Validators.cpp
+ ParametersPlugin_EvalListener.cpp
)
SET(XML_RESOURCES
INSTALL(TARGETS ParametersPlugin DESTINATION plugins)
INSTALL(FILES ${XML_RESOURCES} DESTINATION plugins)
+
+ADD_UNIT_TESTS(TestParameterCreation.py
+ )
--- /dev/null
+/*
+ * ParametersPlugin_EvalListener.cpp
+ *
+ * Created on: Apr 28, 2015
+ * Author: sbh
+ */
+
+#include <ParametersPlugin_EvalListener.h>
+
+#include <Events_Error.h>
+
+#include <ModelAPI_Events.h>
+#include <ModelAPI_Tools.h>
+#include <ModelAPI_AttributeDouble.h>
+
+#include <string>
+#include <sstream>
+
+ParametersPlugin_EvalListener::ParametersPlugin_EvalListener()
+{
+ Events_Loop* aLoop = Events_Loop::loop();
+ const Events_ID kEvaluationEvent = ModelAPI_AttributeEvalMessage::eventId();
+ aLoop->registerListener(this, kEvaluationEvent, NULL, true);
+
+ myInterp = std::shared_ptr<ParametersPlugin_PyInterp>(new ParametersPlugin_PyInterp());
+ myInterp->initialize();
+}
+
+ParametersPlugin_EvalListener::~ParametersPlugin_EvalListener()
+{
+}
+
+void ParametersPlugin_EvalListener::processEvent(const std::shared_ptr<Events_Message>& theMessage)
+{
+ if (!theMessage.get())
+ return;
+
+ const Events_ID kEvaluationEvent = ModelAPI_AttributeEvalMessage::eventId();
+ if (theMessage->eventID() == kEvaluationEvent) {
+ std::shared_ptr<ModelAPI_AttributeEvalMessage> aMessage =
+ std::dynamic_pointer_cast<ModelAPI_AttributeEvalMessage>(theMessage);
+ AttributeDoublePtr aDoubleAttribute =
+ std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aMessage->attribute());
+ if (aDoubleAttribute.get()) {
+ std::string anError;
+ double aValue = evaluate(aDoubleAttribute->text(), anError);
+ if (anError.empty()) {
+ aDoubleAttribute->setValue(aValue);
+ }
+ }
+ } else {
+ Events_Error::send(std::string("ParametersPlugin python interpreter, unhandled message caught: ")
+ + theMessage->eventID().eventText());
+ }
+}
+
+double ParametersPlugin_EvalListener::evaluate(const std::string& theExpression,
+ std::string& theError)
+{
+ std::list<std::string> anExprParams = myInterp->compile(theExpression);
+ // find expression's params in the model
+ std::list<std::string> aContext;
+ std::list<std::string>::iterator it = anExprParams.begin();
+ for ( ; it != anExprParams.end(); it++) {
+ double aValue;
+ if (!ModelAPI_Tools::findVariable(*it, aValue)) continue;
+
+ std::ostringstream sstream;
+ sstream << aValue;
+ std::string aParamValue = sstream.str();
+ aContext.push_back(*it + "=" + aParamValue);
+ }
+ myInterp->extendLocalContext(aContext);
+ double result = myInterp->evaluate(theExpression, theError);
+ myInterp->clearLocalContext();
+ return result;
+}
+
--- /dev/null
+/*
+ * ParametersPlugin_EvalListener.h
+ *
+ * Created on: Apr 28, 2015
+ * Author: sbh
+ */
+
+#ifndef SRC_PARAMETERSPLUGIN_EVALLISTENER_H_
+#define SRC_PARAMETERSPLUGIN_EVALLISTENER_H_
+
+#include <ParametersPlugin.h>
+#include <Events_Loop.h>
+#include <ParametersPlugin_PyInterp.h>
+
+class PARAMETERSPLUGIN_EXPORT ParametersPlugin_EvalListener : public Events_Listener
+{
+ public:
+ ParametersPlugin_EvalListener();
+ virtual ~ParametersPlugin_EvalListener();
+
+ virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
+ protected:
+ double evaluate(const std::string& theExpression,
+ std::string& theError) ;
+
+ private:
+ std::shared_ptr<ParametersPlugin_PyInterp> myInterp;
+};
+
+#endif /* SRC_PARAMETERSPLUGIN_PARAMETERSPLUGIN_EVALLISTENER_H_ */
ParametersPlugin_Parameter::ParametersPlugin_Parameter()
{
- myInterp = new ParametersPlugin_PyInterp();
+ myInterp = std::shared_ptr<ParametersPlugin_PyInterp>(new ParametersPlugin_PyInterp());
myInterp->initialize();
}
ParametersPlugin_Parameter::~ParametersPlugin_Parameter()
{
- delete myInterp;
}
void ParametersPlugin_Parameter::initAttributes()
#include "ParametersPlugin.h"
#include <ModelAPI_Feature.h>
+#include <memory>
+
class ParametersPlugin_PyInterp;
class ParametersPlugin_Parameter : public ModelAPI_Feature
/// Extrusion kind
inline static const std::string& ID()
{
- static const std::string MY_EXTRUSION_ID("Parameter");
- return MY_EXTRUSION_ID;
+ static const std::string MY_PARAMETER_ID("Parameter");
+ return MY_PARAMETER_ID;
}
/// attribute name of references sketch entities list, it should contain a sketch result or
/// a pair a sketch result to sketch face
double evaluate(const std::string& theExpression, std::string& theError);
private:
- ParametersPlugin_PyInterp* myInterp;
+ std::shared_ptr<ParametersPlugin_PyInterp> myInterp;
};
#endif
new ParametersPlugin_VariableValidator);
aFactory->registerValidator("Parameters_ExpressionValidator",
new ParametersPlugin_ExpressionValidator);
+
+ myEvalListener = std::shared_ptr<ParametersPlugin_EvalListener>(new ParametersPlugin_EvalListener());
}
FeaturePtr ParametersPlugin_Plugin::createFeature(std::string theFeatureID)
#define PARAMETERSPLUGIN_PLUGIN_H_
#include <ParametersPlugin.h>
+#include <ParametersPlugin_EvalListener.h>
+
#include <ModelAPI_Plugin.h>
#include <ModelAPI_Feature.h>
public:
ParametersPlugin_Plugin();
+
+ std::shared_ptr<ParametersPlugin_EvalListener> myEvalListener;
};
#endif
}
_global_context = PyModule_GetDict(m); // get interpreter global variable context
Py_INCREF(_global_context);
- _local_context = _global_context;
+ _local_context = PyDict_New();
+ Py_INCREF(_local_context);
return PyRun_SimpleString("from math import *") == 0;
}
+
+void ParametersPlugin_PyInterp::closeContext()
+{
+ Py_XDECREF(_local_context);
+ PyInterp_Interp::closeContext();
+}
std::string errorMessage();
// Overrides PyInterp_Interp
virtual bool initContext();
+ virtual void closeContext();
};
#endif /* PARAMETERSPLUGIN_PYINTERP_H_ */
--- /dev/null
+"""
+ TestParameterCreation.py
+
+ class ParametersPlugin_Parameter
+ static const std::string MY_PARAMETER_ID("Parameter");
+ static const std::string MY_VARIABLE_ID("variable");
+ static const std::string MY_EXPRESSION_ID("expression");
+
+ data()->addAttribute(ParametersPlugin_Parameter::VARIABLE_ID(),
+ ModelAPI_AttributeString::typeId());
+ data()->addAttribute(ParametersPlugin_Parameter::EXPRESSION_ID(),
+ ModelAPI_AttributeString::typeId());
+
+ class ModelAPI_ResultParameter
+ static const std::string MY_VALUE_ID("Value");
+ static const std::string MY_VALUE_ID("State");
+"""
+
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+from GeomDataAPI import *
+from ModelAPI import *
+import math
+
+__updated__ = "2015-04-27"
+
+aSession = ModelAPI_Session.get()
+aDocument = aSession.moduleDocument()
+#=========================================================================
+# Creation of a sketch
+#=========================================================================
+aSession.startOperation()
+aSketchCommonFeature = aDocument.addFeature("Sketch")
+aSketchFeature = featureToCompositeFeature(aSketchCommonFeature)
+origin = geomDataAPI_Point(aSketchFeature.attribute("Origin"))
+origin.setValue(0, 0, 0)
+dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX"))
+dirx.setValue(1, 0, 0)
+norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm"))
+norm.setValue(0, 0, 1)
+aSession.finishOperation()
+#=========================================================================
+# Create several parameters.
+# 1. Basic parameter definition:
+# x1 = 150.0, y1 = 50.0, cr1 = 100.0, cl = 250.0;
+# 2. Check referencing between parameters:
+# x2 = x1 + 100.0, y2 = y1/2.
+# 3. Check math module
+# tm = 2 * pi
+#=========================================================================
+ltNames = ["x1", "y1", "cr1", "cl1"]
+ltExpressions = ["150.", "50.", "100.", "250."]
+dtParams = {}
+aSession.startOperation()
+for name, expr in zip(ltNames, ltExpressions):
+ aParam = aDocument.addFeature("Parameter")
+ aParamName = aParam.string("variable")
+ aParamName.setValue(name)
+ aParamExpr = aParam.string("expression")
+ aParamExpr.setValue(expr)
+ dtParams[name] = aParam
+aSession.finishOperation()
+assert (len(dtParams) == len(ltNames))
+# Check results
+for name, expr in zip(ltNames, ltExpressions):
+ aParam = dtParams[name]
+ aResultAttr = modelAPI_ResultParameter(aParam.firstResult())
+ assert(aResultAttr.data())
+ assert(aResultAttr.data().real("Value"))
+ aResultValue = aResultAttr.data().real("Value").value()
+ print aResultValue, " == ", float(expr)
+ assert(aResultValue == float(expr))
+
+# Check referencing between parameters
+aSession.startOperation()
+ltNames = ["x2", "y2"]
+ltExpressions = ["x1 + 100.0", "y1/2."]
+aSession.startOperation()
+for name, expr in zip(ltNames, ltExpressions):
+ aParam = aDocument.addFeature("Parameter")
+ aParamName = aParam.string("variable")
+ aParamName.setValue(name)
+ aParamExpr = aParam.string("expression")
+ aParamExpr.setValue(expr)
+ dtParams[name] = aParam
+aSession.finishOperation()
+
+aParam = dtParams["x2"]
+aResultAttr = modelAPI_ResultParameter(aParam.firstResult())
+assert(aResultAttr.data())
+assert(aResultAttr.data().real("Value"))
+aX2Value = aResultAttr.data().real("Value").value()
+assert (aX2Value == 250.)
+aParam = dtParams["y2"]
+aResultAttr = modelAPI_ResultParameter(aParam.firstResult())
+assert(aResultAttr.data())
+assert(aResultAttr.data().real("Value"))
+aY2Value = aResultAttr.data().real("Value").value()
+assert (aY2Value == 25.)
+# check math
+aSession.startOperation()
+aParam = aDocument.addFeature("Parameter")
+aParamName = aParam.string("variable")
+aParamName.setValue("tm")
+aParamExpr = aParam.string("expression")
+aParamExpr.setValue("round(2 * pi, 6)")
+aSession.finishOperation()
+aResultAttr = modelAPI_ResultParameter(aParam.firstResult())
+assert(aResultAttr.data())
+assert(aResultAttr.data().real("Value"))
+aTmValue = aResultAttr.data().real("Value").value()
+assert (aTmValue == round(2 * math.pi, 6))
+#=========================================================================
+# Use parameters to set radius of a circle :
+# 1. Create a circle (250., 250), r = 25.
+# 2. Set a 'cr1' as text value of radius attribute
+#=========================================================================
+aSession.startOperation()
+aSketchCircle = aSketchFeature.addFeature("SketchCircle")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
+aRadiusAttr = aSketchCircle.real("CircleRadius")
+anCircleCentr.setValue(250., 250)
+aRadiusAttr.setValue(25.)
+aSession.finishOperation()
+# Apply parameter
+aSession.startOperation()
+aRadiusAttr.setText("cr1")
+aSession.finishOperation()
+assert(aRadiusAttr.value() == 100.)
+#=========================================================================
+# Use parameters for a length constraint on a line:
+# 1. Create a line A(10., 10.) - B(-10., -10.)
+# 2. Create a length constraint, l = 100;
+# 3. Set a 'cl1' as text value of length attribute
+#=========================================================================
+aSession.startOperation()
+aSketchLine = aSketchFeature.addFeature("SketchLine")
+aLineStartPoint = geomDataAPI_Point2D(aSketchLine.attribute("StartPoint"))
+aLineEndPoint = geomDataAPI_Point2D(aSketchLine.attribute("EndPoint"))
+aLineStartPoint.setValue(10., 10.)
+aLineEndPoint.setValue(-10., -10.)
+aSession.finishOperation()
+# Length constraint
+aSession.startOperation()
+aLengthConstraint = aSketchFeature.addFeature("SketchConstraintLength")
+refattrA = aLengthConstraint.refattr("ConstraintEntityA")
+refattrA.setObject(modelAPI_ResultConstruction(aSketchLine.firstResult()))
+aLengthConstraint.execute()
+aSession.finishOperation()
+
+# Apply parameter
+aSession.startOperation()
+aLengthAttr = aLengthConstraint.real("ConstraintValue")
+aLengthAttr.setText("cl1")
+aSession.finishOperation()
+assert(aLengthAttr.value() == 250.)
+#=========================================================================
+# End of test
+#=========================================================================
PartSet_WidgetSketchLabel.h
PartSet_Validators.h
PartSet_WidgetPoint2d.h
+ PartSet_WidgetPoint2dAngle.h
PartSet_WidgetEditor.h
PartSet_WidgetMultiSelector.h
PartSet_WidgetPoint2dDistance.h
PartSet_WidgetShapeSelector.h
+ PartSet_WidgetFileSelector.h
PartSet_Filters.h
PartSet_SketcherMgr.h
PartSet_MenuMgr.h
+ PartSet_DocumentDataModel.h
+ PartSet_PartDataModel.h
+ PartSet_DataTreeModel.h
)
SET(PROJECT_SOURCES
PartSet_WidgetEditor.cpp
PartSet_WidgetMultiSelector.cpp
PartSet_WidgetPoint2d.cpp
+ PartSet_WidgetPoint2dAngle.cpp
PartSet_WidgetPoint2dDistance.cpp
PartSet_WidgetShapeSelector.cpp
+ PartSet_WidgetFileSelector.cpp
PartSet_Filters.cpp
PartSet_SketcherMgr.cpp
PartSet_MenuMgr.cpp
+ PartSet_DocumentDataModel.cpp
+ PartSet_PartDataModel.cpp
)
SET(PROJECT_RESOURCES
${CMAKE_SOURCE_DIR}/src/SketchPlugin
${CMAKE_SOURCE_DIR}/src/SketcherPrs
${CMAKE_SOURCE_DIR}/src/FeaturesPlugin
+ ${CMAKE_SOURCE_DIR}/src/PartSetPlugin
${CMAKE_SOURCE_DIR}/src/GeomAPI
${CMAKE_SOURCE_DIR}/src/GeomValidators
${CMAKE_SOURCE_DIR}/src/AppElements
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+#ifndef PartSet_DataTreeModel_H
+#define PartSet_DataTreeModel_H
+
+#include "PartSet.h"
+
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_ResultPart.h>
+#include <ModelAPI_Session.h>
+
+#include <QAbstractItemModel>
+#include <QColor>
+
+/**\class PartSet_FeaturesModel
+ * \ingroup GUI
+ * \brief Abstaract class of model object which operates with features data.
+ */
+class PARTSET_EXPORT PartSet_FeaturesModel : public QAbstractItemModel
+{
+ public:
+ /// Constructor
+ /// \param theParent a parent object
+ PartSet_FeaturesModel(QObject* theParent)
+ : QAbstractItemModel(theParent),
+ myItemsColor(Qt::black)
+ {
+ }
+
+ //! Returns Feature object by the given Model index.
+ //! Returns 0 if the given index is not index of a feature
+ /// \param theIndex a model index
+ virtual ObjectPtr object(const QModelIndex& theIndex) const = 0;
+
+ //! Returns QModelIndex which corresponds to the given feature
+ //! If the feature is not found then index is not valid
+ virtual QModelIndex objectIndex(const ObjectPtr& theFeature) const = 0;
+
+ //! Returns parent index of the given feature
+ virtual QModelIndex findParent(const ObjectPtr& theObject) const = 0;
+
+ //! Returns index corresponded to the group
+ //! \param theGroup a group name
+ virtual QModelIndex findGroup(const std::string& theGroup) const = 0;
+
+ //! Set color of items
+ void setItemsColor(const QColor& theColor)
+ {
+ myItemsColor = theColor;
+ }
+
+ //! Returns color of items
+ QColor itemsColor() const
+ {
+ return myItemsColor;
+ }
+
+ protected:
+ /// Color of items
+ QColor myItemsColor;
+};
+
+/**\class PartSet_PartModel
+ * \ingroup GUI
+ * \brief Abstaract class of model object which operates with parts data.
+ */
+class PartSet_PartModel : public PartSet_FeaturesModel
+{
+ public:
+ /// Constructor
+ /// \param theParent a parent object
+ PartSet_PartModel(QObject* theParent)
+ : PartSet_FeaturesModel(theParent)
+ {
+ }
+
+ /// Set part id
+ /// \param theId a new id
+ void setPart(FeaturePtr thePart)
+ {
+ myPart = thePart;
+ }
+
+ /// Returns Id of the part
+ FeaturePtr part() const { return myPart; }
+
+ //! Returns true if the given document is a sub-document of this tree
+ //! \param theDoc a document to check
+ virtual bool hasDocument(const DocumentPtr& theDoc) const = 0;
+
+ /// Returns position of the part in history
+ int position() const
+ {
+ DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+ return aRootDoc->index(myPart);
+ }
+
+ protected:
+ //! Id of the current part object in the document
+ FeaturePtr myPart;
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+#include "PartSet_DocumentDataModel.h"
+#include "PartSet_PartDataModel.h"
+#include "PartSet_Module.h"
+//#include "XGUI_Tools.h"
+
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_ResultPart.h>
+#include <ModelAPI_Events.h>
+#include <ModelAPI_Object.h>
+
+#include <Events_Loop.h>
+
+#include <Config_FeatureMessage.h>
+#include <ModuleBase_Tools.h>
+#include <ModuleBase_ActionInfo.h>
+
+#include <PartSetPlugin_Part.h>
+
+#include <QIcon>
+#include <QString>
+#include <QBrush>
+#include <QTreeView>
+
+#include <set>
+
+#define ACTIVE_COLOR QColor(0,72,140)
+#define PASSIVE_COLOR Qt::black
+
+QMap<QString, QString> PartSet_DocumentDataModel::myIcons;
+
+
+PartSet_DocumentDataModel::PartSet_DocumentDataModel(QObject* theParent)
+ : ModuleBase_IDocumentDataModel(theParent),
+ myActivePartModel(0)
+{
+ // Create a top part of data tree model
+ myModel = new PartSet_TopDataModel(this);
+ myModel->setItemsColor(ACTIVE_COLOR);
+
+ Events_Loop* aLoop = Events_Loop::loop();
+ aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+ aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
+ aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
+ aLoop->registerListener(this, Events_Loop::eventByName(Config_FeatureMessage::GUI_EVENT()));
+}
+
+PartSet_DocumentDataModel::~PartSet_DocumentDataModel()
+{
+ clearModelIndexes();
+ clearSubModels();
+}
+
+void PartSet_DocumentDataModel::processEvent(const std::shared_ptr<Events_Message>& theMessage)
+{
+ DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+
+
+ // Created object event *******************
+ if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
+ std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
+ std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
+ std::set<ObjectPtr> aObjects = aUpdMsg->objects();
+
+ std::set<ObjectPtr>::const_iterator aIt;
+ for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
+ ObjectPtr aObject = (*aIt);
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
+ if (aFeature && (!aFeature->isInHistory()))
+ continue;
+
+ DocumentPtr aDoc = aObject->document();
+ if (aDoc == aRootDoc) { // If root objects
+ if (aObject->groupName() == ModelAPI_ResultPart::group()) { // Update only Parts group
+ // Add a new part
+ int aStart = aRootDoc->size(ModelAPI_ResultPart::group());
+ if (aStart > 0) {
+ FeaturePtr aPartFeature = ModelAPI_Feature::feature(aObject);
+ PartSet_PartDataModel* aModel = new PartSet_PartDataModel(this);
+ int anId = aRootDoc->index(aPartFeature);
+ aModel->setPart(aPartFeature);
+ myPartModels.append(aModel);
+ insertRow(aStart, partFolderNode(0));
+ }
+ } else { // Update top groups (other except parts
+ QModelIndex aIndex = myModel->findParent(aObject);
+ int aStart = myModel->rowCount(aIndex) - 1;
+ if (aStart < 0)
+ aStart = 0;
+ aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
+ insertRow(aStart, aIndex);
+ }
+ } else { // if sub-objects of first level nodes
+ PartSet_PartModel* aPartModel = 0;
+ foreach (PartSet_PartModel* aPart, myPartModels) {
+ if (aPart->hasDocument(aDoc)) {
+ aPartModel = aPart;
+ break;
+ }
+ }
+ if (aPartModel) {
+ QModelIndex aIndex = aPartModel->findParent(aObject);
+ int aStart = aPartModel->rowCount(aIndex); // check this index
+ aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
+ insertRow(aStart, aIndex);
+ } else
+ reset();
+ }
+ }
+ // Deleted object event ***********************
+ } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
+ std::shared_ptr<ModelAPI_ObjectDeletedMessage> aUpdMsg =
+ std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
+ DocumentPtr aDoc = aUpdMsg->document();
+ std::set<std::string> aGroups = aUpdMsg->groups();
+
+ std::set<std::string>::const_iterator aIt;
+ for (aIt = aGroups.begin(); aIt != aGroups.end(); ++aIt) {
+ std::string aGroup = (*aIt);
+ if (aDoc == aRootDoc) { // If root objects
+ if (aGroup == ModelAPI_ResultPart::group()) { // Update only Parts group
+ PartSet_PartModel* aDelPartModel = 0;
+ foreach (PartSet_PartModel* aPartModel, myPartModels) {
+ if (aPartModel->position() == -1) {
+ aDelPartModel = aPartModel;
+ break;
+ }
+ }
+ if (aDelPartModel) {
+ deactivatePart();
+ int aStart = myPartModels.size() - 1;
+ removeSubModel(aDelPartModel);
+ removeRow(aStart, partFolderNode(0));
+ }
+ } else { // Update top groups (other except parts
+ QModelIndex aIndex = myModel->findGroup(aGroup);
+ int aStart = myModel->rowCount(aIndex);
+ aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
+ removeRow(aStart, aIndex);
+ }
+ } else {
+ PartSet_PartModel* aPartModel = 0;
+ foreach (PartSet_PartModel* aPart, myPartModels) {
+ if (aPart->hasDocument(aDoc)) {
+ aPartModel = aPart;
+ break;
+ }
+ }
+ if (aPartModel) {
+ QModelIndex aIndex = aPartModel->findGroup(aGroup);
+ int aStart = aPartModel->rowCount(aIndex);
+ aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
+ removeRow(aStart, aIndex);
+ }
+ }
+ }
+ // Deleted object event ***********************
+ } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
+ //std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg = std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
+ //ObjectPtr aFeature = aUpdMsg->feature();
+ //DocumentPtr aDoc = aFeature->document();
+
+ // TODO: Identify the necessary index by the modified feature
+ QModelIndex aIndex;
+ emit dataChanged(aIndex, aIndex);
+
+ // Reset whole tree **************************
+ } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(Config_FeatureMessage::GUI_EVENT())) {
+ std::shared_ptr<Config_FeatureMessage> aFeatureMsg =
+ std::dynamic_pointer_cast<Config_FeatureMessage>(theMessage);
+ if (!aFeatureMsg->isInternal()) {
+ ActionInfo aFeatureInfo;
+ aFeatureInfo.initFrom(aFeatureMsg);
+ // Remember features icons
+ myIcons[QString::fromStdString(aFeatureMsg->id())] = aFeatureInfo.iconFile;
+ }
+ } else {
+ rebuildDataTree();
+ }
+}
+
+void PartSet_DocumentDataModel::rebuildDataTree()
+{
+ DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+
+ beginResetModel();
+ clearModelIndexes();
+
+ // Delete extra models
+ ObjectPtr aObj;
+ FeaturePtr aFeature;
+ QList<PartSet_PartModel*> aDelList;
+ foreach (PartSet_PartModel* aPartModel, myPartModels) {
+ if (aPartModel->position() == -1)
+ aDelList.append(aPartModel);
+ }
+ foreach (PartSet_PartModel* aPartModel, aDelList) {
+ removeSubModel(aPartModel);
+ }
+ // Add non existing models
+ int aHistNb = aRootDoc->size(ModelAPI_Feature::group());
+ for (int i = 0; i < aHistNb; i++) {
+ aObj = aRootDoc->object(ModelAPI_Feature::group(), i);
+ aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+ if (aFeature->getKind() == PartSetPlugin_Part::ID()) {
+ if (!findPartModel(aFeature)) {
+ PartSet_PartDataModel* aModel = new PartSet_PartDataModel(this);
+ aModel->setPart(aFeature);
+ myPartModels.append(aModel);
+ }
+ }
+ }
+ endResetModel();
+}
+
+QVariant PartSet_DocumentDataModel::data(const QModelIndex& theIndex, int theRole) const
+{
+ if (!theIndex.isValid())
+ return QVariant();
+
+ DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+ QModelIndex aParent = theIndex.parent();
+ if ((theIndex.column() == 1) ) {
+ if ((theIndex.internalId() >= PartsFolder) && (theIndex.internalId() <= PartResult)) {
+ if (ModelAPI_Session::get()->activeDocument() == aRootDoc) {
+ if (!aParent.isValid()) {
+ switch (theRole) {
+ case Qt::DecorationRole:
+ if (theIndex.row() == lastHistoryRow())
+ return QIcon(":pictures/arrow.png");
+ }
+ }
+ }
+ } else {
+ QModelIndex* aIndex = toSourceModelIndex(theIndex);
+ const QAbstractItemModel* aModel = aIndex->model();
+ if (isPartSubModel(aModel)) {
+ return aModel->data(*aIndex, theRole);
+ }
+ }
+ return QVariant();
+ }
+
+ switch (theIndex.internalId()) {
+ case PartsFolder:
+ switch (theRole) {
+ case Qt::DisplayRole:
+ return tr("Parts") + QString(" (%1)").arg(rowCount(theIndex));
+ case Qt::DecorationRole:
+ return QIcon(":pictures/constr_folder.png");
+ case Qt::ToolTipRole:
+ return tr("Parts folder");
+ case Qt::ForegroundRole:
+ if (myActivePartIndex.isValid())
+ return QBrush(PASSIVE_COLOR);
+ else
+ return QBrush(ACTIVE_COLOR);
+ default:
+ return QVariant();
+ }
+ break;
+ case HistoryNode:
+ {
+ int aOffset = historyOffset();
+ ObjectPtr aObj = aRootDoc->object(ModelAPI_Feature::group(), theIndex.row() - aOffset);
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+ if (!aFeature)
+ return QVariant();
+ switch (theRole) {
+ case Qt::DisplayRole:
+ if (aFeature)
+ return aFeature->data()->name().c_str();
+ else
+ return QVariant();
+ case Qt::DecorationRole:
+ return featureIcon(aFeature);
+ case Qt::ToolTipRole:
+ return tr("Feature object");
+ case Qt::ForegroundRole:
+ if (theIndex.row() > lastHistoryRow())
+ return QBrush(Qt::lightGray);
+ else {
+ if (myActivePartIndex.isValid())
+ return QBrush(PASSIVE_COLOR);
+ else
+ return QBrush(ACTIVE_COLOR);
+ }
+ default:
+ return QVariant();
+ }
+ }
+ break;
+ case PartResult:
+ {
+ ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), theIndex.row());
+ if (aObject) {
+ switch (theRole) {
+ case Qt::DisplayRole:
+ return std::dynamic_pointer_cast<ModelAPI_Object>(aObject)->data()->name().c_str();
+ case Qt::DecorationRole:
+ return QIcon(":pictures/part_ico.png");
+ case Qt::ForegroundRole:
+ {
+ if (theIndex == myActivePartIndex)
+ return QBrush(ACTIVE_COLOR);
+ else
+ return QBrush(PASSIVE_COLOR);
+ }
+ default:
+ return QVariant();
+ }
+ }
+ }
+ break;
+ }
+ if (aParent.internalId() == HistoryNode) {
+ int aId = aParent.row() - historyOffset();
+ QModelIndex* aIndex = toSourceModelIndex(theIndex);
+ return findPartModel(aId)->data(*aIndex, theRole);
+ }
+ return toSourceModelIndex(theIndex)->data(theRole);
+}
+
+QVariant PartSet_DocumentDataModel::headerData(int theSection, Qt::Orientation theOrient,
+ int theRole) const
+{
+ return QVariant();
+}
+
+int PartSet_DocumentDataModel::rowCount(const QModelIndex& theParent) const
+{
+ SessionPtr aSession = ModelAPI_Session::get();
+ if (!aSession->hasModuleDocument())
+ return 0;
+ DocumentPtr aRootDoc = aSession->moduleDocument();
+ if (!theParent.isValid()) {
+ // Size of external models
+ int aVal = historyOffset();
+ // Plus history size
+ aVal += aRootDoc->size(ModelAPI_Feature::group());
+ return aVal;
+ }
+ if (theParent.internalId() == PartsFolder) {
+ return aRootDoc->size(ModelAPI_ResultPart::group());
+ //int aSize = myPartModels.size();
+ //return myPartModels.size();
+ }
+ if (theParent.internalId() == HistoryNode) {
+ int aId = theParent.row() - historyOffset();
+ PartSet_PartModel* aModel = findPartModel(aId);
+ if (aModel)
+ return aModel->rowCount(QModelIndex());
+ return 0;
+ }
+ if (theParent.internalId() == PartResult)
+ return 0;
+
+ QModelIndex* aParent = toSourceModelIndex(theParent);
+ const QAbstractItemModel* aModel = aParent->model();
+ if (!isSubModel(aModel))
+ return 0;
+
+ /*if (isPartSubModel(aModel)) {
+ if (aModel != myActivePart)
+ return 0;
+ }*/
+ return aModel->rowCount(*aParent);
+}
+
+int PartSet_DocumentDataModel::columnCount(const QModelIndex& theParent) const
+{
+ return 2;
+}
+
+QModelIndex PartSet_DocumentDataModel::index(int theRow, int theColumn,
+ const QModelIndex& theParent) const
+{
+ QModelIndex aIndex;
+ if (!theParent.isValid()) {
+ int aOffs = myModel->rowCount();
+ if (theRow < aOffs) {
+ aIndex = myModel->index(theRow, theColumn, theParent);
+ aIndex = createIndex(theRow, theColumn, (void*) getModelIndex(aIndex));
+ } else {
+ if (theRow == aOffs) // Create Parts node
+ aIndex = partFolderNode(theColumn);
+ else {
+ // create history node
+ aIndex = createIndex(theRow, theColumn, HistoryNode);
+ }
+ }
+ } else {
+ if (theParent.internalId() == PartsFolder) {
+ aIndex = createIndex(theRow, theColumn, PartResult);
+ } else {
+ if (theParent.internalId() == HistoryNode) {
+ int aId = theParent.row() - historyOffset();
+ aIndex = findPartModel(aId)->index(theRow, theColumn, QModelIndex());
+ } else {
+ QModelIndex* aParent = (QModelIndex*) theParent.internalPointer();
+ aIndex = aParent->model()->index(theRow, theColumn, (*aParent));
+ }
+ aIndex = createIndex(theRow, theColumn, (void*) getModelIndex(aIndex));
+ }
+ }
+ return aIndex;
+}
+
+QModelIndex PartSet_DocumentDataModel::parent(const QModelIndex& theIndex) const
+{
+ if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
+ return QModelIndex();
+
+ if (theIndex.internalId() == PartResult)
+ return partFolderNode(0);
+
+ QModelIndex* aIndex = toSourceModelIndex(theIndex);
+ const QAbstractItemModel* aModel = aIndex->model();
+ if (!isSubModel(aModel))
+ return QModelIndex();
+
+ QModelIndex aIndex1 = aModel->parent(*aIndex);
+ const PartSet_PartModel* aPartModel = dynamic_cast<const PartSet_PartModel*>(aModel);
+ if (aPartModel && (!aIndex1.isValid())) {
+ int aId = aPartModel->position();
+ int aRow = aId + historyOffset();
+ return createIndex(aRow, 0, (qint32) HistoryNode);
+ }
+
+ if (aIndex1.isValid())
+ return createIndex(aIndex1.row(), 0, (void*) getModelIndex(aIndex1));
+ return aIndex1;
+}
+
+bool PartSet_DocumentDataModel::hasChildren(const QModelIndex& theParent) const
+{
+ if (!theParent.isValid())
+ return true;
+ return rowCount(theParent) > 0;
+}
+
+QModelIndex* PartSet_DocumentDataModel::toSourceModelIndex(const QModelIndex& theProxy) const
+{
+ QModelIndex* aIndexPtr = static_cast<QModelIndex*>(theProxy.internalPointer());
+ return aIndexPtr;
+}
+
+QModelIndex* PartSet_DocumentDataModel::findModelIndex(const QModelIndex& theIndex) const
+{
+ QList<QModelIndex*>::const_iterator aIt;
+ for (aIt = myIndexes.constBegin(); aIt != myIndexes.constEnd(); ++aIt) {
+ QModelIndex* aIndex = (*aIt);
+ if ((*aIndex) == theIndex)
+ return aIndex;
+ }
+ return 0;
+}
+
+QModelIndex* PartSet_DocumentDataModel::getModelIndex(const QModelIndex& theIndex) const
+{
+ QModelIndex* aIndexPtr = findModelIndex(theIndex);
+ if (!aIndexPtr) {
+ aIndexPtr = new QModelIndex(theIndex);
+ PartSet_DocumentDataModel* that = (PartSet_DocumentDataModel*) this;
+ that->myIndexes.append(aIndexPtr);
+ }
+ return aIndexPtr;
+}
+
+void PartSet_DocumentDataModel::clearModelIndexes()
+{
+ foreach (QModelIndex* aIndex, myIndexes)
+ delete aIndex;
+ myIndexes.clear();
+}
+
+void PartSet_DocumentDataModel::clearSubModels()
+{
+ foreach (PartSet_PartModel* aPart, myPartModels)
+ delete aPart;
+ myPartModels.clear();
+}
+
+ObjectPtr PartSet_DocumentDataModel::object(const QModelIndex& theIndex) const
+{
+ if (theIndex.internalId() == PartsFolder)
+ return ObjectPtr();
+ DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+ if (theIndex.internalId() == HistoryNode) {
+ int aOffset = historyOffset();
+ return aRootDoc->object(ModelAPI_Feature::group(), theIndex.row() - aOffset);
+ }
+ if (theIndex.internalId() == PartResult) {
+ return aRootDoc->object(ModelAPI_ResultPart::group(), theIndex.row());
+ }
+ QModelIndex* aIndex = toSourceModelIndex(theIndex);
+ if (!isSubModel(aIndex->model()))
+ return ObjectPtr();
+
+ const PartSet_FeaturesModel* aModel = dynamic_cast<const PartSet_FeaturesModel*>(aIndex->model());
+ return aModel->object(*aIndex);
+}
+
+bool PartSet_DocumentDataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
+{
+ beginInsertRows(theParent, theRow, theRow + theCount - 1);
+ //endInsertRows();
+
+ // Update history
+ QModelIndex aRoot;
+ int aRow = rowCount(aRoot);
+ beginInsertRows(aRoot, aRow, aRow);
+ endInsertRows();
+
+ return true;
+}
+
+bool PartSet_DocumentDataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
+{
+ beginRemoveRows(theParent, theRow, theRow + theCount - 1);
+ endRemoveRows();
+ return true;
+}
+
+void PartSet_DocumentDataModel::removeSubModel(int theModelId)
+{
+ PartSet_PartModel* aModel = myPartModels.at(theModelId);
+ removeSubModel(aModel);
+}
+
+void PartSet_DocumentDataModel::removeSubModel(PartSet_PartModel* theModel)
+{
+ QIntList aToRemove;
+ for (int i = 0; i < myIndexes.size(); i++) {
+ if (myIndexes.at(i)->model() == theModel)
+ aToRemove.append(i);
+ }
+ int aId;
+ while (aToRemove.size() > 0) {
+ aId = aToRemove.last();
+ delete myIndexes.at(aId);
+ myIndexes.removeAt(aId);
+ aToRemove.removeLast();
+ }
+ delete theModel;
+ myPartModels.removeAll(theModel);
+}
+
+
+bool PartSet_DocumentDataModel::isSubModel(const QAbstractItemModel* theModel) const
+{
+ if (theModel == myModel)
+ return true;
+ return isPartSubModel(theModel);
+}
+
+bool PartSet_DocumentDataModel::isPartSubModel(const QAbstractItemModel* theModel) const
+{
+ return myPartModels.contains((PartSet_PartModel*) theModel);
+}
+
+QModelIndex PartSet_DocumentDataModel::partFolderNode(int theColumn) const
+{
+ int aPos = myModel->rowCount(QModelIndex());
+ return createIndex(aPos, theColumn, PartsFolder);
+}
+
+int PartSet_DocumentDataModel::historyOffset() const
+{
+ // Nb of rows of top model + Parts folder
+ return myModel->rowCount(QModelIndex()) + 1;
+}
+
+bool PartSet_DocumentDataModel::activatePart(const QModelIndex& theIndex)
+{
+ if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
+ return false;
+
+ if (theIndex.isValid() && (theIndex.internalId() == PartResult)) {
+ myActivePartIndex = theIndex;
+ myModel->setItemsColor(PASSIVE_COLOR);
+ if (myActivePartModel)
+ myActivePartModel->setItemsColor(PASSIVE_COLOR);
+
+ // Find activated part feature by its ID
+ ResultPartPtr aPartRes = activePart();
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aPartRes);
+ if (aFeature.get()) {
+ myActivePartModel = findPartModel(aFeature);
+ myActivePartModel->setItemsColor(ACTIVE_COLOR);
+ }
+ }
+ return true;
+}
+
+ResultPartPtr PartSet_DocumentDataModel::activePart() const
+{
+ if (myActivePartIndex.isValid()) {
+ DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+ ObjectPtr aObj = aRootDoc->object(ModelAPI_ResultPart::group(), myActivePartIndex.row());
+ return std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
+ }
+ return ResultPartPtr();
+}
+
+QModelIndex PartSet_DocumentDataModel::activePartTree() const
+{
+ if (myActivePartModel) {
+ return createIndex(myActivePartModel->position() + historyOffset(), 0, HistoryNode);
+ }
+ return QModelIndex();
+}
+
+void PartSet_DocumentDataModel::deactivatePart()
+{
+ if (myActivePartIndex.isValid()) {
+ if (myActivePartModel)
+ myActivePartModel->setItemsColor(PASSIVE_COLOR);
+ myActivePartModel = 0;
+ myActivePartIndex = QModelIndex();
+ myModel->setItemsColor(ACTIVE_COLOR);
+ }
+}
+
+Qt::ItemFlags PartSet_DocumentDataModel::flags(const QModelIndex& theIndex) const
+{
+ if ((theIndex.internalId() >= PartsFolder) && (theIndex.internalId() <= PartResult)) {
+ Qt::ItemFlags aFlags = Qt::ItemIsSelectable;
+ if (object(theIndex)) {
+ aFlags |= Qt::ItemIsEditable;
+ }
+ // Disable items which are below of last history row
+ // Do not disable second column
+ if (theIndex.internalId() == HistoryNode) {
+ if (theIndex.row() <= lastHistoryRow() || (theIndex.column() == 1))
+ aFlags |= Qt::ItemIsEnabled;
+ } else
+ aFlags |= Qt::ItemIsEnabled;
+ return aFlags;
+ } else {
+ QModelIndex* aIndex = toSourceModelIndex(theIndex);
+ const QAbstractItemModel* aModel = aIndex->model();
+ return aModel->flags(*aIndex);
+ }
+}
+
+QModelIndex PartSet_DocumentDataModel::partIndex(const ResultPartPtr& theObject) const
+{
+ DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+ int aNb = aRootDoc->size(ModelAPI_ResultPart::group());
+ for (int aId = 0; aId < aNb; aId++) {
+ if (theObject == aRootDoc->object(ModelAPI_ResultPart::group(), aId))
+ return createIndex(aId, 0, PartResult);
+ }
+ return QModelIndex();
+}
+
+QModelIndex PartSet_DocumentDataModel::objectIndex(const ObjectPtr theObject) const
+{
+ // Check that this feature belongs to root document
+ DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+ DocumentPtr aDoc = theObject->document();
+ if (aDoc == aRootDoc) {
+ // This feature belongs to histrory or top model
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
+ if (aFeature) {
+ int aId;
+ int aNb = aRootDoc->size(ModelAPI_Feature::group());
+ for (aId = 0; aId < aNb; aId++) {
+ if (theObject == aRootDoc->object(ModelAPI_Feature::group(), aId))
+ break;
+ }
+ if (aId < aNb)
+ return index(aId + historyOffset(), 0, QModelIndex());
+ } else {
+ QModelIndex aIndex = myModel->objectIndex(theObject);
+ return
+ aIndex.isValid() ?
+ createIndex(aIndex.row(), 0, (void*) getModelIndex(aIndex)) :
+ QModelIndex();
+ }
+ } else {
+ PartSet_PartModel* aPartModel = 0;
+ foreach(PartSet_PartModel* aModel, myPartModels) {
+ if (aModel->hasDocument(aDoc)) {
+ aPartModel = aModel;
+ break;
+ }
+ }
+ if (aPartModel) {
+ QModelIndex aIndex = aPartModel->objectIndex(theObject);
+ return aIndex.isValid() ?
+ createIndex(aIndex.row(), 0, (void*) getModelIndex(aIndex)) :
+ QModelIndex();
+ }
+ }
+ return QModelIndex();
+}
+
+
+void PartSet_DocumentDataModel::clear()
+{
+ clearModelIndexes();
+ clearSubModels();
+ //myActivePart = 0;
+ myActivePartIndex = QModelIndex();
+ myModel->setItemsColor(ACTIVE_COLOR);
+}
+
+int PartSet_DocumentDataModel::lastHistoryRow() const
+{
+ DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+ FeaturePtr aFeature = aRootDoc->currentFeature(true);
+ if (aFeature.get())
+ return historyOffset() + aRootDoc->index(aFeature);
+ else
+ return historyOffset() - 1;
+}
+
+void PartSet_DocumentDataModel::setLastHistoryItem(const QModelIndex& theIndex)
+{
+ SessionPtr aMgr = ModelAPI_Session::get();
+ DocumentPtr aRootDoc = aMgr->moduleDocument();
+ std::string aOpName = tr("History change").toStdString();
+ if (theIndex.internalId() == HistoryNode) {
+ ObjectPtr aObject = object(theIndex);
+ aMgr->startOperation(aOpName);
+ aRootDoc->setCurrentFeature(std::dynamic_pointer_cast<ModelAPI_Feature>(aObject), true);
+ aMgr->finishOperation();
+ } else {
+ aMgr->startOperation(aOpName);
+ aRootDoc->setCurrentFeature(FeaturePtr(), true);
+ aMgr->finishOperation();
+ }
+}
+
+QModelIndex PartSet_DocumentDataModel::lastHistoryItem() const
+{
+ return index(lastHistoryRow(), 1);
+}
+
+
+QIcon PartSet_DocumentDataModel::featureIcon(const FeaturePtr& theFeature)
+{
+ QIcon anIcon;
+
+ std::string aKind = theFeature->getKind();
+ QString aId(aKind.c_str());
+ if (!myIcons.contains(aId))
+ return anIcon;
+
+ QString anIconString = myIcons[aId];
+
+ ModelAPI_ExecState aState = theFeature->data()->execState();
+ switch(aState) {
+ case ModelAPI_StateDone:
+ case ModelAPI_StateNothing: {
+ anIcon = QIcon(anIconString);
+ }
+ break;
+ case ModelAPI_StateMustBeUpdated: {
+ anIcon = ModuleBase_Tools::lighter(anIconString);
+ }
+ break;
+ case ModelAPI_StateExecFailed: {
+ anIcon = ModuleBase_Tools::composite(":icons/exec_state_failed.png", anIconString);
+ }
+ break;
+ case ModelAPI_StateInvalidArgument: {
+ anIcon = ModuleBase_Tools::composite(":icons/exec_state_invalid_parameters.png",
+ anIconString);
+ }
+ break;
+ default: break;
+ }
+ return anIcon;
+}
+
+void PartSet_DocumentDataModel::onMouseDoubleClick(const QModelIndex& theIndex)
+{
+ if (theIndex.column() != 1)
+ return;
+ QTreeView* aTreeView = dynamic_cast<QTreeView*>(sender());
+ if ((theIndex.internalId() >= PartsFolder) && (theIndex.internalId() <= PartResult)) {
+ if (myActivePartModel)
+ // It means that the root document is not active
+ return;
+ QModelIndex aNewIndex;
+ if (theIndex.internalId() == HistoryNode)
+ aNewIndex = theIndex;
+ int aOldId = lastHistoryRow();
+ setLastHistoryItem(theIndex);
+ int aStartRow = std::min(aOldId, theIndex.row());
+ int aEndRow = std::max(aOldId, theIndex.row());
+ for (int i = aStartRow; i <= aEndRow; i++) {
+ aTreeView->update(createIndex(i, 0, HistoryNode));
+ aTreeView->update(createIndex(i, 1, HistoryNode));
+ }
+
+ } else {
+ QModelIndex* aIndex = toSourceModelIndex(theIndex);
+ const QAbstractItemModel* aModel = aIndex->model();
+ if (isPartSubModel(aModel)) {
+ PartSet_PartDataModel* aPartModel = (PartSet_PartDataModel*)aModel;
+ QModelIndex aOldItem = aPartModel->lastHistoryItem();
+ aPartModel->setLastHistoryItem(*aIndex);
+ QModelIndex aOldIndex = createIndex(aOldItem.row(), aOldItem.column(), (void*) getModelIndex(aOldItem));
+ int aStartRow = std::min(aOldItem.row(), aIndex->row());
+ int aEndRow = std::max(aOldItem.row(), aIndex->row());
+ for (int i = aStartRow; i <= aEndRow; i++) {
+ QModelIndex aInd1 = aPartModel->index(i, 0);
+ QModelIndex aInd2 = createIndex(i, 0, (void*) getModelIndex(aInd1));
+ aTreeView->update(aInd2);
+ aInd1 = aPartModel->index(i, 1);
+ aInd2 = createIndex(i, 1, (void*) getModelIndex(aInd1));
+ aTreeView->update(aInd2);
+ }
+ }
+ }
+}
+
+
+PartSet_PartModel* PartSet_DocumentDataModel::findPartModel(FeaturePtr thePart) const
+{
+ foreach (PartSet_PartModel* aModel, myPartModels) {
+ if (aModel->part() == thePart)
+ return aModel;
+ }
+ return 0;
+}
+
+PartSet_PartModel* PartSet_DocumentDataModel::findPartModel(int thePosition) const
+{
+ foreach (PartSet_PartModel* aModel, myPartModels) {
+ if (aModel->position() == thePosition)
+ return aModel;
+ }
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+#ifndef PartSet_DocumentDataModel_H
+#define PartSet_DocumentDataModel_H
+
+#include "PartSet.h"
+#include <ModuleBase_Definitions.h>
+#include <ModelAPI_ResultPart.h>
+#include <ModelAPI_Feature.h>
+#include <ModuleBase_IDocumentDataModel.h>
+
+#include <Events_Listener.h>
+#include <QList>
+#include <QMap>
+
+class ModelAPI_Document;
+class PartSet_PartModel;
+class PartSet_TopDataModel;
+
+/**\class PartSet_DocumentDataModel
+ * \ingroup GUI
+ * \brief This is a proxy data model for Object Browser (QTreeView).
+ * It contains several sub-models for generation of each sub-part of data tree.
+ */
+class PARTSET_EXPORT PartSet_DocumentDataModel : public ModuleBase_IDocumentDataModel, public Events_Listener
+{
+Q_OBJECT
+ public:
+ /// Constructor
+ /// \param theParent a parent object
+ PartSet_DocumentDataModel(QObject* theParent);
+ virtual ~PartSet_DocumentDataModel();
+
+ /// Event Listener method
+ /// \param theMessage an event message
+ virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
+ /// Returns the data stored under the given role for the item referred to by the index.
+ /// \param theIndex a model index
+ /// \param theRole a data role (see Qt::ItemDataRole)
+ virtual QVariant data(const QModelIndex& theIndex, int theRole) const;
+
+ /// Returns the data for the given role and section in the header with the specified orientation.
+ /// \param theSection a section
+ /// \param theOrient an orientation
+ /// \param theRole a data role (see Qt::ItemDataRole)
+ virtual QVariant headerData(int theSection, Qt::Orientation theOrient, int theRole =
+ Qt::DisplayRole) const;
+
+ /// Returns the number of rows under the given parent. When the parent is valid it means that
+ /// rowCount is returning the number of children of parent.
+ /// \param theParent a parent model index
+ virtual int rowCount(const QModelIndex& theParent = QModelIndex()) const;
+
+ /// Returns the number of columns for the children of the given parent.
+ /// It has a one column
+ /// \param theParent a parent model index
+ virtual int columnCount(const QModelIndex& theParent = QModelIndex()) const;
+
+ /// Returns the index of the item in the model specified by the given row, column and parent index.
+ /// \param theRow a row
+ /// \param theColumn a column
+ /// \param theParent a parent model index
+ virtual QModelIndex index(int theRow, int theColumn, const QModelIndex &theParent =
+ QModelIndex()) const;
+
+ /// Returns the parent of the model item with the given index.
+ /// If the item has no parent, an invalid QModelIndex is returned.
+ /// \param theIndex a model index
+ virtual QModelIndex parent(const QModelIndex& theIndex) const;
+
+ /// Returns true if parent has any children; otherwise returns false.
+ /// \param theParent a parent model index
+ virtual bool hasChildren(const QModelIndex& theParent = QModelIndex()) const;
+
+ /// Inserts count rows into the model before the given row.
+ /// Items in the new row will be children of the item represented by the parent model index.
+ /// \param theRow a start row
+ /// \param theCount a nember of rows to insert
+ /// \param theParent a parent model index
+ bool insertRows(int theRow, int theCount, const QModelIndex& theParent = QModelIndex());
+
+ /// Removes count rows starting with the given row under parent parent from the model.
+ /// \param theRow a start row
+ /// \param theCount a nember of rows to remove
+ /// \param theParent a parent model index
+ bool removeRows(int theRow, int theCount, const QModelIndex& theParent = QModelIndex());
+
+ /// Returns the item flags for the given index.
+ /// \param theIndex a model index
+ virtual Qt::ItemFlags flags(const QModelIndex& theIndex) const;
+
+ //! Returns an object by the given Model index.
+ //! Returns 0 if the given index is not index of an object
+ virtual ObjectPtr object(const QModelIndex& theIndex) const;
+
+ //! Returns index of the object
+ //! \param theObject object to find
+ virtual QModelIndex objectIndex(const ObjectPtr theObject) const;
+
+ //! Returns QModelIndex which corresponds to the given part
+ //! If the object is not found then index is not valid
+ //! \param thePart a part for analysis
+ QModelIndex partIndex(const ResultPartPtr& thePart) const;
+
+ //! Activates a part data model if the index is a Part node index.
+ //! Returns true if active part changed.
+ //! \param theIndex a model index
+ bool activatePart(const QModelIndex& theIndex);
+
+ //! Retrurns active part
+ ResultPartPtr activePart() const;
+
+ //! Retrurns QModelIndex of active part
+ QModelIndex activePartIndex() const
+ {
+ return myActivePartIndex;
+ }
+
+ //! Returns parent index of active part tree (index of Part feature)
+ QModelIndex activePartTree() const;
+
+ //! Deactivates a Part
+ void deactivatePart();
+
+ //! Rebuild data tree
+ virtual void rebuildDataTree();
+
+ //! Clear internal data
+ virtual void clear();
+
+ //! Set an Index which will be considered as a last history index
+ //! \param theIndex a last index for history
+ void setLastHistoryItem(const QModelIndex& theIndex);
+
+ //! Returns last history item
+ QModelIndex lastHistoryItem() const;
+
+ //! Returns icon name according to feature
+ static QIcon featureIcon(const FeaturePtr& theFeature);
+
+ public slots:
+ void onMouseDoubleClick(const QModelIndex& theIndex);
+
+ private:
+
+ enum
+ {
+ PartsFolder = -100,
+ HistoryNode,
+ PartResult
+ };
+
+ //! Converts QModelIndex of this model to QModelIndex of a one of sub-models.
+ QModelIndex* toSourceModelIndex(const QModelIndex& theProxy) const;
+
+ //! Finds a pointer on QModelIndex which is equal to the given one
+ QModelIndex* findModelIndex(const QModelIndex& theIndex) const;
+
+ //! Returns pointer on QModelIndex which is equal to the given one.
+ QModelIndex* getModelIndex(const QModelIndex& theIndex) const;
+
+ //! Deletes all saved pointers on QModelIndex objects.
+ void clearModelIndexes();
+
+ //! Deletes all saved pointers on QModelIndex objects.
+ void clearSubModels();
+
+ //! Removes sub-model on removing a part object. Also it removes QModelIndex-es which refer to this model
+ void removeSubModel(int theModelId);
+
+ //! Removes sub-model on removing a part object. Also it removes QModelIndex-es which refer to this model
+ void removeSubModel(PartSet_PartModel* theModel);
+
+ //! Returns true if the given model is a one of sub-models (of both types)
+ bool isSubModel(const QAbstractItemModel* theModel) const;
+
+ //! Returns true if the given model is a one of sub-models of Part type
+ bool isPartSubModel(const QAbstractItemModel* theModel) const;
+
+ //! Returns Parts Folder node
+ //! \param theColumn an Id of column
+ QModelIndex partFolderNode(int theColumn) const;
+
+ int lastHistoryRow() const;
+
+ int historyOffset() const;
+
+ PartSet_PartModel* findPartModel(FeaturePtr thePart) const;
+
+ PartSet_PartModel* findPartModel(int thePosition) const;
+
+ //! Data model of top part of data tree (not parts object)
+ PartSet_TopDataModel* myModel;
+
+ //! Data models for Parts data tree representation (one data model per a one part)
+ QList<PartSet_PartModel*> myPartModels;
+
+ //! Active part in part editing mode
+ PartSet_PartModel* myActivePartModel;
+
+ QModelIndex myActivePartIndex;
+
+ //! List of saved QModelIndexes created by sub-models
+ QList<QModelIndex*> myIndexes;
+
+ static QMap<QString, QString> myIcons;
+};
+
+#endif
#include "PartSet_SketcherMgr.h"
#include "PartSet_Tools.h"
+#include <PartSetPlugin_Part.h>
+
#include <GeomAPI_Pnt2d.h>
#include <GeomDataAPI_Point2D.h>
#include <Events_Loop.h>
#include <ModelAPI_Events.h>
#include <ModelAPI_Session.h>
+#include <ModelAPI_ResultPart.h>
+#include <ModelAPI_ResultParameter.h>
#include <QAction>
#include <QMenu>
void PartSet_MenuMgr::createActions()
{
- QAction* anAction;
+ QAction* aAction;
+
+ aAction = new QAction(tr("Auxiliary"), this);
+ aAction->setCheckable(true);
+ addAction("AUXILIARY_CMD", aAction);
+
+ aAction = new QAction(QIcon(":icons/activate.png"), tr("Activate"), this);
+ connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onActivatePart(bool)));
+ myActions["ACTIVATE_PART_CMD"] = aAction;
+
+ aAction = new QAction(QIcon(":icons/deactivate.png"), tr("Deactivate"), this);
+ connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onActivatePartSet(bool)));
+ myActions["DEACTIVATE_PART_CMD"] = aAction;
- anAction = new QAction(tr("Auxiliary"), this);
- anAction->setCheckable(true);
- addAction("AUXILIARY_CMD", anAction);
+ // Activate PartSet
+ aAction = new QAction(QIcon(":icons/activate.png"), tr("Activate"), this);
+ connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onActivatePartSet(bool)));
+ myActions["ACTIVATE_PARTSET_CMD"] = aAction;
+
+ aAction = new QAction(QIcon(":icons/edit.png"), tr("Edit..."), this);
+ connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onEdit(bool)));
+ myActions["EDIT_CMD"] = aAction;
}
aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
aFeature->data()->attribute(SketchPlugin_Point::COORD_ID()));
- else if (aFeature && aFeature->getKind() == SketchPlugin_Circle::ID())
- aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID()));
-
else if (anAttr->attr()) {
aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
}
FeaturePtr aObj = ModelAPI_Feature::feature(aPnt->object());
if (!theList.contains(aObj)) {
std::shared_ptr<GeomAPI_Pnt2d> aOrig = getPoint(theStartCoin, theAttr);
+ if (aOrig.get() == NULL)
+ return;
theList.append(aObj);
const std::set<AttributePtr>& aRefsList = aObj->data()->refsToMe();
std::set<AttributePtr>::const_iterator aIt;
FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
std::shared_ptr<GeomAPI_Pnt2d> aPnt = getPoint(aConstrFeature, theAttr);
- if (aOrig->isEqual(aPnt)) {
+ if (aPnt.get() && aOrig->isEqual(aPnt)) {
findCoincidences(aConstrFeature, theList, SketchPlugin_ConstraintCoincidence::ENTITY_A());
findCoincidences(aConstrFeature, theList, SketchPlugin_ConstraintCoincidence::ENTITY_B());
}
}
-bool PartSet_MenuMgr::addViewerItems(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const
+bool PartSet_MenuMgr::addViewerMenu(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const
{
ModuleBase_Operation* anOperation = myModule->workshop()->currentOperation();
if (!PartSet_SketcherMgr::isSketchOperation(anOperation) &&
std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
- std::shared_ptr<GeomAPI_Pnt2d> a2dPnt = getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A());
- if (aSelPnt->isEqual(a2dPnt)) {
+ std::shared_ptr<GeomAPI_Pnt2d> a2dPnt =
+ getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A());
+ if (a2dPnt.get() && aSelPnt->isEqual(a2dPnt)) {
aCoincident = aConstrFeature;
break;
- }
+ } else {
+ a2dPnt = getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B());
+ if (a2dPnt.get() && aSelPnt->isEqual(a2dPnt)) {
+ aCoincident = aConstrFeature;
+ break;
+ }
+ }
}
}
// If we have coincidence then add Detach menu
int aId = theAction->data().toInt();
FeaturePtr aLine = myCoinsideLines.at(aId);
std::shared_ptr<GeomAPI_Pnt2d> aOrig = getPoint(mySelectedFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A());
+ if (aOrig.get() == NULL)
+ aOrig = getPoint(mySelectedFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B());
+
gp_Pnt aOr = aOrig->impl<gp_Pnt>();
const std::set<AttributePtr>& aRefsList = aLine->data()->refsToMe();
FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
std::shared_ptr<GeomAPI_Pnt2d> aPnt = getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A());
+ if (aPnt.get() == NULL)
+ aPnt = getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B());
+ if (aPnt.get() == NULL)
+ return;
gp_Pnt aP = aPnt->impl<gp_Pnt>();
if (aOrig->isEqual(aPnt)) {
aToDelFeatures.append(aConstrFeature);
theValue = anObjects.size() && !isNotAuxiliaryFound;
return anEnabled;
}
+
+void PartSet_MenuMgr::onActivatePart(bool)
+{
+ QObjectPtrList aObjects = myModule->workshop()->selection()->selectedObjects();
+ if (aObjects.size() > 0) {
+ ObjectPtr aObj = aObjects.first();
+ ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
+ if (!aPart.get()) {
+ FeaturePtr aPartFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+ if (aPartFeature.get() && (aPartFeature->getKind() == PartSetPlugin_Part::ID())) {
+ aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aPartFeature->firstResult());
+ }
+ }
+ if (aPart.get())
+ aPart->activate();
+ }
+}
+
+void PartSet_MenuMgr::onActivatePartSet(bool)
+{
+ SessionPtr aMgr = ModelAPI_Session::get();
+ aMgr->setActiveDocument(aMgr->moduleDocument());
+}
+
+void PartSet_MenuMgr::onEdit(bool)
+{
+ QObjectPtrList aObjects = myModule->workshop()->selection()->selectedObjects();
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObjects.first());
+ if (aFeature == NULL) {
+ ResultParameterPtr aParam =
+ std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObjects.first());
+ if (aParam.get() != NULL) {
+ aFeature = ModelAPI_Feature::feature(aParam);
+ }
+ }
+ if (aFeature.get() != NULL)
+ myModule->editFeature(aFeature);
+}
/// \param theMenu a popup menu to be shown in the viewer
/// \param theStdActions a map of standard actions
/// \return true if items are added and there is no necessity to provide standard menu
- bool addViewerItems(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const;
+ bool addViewerMenu(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const;
public slots:
/// Processes the context menu action click
/// \param theAction an action of the selected item
void onLineDetach(QAction* theAction);
+ /// A slot called on Part activation command
+ void onActivatePart(bool);
+
+ /// A slot called on PartSet activation command
+ void onActivatePartSet(bool);
+
+ /// A slot called on edit of feature
+ void onEdit(bool);
+
private:
/// Returns true if the current operation is sketch entity create operation
/// \param theValue the current auxiliary value
// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
#include "PartSet_Module.h"
-#include <PartSet_WidgetSketchLabel.h>
-#include <PartSet_Validators.h>
-#include <PartSet_Tools.h>
-#include <PartSet_WidgetPoint2d.h>
-#include <PartSet_WidgetPoint2dDistance.h>
-#include <PartSet_WidgetShapeSelector.h>
-#include <PartSet_WidgetMultiSelector.h>
-#include <PartSet_WidgetEditor.h>
+#include "PartSet_WidgetSketchLabel.h"
+#include "PartSet_Validators.h"
+#include "PartSet_Tools.h"
+#include "PartSet_WidgetPoint2d.h"
+#include "PartSet_WidgetPoint2dDistance.h"
+#include "PartSet_WidgetShapeSelector.h"
+#include "PartSet_WidgetPoint2dAngle.h"
+#include "PartSet_WidgetMultiSelector.h"
+#include "PartSet_WidgetEditor.h"
+#include "PartSet_WidgetFileSelector.h"
#include "PartSet_SketcherMgr.h"
#include "PartSet_MenuMgr.h"
+#include <PartSetPlugin_Remove.h>
+#include <PartSetPlugin_Part.h>
+
#include <ModuleBase_Operation.h>
#include <ModuleBase_IViewer.h>
#include <ModuleBase_IViewWindow.h>
#include <ModuleBase_IPropertyPanel.h>
#include <ModuleBase_WidgetEditor.h>
#include <ModuleBase_FilterFactory.h>
-#include <GeomValidators_Edge.h>
-#include <GeomValidators_EdgeOrVertex.h>
+#include <ModuleBase_Tools.h>
+#include <GeomValidators_ShapeType.h>
+
#include <GeomValidators_Face.h>
#include <GeomValidators_ConstructionComposite.h>
#include <XGUI_ModuleConnector.h>
#include <XGUI_ContextMenuMgr.h>
#include <XGUI_Tools.h>
+#include <XGUI_ObjectsBrowser.h>
#include <SketchPlugin_Feature.h>
#include <SketchPlugin_Sketch.h>
#include <QApplication>
#include <QMessageBox>
#include <QMainWindow>
+#include <QLineEdit>
#include <GeomAlgoAPI_FaceBuilder.h>
#include <GeomDataAPI_Dir.h>
#include <QDebug>
#endif
+
+
/*!Create and return new instance of XGUI_Module*/
extern "C" PARTSET_EXPORT ModuleBase_IModule* createModule(ModuleBase_IWorkshop* theWshop)
{
}
PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop)
- : ModuleBase_IModule(theWshop),
+ : ModuleBase_IModule(theWshop),
myRestartingMode(RM_None), myVisualLayerId(0)
{
mySketchMgr = new PartSet_SketcherMgr(this);
+ myDataModel = new PartSet_DocumentDataModel(this);
XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWshop);
XGUI_Workshop* aWorkshop = aConnector->workshop();
SLOT(onViewTransformed(int)));
myMenuMgr = new PartSet_MenuMgr(this);
+
+ Events_Loop* aLoop = Events_Loop::loop();
+ aLoop->registerListener(this, Events_Loop::eventByName(EVENT_DOCUMENT_CHANGED));
}
PartSet_Module::~PartSet_Module()
aFactory->registerValidator("PartSet_DifferentObjects", new PartSet_DifferentObjectsValidator);
aFactory->registerValidator("PartSet_DifferentShapes", new ModelAPI_ShapeValidator);
- aFactory->registerValidator("GeomValidators_Edge", new GeomValidators_Edge);
- aFactory->registerValidator("GeomValidators_EdgeOrVertex",
- new GeomValidators_EdgeOrVertex);
+ aFactory->registerValidator("GeomValidators_ShapeType", new GeomValidators_ShapeType);
aFactory->registerValidator("GeomValidators_Face", new GeomValidators_Face);
aFactory->registerValidator("GeomValidators_ConstructionComposite",
}
-bool PartSet_Module::addViewerItems(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const
+bool PartSet_Module::addViewerMenu(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const
{
- return myMenuMgr->addViewerItems(theMenu, theStdActions);
+ return myMenuMgr->addViewerMenu(theMenu, theStdActions);
+}
+
+void PartSet_Module::activeSelectionModes(QIntList& theModes)
+{
+ theModes.clear();
+ if (mySketchMgr->activeSketch().get())
+ PartSet_SketcherMgr::sketchSelectionModes(theModes);
}
bool PartSet_Module::isMouseOverWindow()
aPointWgt->setSketch(mySketchMgr->activeSketch());
connect(aPointWgt, SIGNAL(vertexSelected()), this, SLOT(onVertexSelected()));
aWgt = aPointWgt;
- } if (theType == "point2ddistance") {
+ } else if (theType == "point2ddistance") {
PartSet_WidgetPoint2dDistance* aDistanceWgt = new PartSet_WidgetPoint2dDistance(theParent, theWidgetApi, theParentId);
aDistanceWgt->setWorkshop(aWorkshop);
aDistanceWgt->setSketch(mySketchMgr->activeSketch());
aWgt = aDistanceWgt;
- } if (theType == "sketch_shape_selector") {
+ } else if(theType == "point2dangle") {
+ PartSet_WidgetPoint2dAngle* anAngleWgt = new PartSet_WidgetPoint2dAngle(theParent, theWidgetApi, theParentId);
+ anAngleWgt->setWorkshop(aWorkshop);
+ anAngleWgt->setSketch(mySketchMgr->activeSketch());
+ aWgt = anAngleWgt;
+ } else if (theType == "sketch_shape_selector") {
PartSet_WidgetShapeSelector* aShapeSelectorWgt =
new PartSet_WidgetShapeSelector(theParent, workshop(), theWidgetApi, theParentId);
aShapeSelectorWgt->setSketcher(mySketchMgr->activeSketch());
aWgt = aShapeSelectorWgt;
- } if (theType == "sketch_multi_selector") {
+ } else if (theType == "sketch_multi_selector") {
PartSet_WidgetMultiSelector* aShapeSelectorWgt =
new PartSet_WidgetMultiSelector(theParent, workshop(), theWidgetApi, theParentId);
aShapeSelectorWgt->setSketcher(mySketchMgr->activeSketch());
aWgt = aShapeSelectorWgt;
- }
- if (theType == WDG_DOUBLEVALUE_EDITOR) {
+ } else if (theType == WDG_DOUBLEVALUE_EDITOR) {
aWgt = new PartSet_WidgetEditor(theParent, workshop(), theWidgetApi, theParentId);
+ } else if (theType == "export_file_selector") {
+ aWgt = new PartSet_WidgetFileSelector(theParent, workshop(), theWidgetApi, theParentId);
}
return aWgt;
}
bool PartSet_Module::deleteObjects()
{
+ SessionPtr aMgr = ModelAPI_Session::get();
// 1. check whether the delete should be processed in the module
ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
bool isSketchOp = PartSet_SketcherMgr::isSketchOperation(anOperation),
isNestedOp = PartSet_SketcherMgr::isNestedSketchOperation(anOperation);
- if (!isSketchOp && !isNestedOp)
- return false;
-
- // 2. find selected presentations
- // selected objects should be collected before the current operation abort because
- // the abort leads to selection lost on constraint objects. It can be corrected after #386 issue
- XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
- XGUI_Workshop* aWorkshop = aConnector->workshop();
- ModuleBase_ISelection* aSel = workshop()->selection();
- QObjectPtrList aSelectedObj = aSel->selectedPresentations();
- // if there are no selected objects in the viewer, that means that the selection in another
- // place cased this method. It is necessary to return the false value to understande in above
- // method that delete is not processed
- if (aSelectedObj.count() == 0)
- return false;
-
- // avoid delete of the objects, which are not belong to the current sketch
- // in order to do not delete results of other sketches
- QObjectPtrList aSketchObjects;
- QObjectPtrList::const_iterator anIt = aSelectedObj.begin(), aLast = aSelectedObj.end();
- for ( ; anIt != aLast; anIt++) {
- ObjectPtr anObject = *anIt;
- if (mySketchMgr->isObjectOfSketch(anObject))
- aSketchObjects.append(anObject);
- }
- // if the selection contains only local selected presentations from other sketches,
- // the Delete operation should not be done at all
- if (aSketchObjects.size() == 0)
- return true;
-
- // the active nested sketch operation should be aborted unconditionally
- if (isNestedOp)
- anOperation->abort();
-
- // 3. start operation
- QString aDescription = aWorkshop->contextMenuMgr()->action("DELETE_CMD")->text();
- SessionPtr aMgr = ModelAPI_Session::get();
- aMgr->startOperation(aDescription.toStdString());
-
- // 4. delete features
- // sketch feature should be skipped, only sub-features can be removed
- // when sketch operation is active
- std::set<FeaturePtr> anIgnoredFeatures;
- anIgnoredFeatures.insert(mySketchMgr->activeSketch());
- aWorkshop->deleteFeatures(aSketchObjects, anIgnoredFeatures);
+ if (isSketchOp || isNestedOp) {
+ // 2. find selected presentations
+ // selected objects should be collected before the current operation abort because
+ // the abort leads to selection lost on constraint objects. It can be corrected after #386 issue
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
+ XGUI_Workshop* aWorkshop = aConnector->workshop();
+ ModuleBase_ISelection* aSel = workshop()->selection();
+ QObjectPtrList aSelectedObj = aSel->selectedPresentations();
+ // if there are no selected objects in the viewer, that means that the selection in another
+ // place cased this method. It is necessary to return the false value to understande in above
+ // method that delete is not processed
+ if (aSelectedObj.count() == 0)
+ return false;
+
+ // avoid delete of the objects, which are not belong to the current sketch
+ // in order to do not delete results of other sketches
+ QObjectPtrList aSketchObjects;
+ QObjectPtrList::const_iterator anIt = aSelectedObj.begin(), aLast = aSelectedObj.end();
+ for ( ; anIt != aLast; anIt++) {
+ ObjectPtr anObject = *anIt;
+ if (mySketchMgr->isObjectOfSketch(anObject))
+ aSketchObjects.append(anObject);
+ }
+ // if the selection contains only local selected presentations from other sketches,
+ // the Delete operation should not be done at all
+ if (aSketchObjects.size() == 0)
+ return true;
+
+ // the active nested sketch operation should be aborted unconditionally
+ if (isNestedOp)
+ anOperation->abort();
+
+ // 3. start operation
+ QString aDescription = aWorkshop->contextMenuMgr()->action("DELETE_CMD")->text();
+ aMgr->startOperation(aDescription.toStdString());
+
+ // 4. delete features
+ // sketch feature should be skipped, only sub-features can be removed
+ // when sketch operation is active
+ std::set<FeaturePtr> anIgnoredFeatures;
+ anIgnoredFeatures.insert(mySketchMgr->activeSketch());
+ aWorkshop->deleteFeatures(aSketchObjects, anIgnoredFeatures);
- // 5. stop operation
- aWorkshop->displayer()->updateViewer();
- aMgr->finishOperation();
-
+ // 5. stop operation
+ aWorkshop->displayer()->updateViewer();
+ aMgr->finishOperation();
+ } else {
+ // Delete part with help of PartSet plugin
+ // TODO: the deleted objects has to be processed by multiselection
+ QObjectPtrList aObjects = myWorkshop->selection()->selectedObjects();
+ if (aObjects.size() == 1) {
+ ObjectPtr aObj = aObjects.first();
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+ if (aFeature.get() && (aFeature->getKind() == PartSetPlugin_Part::ID())) {
+ std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
+ aMgr->startOperation(PartSetPlugin_Remove::ID());
+ FeaturePtr aFeature = aDoc->addFeature(PartSetPlugin_Remove::ID());
+ aFeature->execute();
+ aMgr->finishOperation();
+ } else
+ return false;
+ } else
+ return false;
+ }
return true;
}
return;
ModuleBase_IViewer* aViewer = myWorkshop->viewer();
- Handle(V3d_View) aView = aViewer->activeView();
+ //Handle(V3d_View) aView = aViewer->activeView();
XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myWorkshop);
XGUI_Workshop* aWorkshop = aConnector->workshop();
XGUI_Displayer* aDisplayer = aWorkshop->displayer();
- Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
-
- double aLen = aView->Convert(15);
+ Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
+
+ Handle(V3d_Viewer) aV3dViewer = aContext->CurrentViewer();
+ Handle(V3d_View) aView;
+ double aScale = 0;
+ for (aV3dViewer->InitDefinedViews();
+ aV3dViewer->MoreDefinedViews();
+ aV3dViewer->NextDefinedViews()) {
+ Handle(V3d_View) aV = aV3dViewer->DefinedView();
+ double aS = aV->Scale();
+ if (aS > aScale) {
+ aScale = aS;
+ aView = aV;
+ }
+ }
+ if (aView.IsNull())
+ return;
+ double aLen = aView->Convert(20);
SketcherPrs_Tools::setArrowSize(aLen);
bool isModified = false;
if (isModified)
aDisplayer->updateViewer();
}
+
+
+void PartSet_Module::customizeObjectBrowser(QWidget* theObjectBrowser)
+{
+ XGUI_ObjectsBrowser* aOB = dynamic_cast<XGUI_ObjectsBrowser*>(theObjectBrowser);
+ if (aOB) {
+ QLineEdit* aLabel = aOB->activeDocLabel();
+ QPalette aPalet = aLabel->palette();
+ aPalet.setColor(QPalette::Text, QColor(0, 72, 140));
+ aLabel->setPalette(aPalet);
+ connect(aOB->treeView(), SIGNAL(doubleClicked(const QModelIndex&)),
+ myDataModel, SLOT(onMouseDoubleClick(const QModelIndex&)));
+ }
+}
+
+
+void PartSet_Module::addObjectBrowserMenu(QMenu* theMenu) const
+{
+ QObjectPtrList aObjects = myWorkshop->selection()->selectedObjects();
+ int aSelected = aObjects.size();
+ SessionPtr aMgr = ModelAPI_Session::get();
+ if (aSelected == 1) {
+ bool hasResult = false;
+ bool hasFeature = false;
+ bool hasParameter = false;
+ ModuleBase_Tools::checkObjects(aObjects, hasResult, hasFeature, hasParameter);
+
+ ObjectPtr aObject = aObjects.first();
+ if (aObject) {
+ ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);
+ FeaturePtr aPartFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
+ bool isPart = aPart.get() ||
+ (aPartFeature.get() && (aPartFeature->getKind() == PartSetPlugin_Part::ID()));
+ if (isPart) {
+ DocumentPtr aPartDoc;
+ if (!aPart.get()) {
+ aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aPartFeature->firstResult());
+ }
+ if (aPart.get()) // this may be null is Part feature is disabled
+ aPartDoc = aPart->partDoc();
+ if (aMgr->activeDocument() == aPartDoc)
+ theMenu->addAction(myMenuMgr->action("DEACTIVATE_PART_CMD"));
+ else
+ theMenu->addAction(myMenuMgr->action("ACTIVATE_PART_CMD"));
+ } else if (aObject->document() == aMgr->activeDocument()) {
+ if (hasParameter || hasFeature)
+ theMenu->addAction(myMenuMgr->action("EDIT_CMD"));
+ }
+ } else { // If feature is 0 the it means that selected root object (document)
+ if (aMgr->activeDocument() != aMgr->moduleDocument())
+ theMenu->addAction(myMenuMgr->action("ACTIVATE_PARTSET_CMD"));
+ }
+ } else if (aSelected == 0) {
+ // if there is no selection then it means that upper label is selected
+ QModelIndexList aIndexes = myWorkshop->selection()->selectedIndexes();
+ if (aIndexes.size() == 0) // it means that selection happens in top label outside of tree view
+ if (aMgr->activeDocument() != aMgr->moduleDocument())
+ theMenu->addAction(myMenuMgr->action("ACTIVATE_PARTSET_CMD"));
+ }
+}
+
+void PartSet_Module::processEvent(const std::shared_ptr<Events_Message>& theMessage)
+{
+ if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) {
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myWorkshop);
+ XGUI_Workshop* aWorkshop = aConnector->workshop();
+ XGUI_DataTree* aTreeView = aWorkshop->objectBrowser()->treeView();
+ QLineEdit* aLabel = aWorkshop->objectBrowser()->activeDocLabel();
+ QPalette aPalet = aLabel->palette();
+
+ SessionPtr aMgr = ModelAPI_Session::get();
+ DocumentPtr aActiveDoc = aMgr->activeDocument();
+ DocumentPtr aDoc = aMgr->moduleDocument();
+ QModelIndex aOldIndex = myDataModel->activePartTree();
+ if (aActiveDoc == aDoc) {
+ if (aOldIndex.isValid())
+ aTreeView->setExpanded(aOldIndex, false);
+ myDataModel->deactivatePart();
+ aPalet.setColor(QPalette::Text, QColor(0, 72, 140));
+ } else {
+ std::string aGrpName = ModelAPI_ResultPart::group();
+ for (int i = 0; i < aDoc->size(aGrpName); i++) {
+ ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aDoc->object(aGrpName, i));
+ if (aPart->partDoc() == aActiveDoc) {
+ QModelIndex aIndex = myDataModel->partIndex(aPart);
+ if (myDataModel->activatePart(aIndex)) {
+ aTreeView->setExpanded(aOldIndex, false);
+ aTreeView->setExpanded(myDataModel->activePartTree(), true);
+ aPalet.setColor(QPalette::Text, Qt::black);
+ }
+ break;
+ }
+ }
+ }
+ aLabel->setPalette(aPalet);
+ aWorkshop->updateCommandStatus();
+
+ // Update displayed objects in order to update active color
+ XGUI_Displayer* aDisplayer = aWorkshop->displayer();
+ QObjectPtrList aObjects = aDisplayer->displayedObjects();
+ foreach(ObjectPtr aObj, aObjects)
+ aDisplayer->redisplay(aObj, false);
+ aDisplayer->updateViewer();
+ }
+}
#include "PartSet.h"
#include "PartSet_Filters.h"
+#include "PartSet_DocumentDataModel.h"
#include <ModuleBase_IModule.h>
#include <ModuleBase_Definitions.h>
#include <ModelAPI_Attribute.h>
#include <ModelAPI_CompositeFeature.h>
+#include <Events_Listener.h>
+
//#include <StdSelect_FaceFilter.hxx>
#include <TopoDS_Shape.hxx>
* \ingroup Modules
* Implementation of Partset module
*/
-class PARTSET_EXPORT PartSet_Module : public ModuleBase_IModule
+class PARTSET_EXPORT PartSet_Module : public ModuleBase_IModule, public Events_Listener
{
Q_OBJECT
};
public:
+
/// Constructor
/// \param theWshop a pointer to a workshop
PartSet_Module(ModuleBase_IWorkshop* theWshop);
/// \param theObject a model object
virtual bool canDisplayObject(const ObjectPtr& theObject) const;
+ /// Add menu atems for object browser into the given menu
+ /// \param theMenu a popup menu to be shown in the object browser
+ virtual void addObjectBrowserMenu(QMenu* theMenu) const;
+
/// Add menu atems for viewer into the given menu
/// \param theMenu a popup menu to be shown in the viewer
/// \param theStdActions a map of standard actions
/// \return true if items are added and there is no necessity to provide standard menu
- virtual bool addViewerItems(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const;
+ virtual bool addViewerMenu(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const;
+
+ /// Returns a list of modes, where the AIS objects should be activated
+ /// \param theModes a list of modes
+ virtual void activeSelectionModes(QIntList& theModes);
/// Returns whether the mouse enter the viewer's window
/// \return true if items are added and there is no necessity to provide standard menu
PartSet_SketcherMgr* sketchMgr() const { return mySketchMgr; }
+ /// Returns data model object for representation of data tree in Object browser
+ virtual ModuleBase_IDocumentDataModel* dataModel() const { return myDataModel; }
+
+ /// Event Listener method
+ /// \param theMessage an event message
+ virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
+ /// This method is called on object browser creation for customisation of module specific features
+ /// \param theObjectBrowser a pinter on Object Browser widget
+ virtual void customizeObjectBrowser(QWidget* theObjectBrowser);
+
public slots:
/// SLOT, that is called by no more widget signal emitted by property panel
/// Set a specific flag to restart the sketcher operation
/// \param theOperation the operation
virtual void sendOperation(ModuleBase_Operation* theOperation);
+ //! Activates or deactivates a part
+ //! If PartPtr is Null pointer then PartSet will be activated
+ //void activatePart(std::shared_ptr<ModelAPI_ResultPart> theFeature);
+
private slots:
/// Processing of vertex selected
void onVertexSelected();
PartSet_MenuMgr* myMenuMgr;
int myVisualLayerId;
+
+ PartSet_DocumentDataModel* myDataModel;
};
#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+#include "PartSet_PartDataModel.h"
+#include "PartSet_Module.h"
+#include "PartSet_DocumentDataModel.h"
+
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Result.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_AttributeDocRef.h>
+#include <ModelAPI_Object.h>
+#include <ModelAPI_ResultPart.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_ResultParameter.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultGroup.h>
+#include <ModelAPI_AttributeDouble.h>
+
+#include <QIcon>
+#include <QBrush>
+
+
+PartSet_TopDataModel::PartSet_TopDataModel(QObject* theParent)
+ : PartSet_FeaturesModel(theParent)
+{
+}
+
+PartSet_TopDataModel::~PartSet_TopDataModel()
+{
+}
+
+QVariant PartSet_TopDataModel::data(const QModelIndex& theIndex, int theRole) const
+{
+ if (theIndex.column() == 1)
+ return QVariant();
+
+ switch (theRole) {
+ case Qt::DisplayRole:
+ // return a name
+ switch (theIndex.internalId()) {
+ case ParamsFolder:
+ return tr("Parameters") + QString(" (%1)").arg(rowCount(theIndex));
+ case ParamObject: {
+ DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+ ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultParameter::group(), theIndex.row());
+ if (aObject) {
+ ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObject);
+ AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
+ QString aVal = QString::number(aValueAttribute->value());
+ QString aTitle = QString(aObject->data()->name().c_str());
+ return aTitle + " = " + aVal;
+ }
+ }
+ break;
+ case ConstructFolder:
+ return tr("Constructions") + QString(" (%1)").arg(rowCount(theIndex));
+ case ConstructObject: {
+ DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+ ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultConstruction::group(),
+ theIndex.row());
+ if (aObject)
+ return aObject->data()->name().c_str();
+ }
+ break;
+ //case GroupsFolder:
+ // return tr("Groups") + QString(" (%1)").arg(rowCount(theIndex));
+ //case GroupObject: {
+ // DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+ // ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultGroup::group(),
+ // theIndex.row());
+ // if (aObject)
+ // return aObject->data()->name().c_str();
+ //}
+ // break;
+ }
+ break;
+
+ case Qt::DecorationRole:
+ {
+ // return an Icon
+ switch (theIndex.internalId()) {
+ case ParamsFolder:
+ return QIcon(":pictures/params_folder.png");
+ case ConstructFolder:
+ return QIcon(":pictures/constr_folder.png");
+ case ConstructObject:
+ return QIcon(":pictures/constr_object.png");
+ //case GroupsFolder:
+ // return QIcon(":pictures/constr_folder.png");
+ }
+ }
+ break;
+
+ case Qt::ToolTipRole:
+ // return Tooltip
+ break;
+ case Qt::ForegroundRole:
+ return QBrush(myItemsColor);
+ break;
+ }
+ return QVariant();
+}
+
+QVariant PartSet_TopDataModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ return QVariant();
+}
+
+int PartSet_TopDataModel::rowCount(const QModelIndex& theParent) const
+{
+ if (!theParent.isValid())
+ return 2; // In case of groups using it has to be +1
+
+ DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+ if (theParent.internalId() == ParamsFolder)
+ return aRootDoc->size(ModelAPI_ResultParameter::group());
+
+ if (theParent.internalId() == ConstructFolder)
+ return aRootDoc->size(ModelAPI_ResultConstruction::group());
+
+ //if (theParent.internalId() == GroupsFolder)
+ // return aRootDoc->size(ModelAPI_ResultGroup::group());
+
+ return 0;
+}
+
+int PartSet_TopDataModel::columnCount(const QModelIndex &parent) const
+{
+ return 1;
+}
+
+QModelIndex PartSet_TopDataModel::index(int theRow, int theColumn, const QModelIndex& theParent) const
+{
+ if (!theParent.isValid()) {
+ switch (theRow) {
+ case 0:
+ return createIndex(theRow, theColumn, (qint32) ParamsFolder);
+ case 1:
+ return createIndex(theRow, theColumn, (qint32) ConstructFolder);
+ //case 2:
+ // return createIndex(theRow, theColumn, (qint32) GroupsFolder);
+ }
+ } else {
+ if (theParent.internalId() == ParamsFolder)
+ return createIndex(theRow, theColumn, (qint32) ParamObject);
+
+ if (theParent.internalId() == ConstructFolder)
+ return createIndex(theRow, theColumn, (qint32) ConstructObject);
+
+ //if (theParent.internalId() == GroupsFolder)
+ // return createIndex(theRow, theColumn, (qint32) GroupObject);
+ }
+ return QModelIndex();
+}
+
+QModelIndex PartSet_TopDataModel::parent(const QModelIndex& theIndex) const
+{
+ int aId = (int) theIndex.internalId();
+ switch (aId) {
+ case ParamsFolder:
+ case ConstructFolder:
+ //case GroupsFolder:
+ return QModelIndex();
+ case ParamObject:
+ return createIndex(0, 0, (qint32) ParamsFolder);
+ case ConstructObject:
+ return createIndex(1, 0, (qint32) ConstructFolder);
+ //case GroupObject:
+ // return createIndex(2, 0, (qint32) GroupsFolder);
+ }
+ return QModelIndex();
+}
+
+bool PartSet_TopDataModel::hasChildren(const QModelIndex& theParent) const
+{
+ return rowCount(theParent) > 0;
+}
+
+ObjectPtr PartSet_TopDataModel::object(const QModelIndex& theIndex) const
+{
+ switch (theIndex.internalId()) {
+ case ParamsFolder:
+ case ConstructFolder:
+ return ObjectPtr();
+ case ParamObject: {
+ DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+ return aRootDoc->object(ModelAPI_ResultParameter::group(), theIndex.row());
+ }
+ case ConstructObject: {
+ DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+ return aRootDoc->object(ModelAPI_ResultConstruction::group(), theIndex.row());
+ }
+ //case GroupObject: {
+ // DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+ // return aRootDoc->object(ModelAPI_ResultGroup::group(), theIndex.row());
+ //}
+ }
+ return ObjectPtr();
+}
+
+QModelIndex PartSet_TopDataModel::findParent(const ObjectPtr& theObject) const
+{
+ return findGroup(theObject->groupName().c_str());
+}
+
+QModelIndex PartSet_TopDataModel::findGroup(const std::string& theGroup) const
+{
+ if (theGroup == ModelAPI_ResultParameter::group())
+ return createIndex(0, 0, (qint32) ParamsFolder);
+ if (theGroup == ModelAPI_ResultConstruction::group())
+ return createIndex(1, 0, (qint32) ConstructFolder);
+ //if (theGroup == ModelAPI_ResultGroup::group())
+ // return createIndex(2, 0, (qint32) ConstructFolder);
+ return QModelIndex();
+}
+
+QModelIndex PartSet_TopDataModel::objectIndex(const ObjectPtr& theObject) const
+{
+ QModelIndex aIndex;
+ if (theObject) {
+ DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+ std::string aGroup = theObject->groupName();
+ int aNb = aRootDoc->size(aGroup);
+ int aRow = -1;
+ for (int i = 0; i < aNb; i++) {
+ if (aRootDoc->object(aGroup, i) == theObject) {
+ aRow = i;
+ break;
+ }
+ }
+ if (aRow != -1) {
+ if (aGroup == ModelAPI_ResultParameter::group())
+ return createIndex(aRow, 0, (qint32) ParamObject);
+ if (aGroup == ModelAPI_ResultConstruction::group())
+ return createIndex(aRow, 0, (qint32) ConstructObject);
+ //if (aGroup == ModelAPI_ResultGroup::group())
+ // return createIndex(aRow, 0, (qint32) GroupObject);
+ }
+ }
+ return aIndex;
+}
+
+//******************************************************************
+//******************************************************************
+//******************************************************************
+PartSet_PartDataModel::PartSet_PartDataModel(QObject* theParent)
+ : PartSet_PartModel(theParent)
+{
+}
+
+PartSet_PartDataModel::~PartSet_PartDataModel()
+{
+}
+
+QVariant PartSet_PartDataModel::data(const QModelIndex& theIndex, int theRole) const
+{
+ DocumentPtr aPartDoc = partDocument();
+ if (theIndex.column() == 1) {
+ DocumentPtr aActiveDoc = ModelAPI_Session::get()->activeDocument();
+ QModelIndex aParent = theIndex.parent();
+ if (aActiveDoc == aPartDoc) {
+ if (!aParent.isValid()) {
+ switch (theRole) {
+ case Qt::DecorationRole:
+ if (theIndex.row() == lastHistoryRow())
+ return QIcon(":pictures/arrow.png");
+ }
+ }
+ }
+ return QVariant();
+ }
+
+ switch (theRole) {
+ case Qt::DisplayRole:
+ // return a name
+ switch (theIndex.internalId()) {
+ //case MyRoot: {
+ // DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+ // ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), myId);
+ // if (aObject)
+ // return std::dynamic_pointer_cast<ModelAPI_Object>(aObject)->data()->name().c_str();
+ //}
+ case ParamsFolder:
+ return tr("Parameters") + QString(" (%1)").arg(rowCount(theIndex));
+ case ConstructFolder:
+ return tr("Constructions") + QString(" (%1)").arg(rowCount(theIndex));
+ case BodiesFolder:
+ return tr("Bodies") + QString(" (%1)").arg(rowCount(theIndex));
+ case GroupsFolder:
+ return tr("Groups") + QString(" (%1)").arg(rowCount(theIndex));
+ case ParamObject: {
+ ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultParameter::group(), theIndex.row());
+ if (aObject) {
+ ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObject);
+ AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
+ QString aVal = QString::number(aValueAttribute->value());
+ QString aTitle = QString(aObject->data()->name().c_str());
+ return aTitle + " = " + aVal;
+ }
+ }
+ break;
+ case ConstructObject: {
+ ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultConstruction::group(), theIndex.row());
+ if (aObject)
+ return std::dynamic_pointer_cast<ModelAPI_Object>(aObject)->data()->name().c_str();
+ }
+ break;
+ case BodiesObject: {
+ ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultBody::group(), theIndex.row());
+ if (aObject)
+ return aObject->data()->name().c_str();
+ }
+ break;
+ case GroupObject: {
+ ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultGroup::group(), theIndex.row());
+ if (aObject)
+ return aObject->data()->name().c_str();
+ }
+ case HistoryObject: {
+ ObjectPtr aObject = aPartDoc->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber());
+ if (aObject)
+ return aObject->data()->name().c_str();
+ }
+ }
+ break;
+ case Qt::DecorationRole:
+ // return an Icon
+ switch (theIndex.internalId()) {
+ //case MyRoot:
+ // return QIcon(":pictures/part_ico.png");
+ case ParamsFolder:
+ return QIcon(":pictures/params_folder.png");
+ case ConstructFolder:
+ case BodiesFolder:
+ return QIcon(":pictures/constr_folder.png");
+ case GroupsFolder:
+ return QIcon(":pictures/constr_folder.png");
+ case ConstructObject:
+ case GroupObject:
+ case BodiesObject: {
+ std::string aGroup = theIndex.internalId() == ConstructObject ?
+ ModelAPI_ResultConstruction::group() : ModelAPI_ResultBody::group();
+ ObjectPtr anObject = aPartDoc->object(aGroup, theIndex.row());
+ 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 = aPartDoc->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber());
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
+ if (aFeature)
+ return PartSet_DocumentDataModel::featureIcon(aFeature);
+ }
+ }
+ break;
+ case Qt::ToolTipRole:
+ // return Tooltip
+ break;
+ case Qt::ForegroundRole:
+ if (theIndex.internalId() == HistoryObject) {
+ if (theIndex.row() > lastHistoryRow())
+ return QBrush(Qt::lightGray);
+ }
+ return QBrush(myItemsColor);
+ }
+ return QVariant();
+}
+
+QVariant PartSet_PartDataModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ return QVariant();
+}
+
+int PartSet_PartDataModel::rowCount(const QModelIndex& parent) const
+{
+ if (!parent.isValid()) {
+ DocumentPtr aDoc = partDocument();
+ if (aDoc.get()) {
+ return getRowsNumber() + aDoc->size(ModelAPI_Feature::group());
+ } else
+ return 0;
+ }
+ switch (parent.internalId()) {
+ case ParamsFolder:
+ return partDocument()->size(ModelAPI_ResultParameter::group());
+ case ConstructFolder:
+ return partDocument()->size(ModelAPI_ResultConstruction::group());
+ case BodiesFolder:
+ return partDocument()->size(ModelAPI_ResultBody::group());
+ case GroupsFolder:
+ return partDocument()->size(ModelAPI_ResultGroup::group());
+ }
+ return 0;
+}
+
+int PartSet_PartDataModel::columnCount(const QModelIndex &parent) const
+{
+ return 2;
+}
+
+QModelIndex PartSet_PartDataModel::index(int theRow, int theColumn, const QModelIndex &theParent) const
+{
+ if (!theParent.isValid()) {
+ switch (theRow) {
+ case 0:
+ return createIndex(theRow, theColumn, (qint32) ParamsFolder);
+ case 1:
+ return createIndex(theRow, theColumn, (qint32) ConstructFolder);
+ case 2:
+ return createIndex(theRow, theColumn, (qint32) BodiesFolder);
+ case 3:
+ {
+ int aSize = partDocument()->size(ModelAPI_ResultGroup::group());
+ if (aSize > 0)
+ return createIndex(theRow, theColumn, (qint32) GroupsFolder);
+ else
+ return createIndex(theRow, theColumn, (qint32) HistoryObject);
+ }
+ default:
+ return createIndex(theRow, theColumn, (qint32) HistoryObject);
+ }
+ } else {
+ int aId = (int) theParent.internalId();
+ switch (aId) {
+ case ParamsFolder:
+ return createIndex(theRow, theColumn, (qint32) ParamObject);
+ case ConstructFolder:
+ return createIndex(theRow, theColumn, (qint32) ConstructObject);
+ case BodiesFolder:
+ return createIndex(theRow, theColumn, (qint32) BodiesObject);
+ case GroupsFolder:
+ return createIndex(theRow, theColumn, (qint32) GroupObject);
+ }
+ }
+ return QModelIndex();
+}
+
+QModelIndex PartSet_PartDataModel::parent(const QModelIndex& theIndex) const
+{
+ switch (theIndex.internalId()) {
+ case ParamsFolder:
+ case ConstructFolder:
+ case BodiesFolder:
+ case GroupsFolder:
+ case HistoryObject:
+ return QModelIndex();
+
+ case ParamObject:
+ return createIndex(0, 0, (qint32) ParamsFolder);
+ case ConstructObject:
+ return createIndex(1, 0, (qint32) ConstructFolder);
+ case BodiesObject:
+ return createIndex(2, 0, (qint32) BodiesFolder);
+ case GroupObject:
+ return createIndex(3, 0, (qint32) GroupsFolder);
+ }
+ return QModelIndex();
+}
+
+bool PartSet_PartDataModel::hasChildren(const QModelIndex& theParent) const
+{
+ return rowCount(theParent) > 0;
+}
+
+DocumentPtr PartSet_PartDataModel::partDocument() const
+{
+ ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(myPart->firstResult());
+ if (aPart.get()) // this may be null is Part feature is disabled
+ return aPart->partDoc();
+ return DocumentPtr();
+}
+
+ObjectPtr PartSet_PartDataModel::object(const QModelIndex& theIndex) const
+{
+ switch (theIndex.internalId()) {
+ case ParamsFolder:
+ case ConstructFolder:
+ case BodiesFolder:
+ case GroupsFolder:
+ return ObjectPtr();
+
+ case ParamObject:
+ return partDocument()->object(ModelAPI_ResultParameter::group(), theIndex.row());
+ case ConstructObject:
+ return partDocument()->object(ModelAPI_ResultConstruction::group(), theIndex.row());
+ case BodiesObject:
+ return partDocument()->object(ModelAPI_ResultBody::group(), theIndex.row());
+ case GroupObject:
+ return partDocument()->object(ModelAPI_ResultGroup::group(), theIndex.row());
+ case HistoryObject:
+ return partDocument()->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber());
+ }
+ return ObjectPtr();
+}
+
+bool PartSet_PartDataModel::hasDocument(const DocumentPtr& theDoc) const
+{
+ return (partDocument() == theDoc);
+}
+
+QModelIndex PartSet_PartDataModel::findParent(const ObjectPtr& theObject) const
+{
+ return findGroup(theObject->groupName().c_str());
+}
+
+QModelIndex PartSet_PartDataModel::findGroup(const std::string& theGroup) const
+{
+ if (theGroup == ModelAPI_ResultParameter::group())
+ return createIndex(0, 0, (qint32) ParamsFolder);
+ if (theGroup == ModelAPI_ResultConstruction::group())
+ return createIndex(1, 0, (qint32) ConstructFolder);
+ if (theGroup == ModelAPI_ResultBody::group())
+ return createIndex(2, 0, (qint32) BodiesFolder);
+ if (theGroup == ModelAPI_ResultGroup::group())
+ return createIndex(3, 0, (qint32) GroupsFolder);
+ return QModelIndex();
+}
+
+QModelIndex PartSet_PartDataModel::objectIndex(const ObjectPtr& theObject) const
+{
+ QModelIndex aIndex;
+ if (theObject) {
+ if (part() == theObject)
+ return aIndex;
+
+ std::string aGroup = theObject->groupName();
+ DocumentPtr aDoc = theObject->document();
+ int aNb = aDoc->size(aGroup);
+ int aRow = -1;
+ for (int i = 0; i < aNb; i++) {
+ if (aDoc->object(aGroup, i) == theObject) {
+ aRow = i;
+ break;
+ }
+ }
+ if (aRow == -1)
+ return aIndex;
+ if (aGroup == ModelAPI_ResultParameter::group())
+ return createIndex(aRow, 0, (qint32) ParamObject);
+ else if (aGroup == ModelAPI_ResultConstruction::group())
+ return createIndex(aRow, 0, (qint32) ConstructObject);
+ else if (aGroup == ModelAPI_ResultBody::group())
+ return createIndex(aRow, 0, (qint32) BodiesObject);
+ else if (aGroup == ModelAPI_ResultGroup::group())
+ return createIndex(aRow, 0, (qint32) GroupObject);
+ else
+ return createIndex(aRow + getRowsNumber(), 0, (qint32) HistoryObject);
+ }
+ return aIndex;
+}
+
+
+int PartSet_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;
+}
+
+int PartSet_PartDataModel::lastHistoryRow() const
+{
+ DocumentPtr aDoc = partDocument();
+ FeaturePtr aFeature = aDoc->currentFeature(true);
+ if (aFeature.get())
+ return getRowsNumber() + aDoc->index(aFeature);
+ else
+ return getRowsNumber() - 1;
+}
+
+void PartSet_PartDataModel::setLastHistoryItem(const QModelIndex& theIndex)
+{
+ SessionPtr aMgr = ModelAPI_Session::get();
+ DocumentPtr aDoc = partDocument();
+ std::string aOpName = tr("History change").toStdString();
+ if (theIndex.internalId() == HistoryObject) {
+ ObjectPtr aObject = object(theIndex);
+ aMgr->startOperation(aOpName);
+ aDoc->setCurrentFeature(std::dynamic_pointer_cast<ModelAPI_Feature>(aObject), true);
+ aMgr->finishOperation();
+ } else {
+ aMgr->startOperation(aOpName);
+ aDoc->setCurrentFeature(FeaturePtr(), true);
+ aMgr->finishOperation();
+ }
+}
+
+QModelIndex PartSet_PartDataModel::lastHistoryItem() const
+{
+ return index(lastHistoryRow(), 1);
+}
+
+Qt::ItemFlags PartSet_PartDataModel::flags(const QModelIndex& theIndex) const
+{
+ Qt::ItemFlags aFlags = Qt::ItemIsSelectable;
+ if (object(theIndex)) {
+ aFlags |= Qt::ItemIsEditable;
+ }
+ if (theIndex.internalId() == HistoryObject) {
+ if (theIndex.row() <= lastHistoryRow() || (theIndex.column() == 1))
+ aFlags |= Qt::ItemIsEnabled;
+ } else
+ aFlags |= Qt::ItemIsEnabled;
+ return aFlags;
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+#ifndef PartSet_PartDataModel_H
+#define PartSet_PartDataModel_H
+
+#include "PartSet.h"
+#include "PartSet_DataTreeModel.h"
+
+/**\class PartSet_TopDataModel
+ * \ingroup GUI
+ * \brief This is a data model for Object Browser (QTreeView).
+ * It represents only upper part of data tree (non-parts tree items)
+ */
+class PARTSET_EXPORT PartSet_TopDataModel : public PartSet_FeaturesModel
+{
+Q_OBJECT
+ public:
+ /// Constructor
+ /// \param theParent a parent object
+ PartSet_TopDataModel(QObject* theParent);
+ virtual ~PartSet_TopDataModel();
+
+ // Reimpl from QAbstractItemModel
+
+ /// Returns the data stored under the given role for the item referred to by the index.
+ /// \param theIndex a model index
+ /// \param theRole a data role (see Qt::ItemDataRole)
+ virtual QVariant data(const QModelIndex& theIndex, int theRole) const;
+
+ /// Returns the data for the given role and section in the header with the specified orientation.
+ /// \param theSection a section
+ /// \param theOrient an orientation
+ /// \param theRole a data role (see Qt::ItemDataRole)
+ virtual QVariant headerData(int theSection, Qt::Orientation theOrient,
+ int theRole = Qt::DisplayRole) const;
+
+ /// Returns the number of rows under the given parent. When the parent is valid it means that
+ /// rowCount is returning the number of children of parent.
+ /// \param theParent a parent model index
+ virtual int rowCount(const QModelIndex &theParent = QModelIndex()) const;
+
+ /// Returns the number of columns for the children of the given parent.
+ /// It has a one column
+ /// \param theParent a parent model index
+ virtual int columnCount(const QModelIndex &theParent = QModelIndex()) const;
+
+
+ /// Returns the index of the item in the model specified by the given row, column and parent index.
+ /// \param theRow a row
+ /// \param theColumn a column
+ /// \param theParent a parent model index
+ virtual QModelIndex index(int theRow, int theColumn, const QModelIndex& theParent =
+ QModelIndex()) const;
+
+ /// Returns the parent of the model item with the given index.
+ /// If the item has no parent, an invalid QModelIndex is returned.
+ /// \param theIndex a model index
+ virtual QModelIndex parent(const QModelIndex& theIndex) const;
+
+ /// Returns true if parent has any children; otherwise returns false.
+ /// \param theParent a parent model index
+ virtual bool hasChildren(const QModelIndex& theParent = QModelIndex()) const;
+
+ //! Returns object by the given Model index.
+ //! Returns 0 if the given index is not index of a object
+ virtual ObjectPtr object(const QModelIndex& theIndex) const;
+
+ //! Returns QModelIndex which corresponds to the given object
+ //! If the object is not found then index is not valid
+ virtual QModelIndex objectIndex(const ObjectPtr& theObject) const;
+
+ //! Returns parent index of the given object
+ virtual QModelIndex findParent(const ObjectPtr& theObject) const;
+
+ //! Returns index corresponded to the group
+ virtual QModelIndex findGroup(const std::string& theGroup) const;
+
+ private:
+ //! Types of QModelIndexes
+ enum DataIds
+ {
+ ParamsFolder,
+ ParamObject,
+ ConstructFolder,
+ ConstructObject
+ //GroupsFolder,
+ //GroupObject
+ };
+
+};
+
+/**\class PartSet_PartDataModel
+ * \ingroup GUI
+ * \brief This is a data model for Object Browser (QTreeView).
+ * It represents data tree only of a one part
+ */
+class PartSet_PartDataModel : public PartSet_PartModel
+{
+Q_OBJECT
+ public:
+ /// Constructor
+ /// \param theParent a parent object
+ PartSet_PartDataModel(QObject* theParent);
+ virtual ~PartSet_PartDataModel();
+
+ // Reimpl from QAbstractItemModel
+
+ /// Returns the data stored under the given role for the item referred to by the index.
+ /// \param theIndex a model index
+ /// \param theRole a data role (see Qt::ItemDataRole)
+ virtual QVariant data(const QModelIndex& theIndex, int theRole) const;
+
+ /// Returns the data for the given role and section in the header with the specified orientation.
+ /// \param theSection a section
+ /// \param theOrient an orientation
+ /// \param theRole a data role (see Qt::ItemDataRole)
+ virtual QVariant headerData(int theSection, Qt::Orientation theOrient,
+ int theRole = Qt::DisplayRole) const;
+
+ /// Returns the number of rows under the given parent. When the parent is valid it means that
+ /// rowCount is returning the number of children of parent.
+ /// \param theParent a parent model index
+ virtual int rowCount(const QModelIndex &theParent = QModelIndex()) const;
+
+ /// Returns the number of columns for the children of the given parent.
+ /// It has a one column
+ /// \param theParent a parent model index
+ virtual int columnCount(const QModelIndex &theParent = QModelIndex()) const;
+
+ /// Returns the item flags for the given index.
+ /// \param theIndex a model index
+ virtual Qt::ItemFlags flags(const QModelIndex& theIndex) const;
+
+ /// Returns the index of the item in the model specified by the given row, column and parent index.
+ /// \param theRow a row
+ /// \param theColumn a column
+ /// \param theParent a parent model index
+ virtual QModelIndex index(int theRow, int theColumn, const QModelIndex& theParent =
+ QModelIndex()) const;
+
+ /// Returns the parent of the model item with the given index.
+ /// If the item has no parent, an invalid QModelIndex is returned.
+ /// \param theIndex a model index
+ virtual QModelIndex parent(const QModelIndex& theIndex) const;
+
+ /// Returns true if parent has any children; otherwise returns false.
+ /// \param theParent a parent model index
+ virtual bool hasChildren(const QModelIndex& theParent = QModelIndex()) const;
+
+ //! Returns object by the given Model index.
+ //! Returns 0 if the given index is not index of a object
+ virtual ObjectPtr object(const QModelIndex& theIndex) const;
+
+ //! Returns QModelIndex which corresponds to the given object
+ //! If the object is not found then index is not valid
+ virtual QModelIndex objectIndex(const ObjectPtr& theObject) const;
+
+ //! Returns true if the given document is a sub-document of this tree
+ virtual bool hasDocument(const DocumentPtr& theDoc) const;
+
+ //! Returns parent index of the given object
+ virtual QModelIndex findParent(const ObjectPtr& theObject) const;
+
+ //! Returns index corresponded to the group
+ virtual QModelIndex findGroup(const std::string& theGroup) const;
+
+ //! Set an Index which will be considered as a last history index
+ //! \param theIndex a last index for history
+ void setLastHistoryItem(const QModelIndex& theIndex);
+
+ //! Returns last history item
+ QModelIndex lastHistoryItem() const;
+
+ private:
+
+ //! Returns document of the current part
+ DocumentPtr partDocument() const;
+
+ //! Returns defult number of rows
+ int getRowsNumber() const;
+
+ int lastHistoryRow() const;
+
+ //! Types of QModelIndexes
+ enum DataIds
+ {
+ //MyRoot,
+ ParamsFolder,
+ ParamObject,
+ ConstructFolder,
+ ConstructObject,
+ BodiesFolder,
+ BodiesObject,
+ GroupsFolder,
+ GroupObject,
+ HistoryObject
+ };
+};
+
+#endif
#include <SketchPlugin_ConstraintCoincidence.h>
#include <SketchPlugin_ConstraintFillet.h>
#include <SketchPlugin_ConstraintMirror.h>
+#include <SketchPlugin_MultiRotation.h>
+#include <SketchPlugin_MultiTranslation.h>
#include <SketcherPrs_Tools.h>
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();
- aIds << SketchPlugin_ConstraintHorizontal::ID().c_str();
- aIds << SketchPlugin_ConstraintVertical::ID().c_str();
- aIds << SketchPlugin_ConstraintEqual::ID().c_str();
- aIds << SketchPlugin_ConstraintTangent::ID().c_str();
- aIds << SketchPlugin_ConstraintCoincidence::ID().c_str();
aIds << SketchPlugin_ConstraintFillet::ID().c_str();
- aIds << SketchPlugin_ConstraintMirror::ID().c_str();
+ aIds.append(constraintsIdList());
}
return aIds;
}
aIds << SketchPlugin_ConstraintTangent::ID().c_str();
aIds << SketchPlugin_ConstraintCoincidence::ID().c_str();
aIds << SketchPlugin_ConstraintMirror::ID().c_str();
+ aIds << SketchPlugin_MultiRotation::ID().c_str();
+ aIds << SketchPlugin_MultiTranslation::ID().c_str();
}
return aIds;
}
+void PartSet_SketcherMgr::sketchSelectionModes(QIntList& theModes)
+{
+ theModes.clear();
+
+ theModes.append(SketcherPrs_Tools::Sel_Dimension_Text);
+ theModes.append(SketcherPrs_Tools::Sel_Dimension_Line);
+ theModes.append(SketcherPrs_Tools::Sel_Constraint);
+ theModes.append(AIS_Shape::SelectionMode((TopAbs_ShapeEnum) TopAbs_VERTEX));
+ theModes.append(AIS_Shape::SelectionMode((TopAbs_ShapeEnum) TopAbs_EDGE));
+}
bool PartSet_SketcherMgr::isSketchOperation(ModuleBase_Operation* theOperation)
{
// Display all sketcher sub-Objects
myCurrentSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theOperation->feature());
XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
- XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
// Hide sketcher result
std::list<ResultPtr> aResults = myCurrentSketch->results();
std::list<ResultPtr>::const_iterator aIt;
for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
- aDisplayer->erase((*aIt), false);
+ (*aIt)->setDisplayed(false);
}
- aDisplayer->erase(myCurrentSketch, false);
+ myCurrentSketch->setDisplayed(false);
// Display sketcher objects
for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
std::list<ResultPtr> aResults = aFeature->results();
std::list<ResultPtr>::const_iterator aIt;
for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
- aDisplayer->display((*aIt), false);
+ (*aIt)->setDisplayed(true);
}
- aDisplayer->display(aFeature, false);
+ aFeature->setDisplayed(true);
}
if (myPlaneFilter.IsNull())
std::shared_ptr<GeomAPI_Pln> aPln = PartSet_Tools::sketchPlane(myCurrentSketch);
myPlaneFilter->setPlane(aPln->impl<gp_Pln>());
}
- aDisplayer->updateViewer();
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+ // all sketch objects should be activated in the sketch selection modes by edit operation start
+ if (theOperation->isEditOperation())
+ activateObjectsInSketchMode(true);
}
void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
activateObjectsInSketchMode(false);
XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
- XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
DataPtr aData = myCurrentSketch->data();
if ((!aData) || (!aData->isValid())) {
+ XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
// The sketch was aborted
myCurrentSketch = CompositeFeaturePtr();
myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);
foreach (ObjectPtr aObj, aObjects) {
DataPtr aObjData = aObj->data();
if ((!aObjData) || (!aObjData->isValid()))
- aDisplayer->erase(aObj);
+ aObj->setDisplayed(false);
}
return;
}
std::list<ResultPtr> aResults = aFeature->results();
std::list<ResultPtr>::const_iterator aIt;
for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
- aDisplayer->erase((*aIt), false);
+ (*aIt)->setDisplayed(false);
}
- aDisplayer->erase(aFeature, false);
+ aFeature->setDisplayed(false);
}
// Display sketcher result
std::list<ResultPtr> aResults = myCurrentSketch->results();
std::list<ResultPtr>::const_iterator aIt;
for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
- aDisplayer->display((*aIt), false);
+ (*aIt)->setDisplayed(true);
}
- aDisplayer->display(myCurrentSketch);
+ myCurrentSketch->setDisplayed(true);
myCurrentSketch = CompositeFeaturePtr();
myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);
- aDisplayer->updateViewer();
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
}
void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation)
// it is hidden by a sketch operation start and shown by a sketch stop, just the sketch
// nested features can be visualized
FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
- if (aFeature.get() != NULL && aFeature == activeSketch())
+ if (aFeature.get() != NULL && aFeature == activeSketch()) {
aCanDisplay = false;
+ }
}
else { // there are no an active sketch
// 2. sketch sub-features should not be visualized if the sketch operation is not active
if (aFeature.get() != NULL) {
std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
- if (aSketchFeature.get())
+ if (aSketchFeature.get()) {
aCanDisplay = false;
+ }
}
}
}
}
}
- if (!isObjectFound)
+ if (!isObjectFound) {
+ theObject->setDisplayed(aCanDisplay); // If it be set into True - set to False
return aCanDisplay;
+ }
// 4. For created nested feature operation do not display the created feature if
// the mouse curstor leaves the OCC window.
}
}
#endif
+ theObject->setDisplayed(aCanDisplay); // If it be set into True - set to False
return aCanDisplay;
}
ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
- XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
// 1. change visibility of the object itself, here the presentable object is processed,
// e.g. constraints features
FeaturePtr aFeature = theOperation->feature();
std::list<ResultPtr> aResults = aFeature->results();
if (isToDisplay)
- aDisplayer->display(aFeature, false);
+ aFeature->setDisplayed(true);
else
- aDisplayer->erase(aFeature, false);
+ aFeature->setDisplayed(false);
// change visibility of the object results, e.g. non-constraint features
std::list<ResultPtr>::const_iterator aIt;
for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
if (isToDisplay) {
- aDisplayer->display(*aIt, false);
+ (*aIt)->setDisplayed(true);
}
else {
- aDisplayer->erase(*aIt, false);
+ (*aIt)->setDisplayed(false);
}
}
- aDisplayer->updateViewer();
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
}
void PartSet_SketcherMgr::activateObjectsInSketchMode(const bool isActive)
XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
QIntList aModes;
- if (isActive) {
- aModes.append(SketcherPrs_Tools::Sel_Dimension_Text);
- aModes.append(SketcherPrs_Tools::Sel_Dimension_Line);
- aModes.append(SketcherPrs_Tools::Sel_Constraint);
- aModes.append(AIS_Shape::SelectionMode((TopAbs_ShapeEnum) TopAbs_VERTEX));
- aModes.append(AIS_Shape::SelectionMode((TopAbs_ShapeEnum) TopAbs_EDGE));
- }
+ if (isActive)
+ sketchSelectionModes(aModes);
aDisplayer->activateObjects(aModes);
}
ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
- XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
const QStringList& aConstrIds = constraintsIdList();
for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
FeaturePtr aSubFeature = myCurrentSketch->subFeature(i);
if (aConstrIds.contains(QString(aSubFeature->getKind().c_str()))) {
if (myIsConstraintsShown)
- aDisplayer->display(aSubFeature, false);
+ aSubFeature->setDisplayed(true);
else
- aDisplayer->erase(aSubFeature, false);
+ aSubFeature->setDisplayed(false);
}
}
- aDisplayer->updateViewer();
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
}
/// Returns list of strings which contains id's of constraints operations
static const QStringList& constraintsIdList();
+ /// Returns a list of modes, where the AIS objects should be activated
+ /// \param theModes a list of modes
+ static void sketchSelectionModes(QIntList& theModes);
+
public slots:
/// Process sketch plane selected event
void onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& thePln);
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+/*
+ * PartSet_WidgetFileSelector.cpp
+ *
+ * Created on: May 18, 2015
+ * Author: spo
+ */
+
+#include "PartSet_WidgetFileSelector.h"
+
+#include <ModelAPI_AttributeString.h>
+
+PartSet_WidgetFileSelector::PartSet_WidgetFileSelector(QWidget* theParent,
+ ModuleBase_IWorkshop* theWorkshop,
+ const Config_WidgetAPI* theData,
+ const std::string& theParentId)
+: ModuleBase_WidgetFileSelector(theParent, theData, theParentId)
+, myWorkshop(theWorkshop)
+{
+}
+
+bool PartSet_WidgetFileSelector::restoreValue()
+{
+ // A rare case when plugin was not loaded.
+ if (!myFeature)
+ return false;
+
+ DataPtr aData = myFeature->data();
+ AttributeStringPtr aStringAttr = aData->string("export_file_format");
+ mySelectedFilter = formatToFilter(shortFormatToFullFormat(QString::fromStdString(aStringAttr->value())));
+
+ return ModuleBase_WidgetFileSelector::restoreValue();
+}
+
+bool PartSet_WidgetFileSelector::storeValueCustom() const
+{
+ // A rare case when plugin was not loaded.
+ if (!myFeature)
+ return false;
+
+ DataPtr aData = myFeature->data();
+ AttributeStringPtr aStringAttr = aData->string("export_file_format");
+ aStringAttr->setValue(filterToShortFormat(mySelectedFilter).toStdString());
+
+ return ModuleBase_WidgetFileSelector::storeValueCustom();
+}
+
+QString PartSet_WidgetFileSelector::filterToShortFormat( const QString & theFilter )
+{
+ return theFilter.section(' ', 0, 0);
+}
+
+QString PartSet_WidgetFileSelector::shortFormatToFullFormat( const QString & theFormat ) const
+{
+ foreach(const QString & eachFormat, getValidatorFormats())
+ if (filterToShortFormat(formatToFilter(eachFormat)) == theFormat)
+ return eachFormat;
+ return QString();
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+/*
+ * PartSet_WidgetFileSelector.h
+ *
+ * Created on: May 18, 2015
+ * Author: spo
+ */
+
+#ifndef PARTSET_WIDGETFILESELECTOR_H_
+#define PARTSET_WIDGETFILESELECTOR_H_
+
+#include "PartSet.h"
+
+#include <ModuleBase_WidgetFileSelector.h>
+
+class ModuleBase_IWorkshop;
+
+/**
+* \ingroup Modules
+* Customization of ModuleBase_WidgetFileSelector in order to write
+* format of exported file.
+*/
+class PARTSET_EXPORT PartSet_WidgetFileSelector : public ModuleBase_WidgetFileSelector
+{
+ Q_OBJECT
+public:
+ /// Constructor
+ /// \param theParent the parent object
+ /// \param theWorkshop instance of workshop interface
+ /// \param theData the widget configuration. The attribute of the model widget is obtained from
+ /// \param theParentId is Id of a parent of the current attribute
+ PartSet_WidgetFileSelector(QWidget* theParent,
+ ModuleBase_IWorkshop* theWorkshop,
+ const Config_WidgetAPI* theData,
+ const std::string& theParentId);
+
+ virtual ~PartSet_WidgetFileSelector() {}
+
+ /// Reimplemented from ModuleBase_WidgetFileSelector::restoreValue()
+ virtual bool restoreValue();
+
+protected:
+ /// Reimplemented from ModuleBase_WidgetFileSelector::storeValueCustom()
+ virtual bool storeValueCustom() const;
+
+ /// Returns a short format string of theFilter string
+ static QString filterToShortFormat( const QString & theFilter );
+
+ /// Returns a full format string for the short format
+ QString shortFormatToFullFormat( const QString & theShortFormat ) const;
+
+private:
+ ModuleBase_IWorkshop* myWorkshop; // the current workshop
+};
+
+#endif /* PARTSET_WIDGETFILESELECTOR_H_ */
virtual ~PartSet_WidgetMultiSelector();
+ /// Defines if it is supposed that the widget should interact with the viewer.
+ virtual bool isViewerSelector() { return true; }
+
/// Set sketcher
/// \param theSketch a sketcher object
void setSketcher(CompositeFeaturePtr theSketch) { mySketch = theSketch; }
#include <GeomAPI_Pnt2d.h>
#include <SketchPlugin_Feature.h>
+#include <SketchPlugin_ConstraintCoincidence.h>
#include <QGroupBox>
#include <QGridLayout>
{
}
-bool PartSet_WidgetPoint2D::setSelection(ModuleBase_ViewerPrs theValue)
+bool PartSet_WidgetPoint2D::setSelection(const QList<ModuleBase_ViewerPrs>& theValues, int& thePosition)
{
+ if (thePosition < 0 || thePosition >= theValues.size())
+ return false;
+ ModuleBase_ViewerPrs aValue = theValues[thePosition];
+ thePosition++;
+
Handle(V3d_View) aView = myWorkshop->viewer()->activeView();
bool isDone = false;
- TopoDS_Shape aShape = theValue.shape();
+ TopoDS_Shape aShape = aValue.shape();
double aX, aY;
if (getPoint2d(aView, aShape, aX, aY)) {
isDone = setPoint(aX, aY);
QIntList aModes;
aModes << TopAbs_VERTEX;
- if (isEditingMode())
- aModes << TopAbs_EDGE;
+ aModes << TopAbs_EDGE;
myWorkshop->moduleConnector()->activateSubShapesSelection(aModes);
}
emit vertexSelected();
emit focusOutWidget(this);
return;
+ } else if (aShape.ShapeType() == TopAbs_EDGE) {
+ // Create point-edge coincedence
+ FeaturePtr aFeature = mySketch->addFeature(SketchPlugin_ConstraintCoincidence::ID());
+ std::shared_ptr<ModelAPI_Data> aData = aFeature->data();
+
+ std::shared_ptr<ModelAPI_AttributeRefAttr> aRef1 = std::dynamic_pointer_cast<
+ ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ AttributePtr aThisAttr = feature()->data()->attribute(attributeID());
+ std::shared_ptr<GeomDataAPI_Point2D> aThisPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aThisAttr);
+ aRef1->setAttr(aThisPoint);
+
+ std::shared_ptr<ModelAPI_AttributeRefAttr> aRef2 = std::dynamic_pointer_cast<
+ ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ aRef2->setObject(aObject);
+ aFeature->execute();
+ emit vertexSelected();
+ emit focusOutWidget(this);
+ return;
}
}
// End of Bug dependent fragment
/// 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);
+ virtual bool setSelection(const QList<ModuleBase_ViewerPrs>& theValues, int& thePosition);
virtual bool restoreValue();
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PartSet_WidgetPoint2dAngle.h
+// Created: 23 June 2014
+// Author: Vitaly Smetannikov
+
+#include "PartSet_WidgetPoint2dAngle.h"
+
+#include <ModuleBase_ParamSpinBox.h>
+
+#include <ModuleBase_Tools.h>
+
+#include <GeomAPI_Pnt2d.h>
+#include <GeomDataAPI_Point2D.h>
+
+#include <ModelAPI_Data.h>
+#include <ModelAPI_AttributeDouble.h>
+
+#include <QMouseEvent>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
+
+#define PI 3.1415926535897932
+
+PartSet_WidgetPoint2dAngle::PartSet_WidgetPoint2dAngle(QWidget* theParent,
+ const Config_WidgetAPI* theData,
+ const std::string& theParentId)
+: PartSet_WidgetPoint2dDistance(theParent, theData, theParentId)
+{
+}
+
+PartSet_WidgetPoint2dAngle::~PartSet_WidgetPoint2dAngle()
+{
+}
+
+double PartSet_WidgetPoint2dAngle::computeValue(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPnt,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theCurrentPnt)
+{
+ std::shared_ptr<GeomAPI_Dir2d> aHorizontalDir(new GeomAPI_Dir2d(1, 0));
+ std::shared_ptr<GeomAPI_XY> aStartPnt = theFirstPnt->xy();
+ std::shared_ptr<GeomAPI_XY> aEndPnt = theCurrentPnt->xy();
+
+ std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
+
+ double aValue = aHorizontalDir->angle(aLineDir);
+ aValue *= 180.0 / PI;
+
+ return aValue;
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PartSet_WidgetPoint2dAngle.h
+// Created: 30 Apr 2015
+// Author: Natalia Ermolaeva
+
+#ifndef PartSet_WidgetPoint2dAngle_H
+#define PartSet_WidgetPoint2dAngle_H
+
+#include "PartSet.h"
+#include "PartSet_WidgetPoint2dDistance.h"
+
+#include <ModelAPI_Feature.h>
+
+class GeomAPI_Pnt2d;
+
+/**
+* \ingroup Modules
+* Implementation of model widget for widget which provides input of an anble between two points
+* The XML definion is the same as the parent one.
+*/
+class PARTSET_EXPORT PartSet_WidgetPoint2dAngle : public PartSet_WidgetPoint2dDistance
+{
+Q_OBJECT
+ public:
+ /// Constructor
+ /// \param theParent the parent object
+ /// \param theData the widget configuation. The attribute of the model widget is obtained from
+ /// \param theParentId is Id of a parent of the current attribute
+ PartSet_WidgetPoint2dAngle(QWidget* theParent, const Config_WidgetAPI* theData,
+ const std::string& theParentId);
+
+ virtual ~PartSet_WidgetPoint2dAngle();
+
+protected:
+ /// Compute an angle between points
+ /// \param theFirstPnt a point value of the out point attribute
+ /// \param theCurrentPnt a point of the current widget
+ /// \return a double value
+ virtual double computeValue(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPnt,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theCurrentPnt);
+};
+
+#endif
if (!aPoint)
return;
- double aRadius = thePnt->distance(aPoint->pnt());
+ double aValue = computeValue(aPoint->pnt(), thePnt);
AttributeDoublePtr aReal = aData->real(attributeID());
- if (aReal && (aReal->value() != aRadius)) {
- aReal->setValue(aRadius);
+ if (aReal && (aReal->value() != aValue)) {
+ aReal->setValue(aValue);
- ModuleBase_Tools::setSpinValue(mySpinBox, aRadius);
+ ModuleBase_Tools::setSpinValue(mySpinBox, aValue);
storeValue();
}
}
+double PartSet_WidgetPoint2dDistance::computeValue(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPnt,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theCurrentPnt)
+{
+ return theCurrentPnt->distance(theFirstPnt);
+}
+
void PartSet_WidgetPoint2dDistance::activateCustom()
{
XGUI_ViewerProxy* aViewer = myWorkshop->viewer();
/// 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<GeomAPI_Pnt2d>& thePnt);
+ /// Compute the distance between points
+ /// \param theFirstPnt a point value of the out point attribute
+ /// \param theCurrentPnt a point of the current widget
+ /// \return a double value
+ virtual double computeValue(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPnt,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theCurrentPnt);
+
private slots:
/// Process values changed event
void onValuesChanged();
- private:
+protected:
XGUI_Workshop* myWorkshop;
std::string myFirstPntName;
#include <XGUI_Workshop.h>
+#include <XGUI_ModuleConnector.h>
+#include <XGUI_Displayer.h>
+#include <XGUI_SelectionMgr.h>
+#include <XGUI_Selection.h>
+#include <SelectMgr_IndexedMapOfOwner.hxx>
+#include <StdSelect_BRepOwner.hxx>
+
PartSet_WidgetShapeSelector::PartSet_WidgetShapeSelector(QWidget* theParent,
ModuleBase_IWorkshop* theWorkshop,
const Config_WidgetAPI* theData,
bool PartSet_WidgetShapeSelector::setObject(ObjectPtr theSelectedObject, GeomShapePtr theShape)
{
ObjectPtr aSelectedObject = theSelectedObject;
- GeomShapePtr aShape = theShape;
+ //GeomShapePtr aShape = theShape;
FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(aSelectedObject);
if (aSelectedFeature == myFeature) // In order to avoid selection of the same object
if ((aSPFeature.get() != NULL) && aSPFeature->isExternal() && (!myExternalObjectMgr->useExternal()))
return false;
- if (aSPFeature.get() == NULL && aShape.get() != NULL && !aShape->isNull() && myExternalObjectMgr->useExternal()) {
+ if (aSPFeature.get() == NULL && theShape.get() != NULL && !theShape->isNull() && myExternalObjectMgr->useExternal()) {
aSelectedObject = myExternalObjectMgr->externalObject(theSelectedObject, theShape, sketch());
} else {
// Processing of sketch object
- DataPtr aData = myFeature->data();
- if (aShape) {
- AttributePtr aAttr = aData->attribute(attributeID());
- AttributeRefAttrPtr aRefAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aAttr);
- if (aRefAttr) {
- // it is possible that the point feature is selected. It should be used itself
- // instead of searching an attribute for the shape
- bool aShapeIsResult = false;
- /*ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theSelectedObject);
- if (aResult.get() != NULL) {
- GeomShapePtr aShapePtr = aResult->shape();
- // it is important to call isEqual of the shape of result.
- // It is a GeomAPI_Vertex shape for the point. The shape of the parameter is
- // GeomAPI_Shape. It is important to use the realization of the isEqual method from
- // GeomAPI_Vertex class
- aShapeIsResult = aShapePtr.get() != NULL && aShapePtr->isEqual(theShape);
- }*/
-
- AttributePtr aPntAttr;
- if (!aShapeIsResult) {
- TopoDS_Shape aTDSShape = aShape->impl<TopoDS_Shape>();
- aPntAttr = PartSet_Tools::findAttributeBy2dPoint(aSelectedObject, aTDSShape, mySketch);
+ if (theShape.get()) {
+ setPointAttribute(theSelectedObject, theShape);
+ return true;
+ }
+ }
+ return ModuleBase_WidgetShapeSelector::setObject(aSelectedObject, theShape);
+}
+
+//********************************************************************
+GeomShapePtr PartSet_WidgetShapeSelector::getShape() const
+{
+ // an empty shape by default
+ GeomShapePtr aShape;
+
+ // 1. find an attribute value in attribute reference attribute value
+ DataPtr aData = myFeature->data();
+ AttributePtr aAttr = aData->attribute(attributeID());
+ AttributeRefAttrPtr aRefAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aAttr);
+ if (aRefAttr) {
+ if (!aRefAttr->isObject()) {
+ AttributePtr anAttribute = aRefAttr->attr();
+ if (anAttribute.get()) {
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myWorkshop);
+ XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
+
+ // 2. find visualized vertices of the attribute and if the attribute of the vertex is
+ // the same, return it
+ FeaturePtr anAttributeFeature = ModelAPI_Feature::feature(anAttribute->owner());
+ // 2.1 get visualized results of the feature
+ const std::list<ResultPtr>& aResList = anAttributeFeature->results();
+ std::list<ResultPtr>::const_iterator anIt = aResList.begin(), aLast = aResList.end();
+ for (; anIt != aLast; anIt++) {
+ AISObjectPtr aAISObj = aDisplayer->getAISObject(*anIt);
+ if (aAISObj.get() != NULL) {
+ Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
+ // 2.2 find selected owners of a visualizedd object
+ SelectMgr_IndexedMapOfOwner aSelectedOwners;
+ aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);
+ for (Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++) {
+ Handle(SelectMgr_EntityOwner) anOwner = aSelectedOwners(i);
+ if (!anOwner.IsNull()) {
+ Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast(anOwner);
+ if (!aBRepOwner.IsNull() && aBRepOwner->HasShape()) {
+ const TopoDS_Shape& aBRepShape = aBRepOwner->Shape();
+ if (aBRepShape.ShapeType() == TopAbs_VERTEX) {
+ // 2.3 if the owner is vertex and an attribute of the vertex is equal to the initial
+ // attribute, returns the shape
+ AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(anAttributeFeature,
+ aBRepShape, sketch());
+ if (aPntAttr.get() != NULL && aPntAttr == anAttribute) {
+ aShape = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape);
+ aShape->setImpl(new TopoDS_Shape(aBRepShape));
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
}
- // this is an alternative, whether the attribute should be set or object in the attribute
- // the first check is the attribute because the object already exist
- // the object is set only if there is no selected attribute
- // test case is - preselection for distance operation, which contains two points selected on lines
- if (aPntAttr)
- aRefAttr->setAttr(aPntAttr);
- else if (aSelectedObject)
- aRefAttr->setObject(aSelectedObject);
- return true;
}
}
}
- return ModuleBase_WidgetShapeSelector::setObject(aSelectedObject, aShape);
+ if (!aShape.get())
+ aShape = ModuleBase_WidgetShapeSelector::getShape();
+ return aShape;
}
//********************************************************************
ModuleBase_WidgetShapeSelector::restoreAttributeValue(theValid);
myExternalObjectMgr->removeExternal(sketch(), myFeature);
}
+
+//********************************************************************
+void PartSet_WidgetShapeSelector::setPointAttribute(ObjectPtr theSelectedObject, GeomShapePtr theShape)
+{
+ DataPtr aData = myFeature->data();
+ AttributePtr aAttr = aData->attribute(attributeID());
+ AttributeRefAttrPtr aRefAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aAttr);
+ if (aRefAttr) {
+ // it is possible that the point feature is selected. It should be used itself
+ // instead of searching an attribute for the shape
+ bool aShapeIsResult = false;
+ /*ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theSelectedObject);
+ if (aResult.get() != NULL) {
+ GeomShapePtr aShapePtr = aResult->shape();
+ // it is important to call isEqual of the shape of result.
+ // It is a GeomAPI_Vertex shape for the point. The shape of the parameter is
+ // GeomAPI_Shape. It is important to use the realization of the isEqual method from
+ // GeomAPI_Vertex class
+ aShapeIsResult = aShapePtr.get() != NULL && aShapePtr->isEqual(theShape);
+ }*/
+
+ AttributePtr aPntAttr;
+ if (!aShapeIsResult) {
+ TopoDS_Shape aTDSShape = theShape->impl<TopoDS_Shape>();
+ aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theSelectedObject, aTDSShape, mySketch);
+ }
+ // this is an alternative, whether the attribute should be set or object in the attribute
+ // the first check is the attribute because the object already exist
+ // the object is set only if there is no selected attribute
+ // test case is - preselection for distance operation, which contains two points selected on lines
+ if (aPntAttr)
+ aRefAttr->setAttr(aPntAttr);
+ else
+ aRefAttr->setObject(theSelectedObject);
+ }
+}
/**
* \ingroup Modules
* Customosation of ModuleBase_WidgetShapeSelector in order to provide
-* working with sketch specific objects.
+* working with sketch specific objects and external objects.
*/
class PARTSET_EXPORT PartSet_WidgetShapeSelector: public ModuleBase_WidgetShapeSelector
{
/// \param theShape a selected shape, which is used in the selection attribute
virtual bool setObject(ObjectPtr theSelectedObject, GeomShapePtr theShape);
+ /// Get the shape from the attribute if the attribute contain a shape
+ /// It processes the ref attr type of attributes. It obtains the referenced attribute,
+ /// results of the attribute feature. And it founds a vertes in the owners of the results
+ /// If the vertex is found, it creates a geom shape on it.
+ /// \return a shape
+ virtual GeomShapePtr getShape() const;
+
/// Creates a backup of the current values of the attribute
/// It should be realized in the specific widget because of different
/// parameters of the current attribute
/// \param theValid a boolean flag, if restore happens for valid parameters
void restoreAttributeValue(const bool theValid);
+ /// Found the sketch point attribute by the shape and set it in the feature attribute
+ /// otherwise set the selected object
+ /// \param theSelectedObject an object
+ /// \param theShape a selected shape, which is used in the selection attribute
+ void setPointAttribute(ObjectPtr theSelectedObject, GeomShapePtr theShape);
+
protected:
PartSet_ExternalObjectsMgr* myExternalObjectMgr;
/// Pointer to a sketch
erasePreviewPlanes();
}
-bool PartSet_WidgetSketchLabel::setSelection(ModuleBase_ViewerPrs theValue)
+bool PartSet_WidgetSketchLabel::setSelection(const QList<ModuleBase_ViewerPrs>& theValues, int& thePosition)
{
// do not use the given selection if the plane of the sketch has been already set.
// If this check is absent, a selected plane in the viewer can be set in the sketch
if (plane().get())
return true;
- return ModuleBase_WidgetValidated::setSelection(theValue);
+ return ModuleBase_WidgetValidated::setSelection(theValues, thePosition);
}
QList<QWidget*> PartSet_WidgetSketchLabel::getControls() const
/// This value should be processed in the widget according to the needs
/// The method is called by the current operation to process the operation preselection.
/// It is redefined to do nothing if the plane of the sketch has been already set.
- /// \param theValue the wrapped widget value
- virtual bool setSelection(ModuleBase_ViewerPrs theValue);
+ /// \param theValues the wrapped selection values
+ /// \param thePosition an index in the list of values, the values should be get from the index
+ virtual bool setSelection(const QList<ModuleBase_ViewerPrs>& theValues, int& thePosition);
virtual bool restoreValue()
{
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
+ <file>icons/angle.png</file>
+ <file>icons/angle_up.png</file>
+ <file>icons/angle_down.png</file>
<file>icons/arc.png</file>
<file>icons/circle.png</file>
<file>icons/color.png</file>
<file>icons/point.png</file>
<file>icons/plane.png</file>
+ <file>icons/plane_inverted.png</file>
<file>icons/axis.png</file>
<file>icons/duplicate.png</file>
<file>icons/remove.png</file>
<file>icons/revol.png</file>
<file>icons/common.png</file>
<file>icons/import.png</file>
+ <file>icons/export.png</file>
<file>icons/line.png</file>
<file>icons/sketch.png</file>
<file>icons/hand_point.png</file>
+ <file>icons/dimension_up.png</file>
+ <file>icons/dimension_down.png</file>
<file>icons/dimension_v.png</file>
<file>icons/radius.png</file>
<file>icons/perpendicular.png</file>
<file>icons/fillet.png</file>
<file>icons/coincedence.png</file>
<file>icons/mirror.png</file>
+ <file>icons/translate.png</file>
+ <file>icons/rotate.png</file>
+ <file>icons/exec_state_failed.png</file>
+ <file>icons/exec_state_invalid_parameters.png</file>
+ <file>icons/activate.png</file>
+ <file>icons/deactivate.png</file>
+ <file>icons/edit.png</file>
</qresource>
</RCC>
if (!aResult) {
aResult = document()->createPart(data());
setResult(aResult);
- aResult->activate();
+ // do not activate part by simple execution if it is not loaded yet: it must be explicitly
+ // activated for this
+ if (!ModelAPI_Session::get()->isLoadByDemand(aResult->data()->name())) {
+ aResult->activate();
+ }
}
}
/// Part must be added only to PartSet
PARTSETPLUGIN_EXPORT virtual const std::string& documentToAdd();
- /// Returns true if this feature must be displayed in the history (top level of Part tree)
- PARTSETPLUGIN_EXPORT virtual bool isInHistory()
- {
- return false;
- }
-
/// Use plugin manager for features creation
PartSetPlugin_Part();
};
else:
self.my.data().boolean("reverse").setValue(False)
- self.my.data().real("size").setValue(size)
+ self.my.data().real("to_size").setValue(size)
if ModelAPI_Session.get().validators().validate(self.my):
self.my.execute()
else:
self.my.data().boolean("reverse").setValue(False)
- self.my.data().real("size").setValue(size)
+ self.my.data().real("to_size").setValue(size)
self.my.execute()
def result (self):
self.base.setValue( self.length, length )
self.box.setSize( height )
- # Publishing the result
- self.addResult( self.box.result() )
-
-
-
+ # Publishing the result: not needed for Macro feature
+ #self.addResult( self.box.result() )
+
+ def isMacro(self):
+ # Box feature is macro: removes itself on the creation transaction finish
+ return True
SketchPlugin_ConstraintTangent.h
SketchPlugin_ConstraintMirror.h
SketchPlugin_ConstraintFillet.h
+ SketchPlugin_MultiRotation.h
+ SketchPlugin_MultiTranslation.h
SketchPlugin_ExternalValidator.h
SketchPlugin_Validators.h
)
SketchPlugin_ConstraintTangent.cpp
SketchPlugin_ConstraintMirror.cpp
SketchPlugin_ConstraintFillet.cpp
+ SketchPlugin_MultiRotation.cpp
+ SketchPlugin_MultiTranslation.cpp
SketchPlugin_ExternalValidator.cpp
SketchPlugin_Validators.cpp
)
std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
//std::cout<<"Execute circle "<<aCenter->x()<<" "<<aCenter->y()<<" "<<aCenter->z()<<std::endl;
// make a visible point
- std::shared_ptr<GeomAPI_Shape> aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter);
- std::shared_ptr<ModelAPI_ResultConstruction> aConstr1 = document()->createConstruction(
- data(), 0);
- aConstr1->setShape(aCenterPointShape);
- aConstr1->setIsInHistory(false);
- setResult(aConstr1, 0);
+ SketchPlugin_Sketch::createPoint2DResult(this, sketch(), CENTER_ID(), 0);
// make a visible circle
std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
* Also the list of possible attributes is provided to simplify assignment.
*/
-#define SKETCH_CONSTRAINT_COLOR "#ffff00"
-#define SKETCH_DIMENSION_COLOR "#ff00ff"
+#define SKETCH_CONSTRAINT_COLOR "225,225,0"
+#define SKETCH_DIMENSION_COLOR "64,128,225"
/** \class SketchPlugin_ConstraintBase
* \ingroup Plugins
AISObjectPtr anAIS = thePrevious;
if (!anAIS) {
anAIS = SketcherPrs_Factory::coincidentConstraint(this, sketch()->coordinatePlane());
- std::vector<int> aRGB = Config_PropManager::color("Visualization", "sketch_constraint_color",
- SKETCH_DIMENSION_COLOR);
- anAIS->setColor(aRGB[0], aRGB[1], aRGB[2]);
+ //std::vector<int> aRGB = Config_PropManager::color("Visualization", "sketch_constraint_color",
+ // SKETCH_DIMENSION_COLOR);
+ //anAIS->setColor(aRGB[0], aRGB[1], aRGB[2]);
}
return anAIS;
}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File: SketchPlugin_MultiRotation.cpp
+// Created: 21 Apr 2015
+// Author: Artem ZHIDKOV
+
+#include "SketchPlugin_MultiRotation.h"
+
+#include <GeomDataAPI_Point2D.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_Events.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_XY.h>
+
+#include <SketcherPrs_Factory.h>
+
+#include <cmath>
+
+#define PI 3.1415926535897932
+
+SketchPlugin_MultiRotation::SketchPlugin_MultiRotation()
+{
+}
+
+void SketchPlugin_MultiRotation::initAttributes()
+{
+ data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(ANGLE_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(NUMBER_OF_COPIES_ID(), ModelAPI_AttributeInteger::typeId());
+ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefList::typeId());
+ data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefList::typeId());
+ AttributeSelectionListPtr aSelection =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
+ ROTATION_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
+ aSelection->setSelectionType("EDGE");
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_A());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_B());
+}
+
+void SketchPlugin_MultiRotation::execute()
+{
+ AttributeSelectionListPtr aRotationObjectRefs = selectionList(ROTATION_LIST_ID());
+ int aNbCopies = integer(NUMBER_OF_COPIES_ID())->value();
+
+ // Obtain center and angle of rotation
+ std::shared_ptr<GeomDataAPI_Point2D> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ attribute(CENTER_ID()));
+ if (!aCenter || !aCenter->isInitialized())
+ return;
+ // make a visible points
+ SketchPlugin_Sketch::createPoint2DResult(this, sketch(), CENTER_ID(), 0);
+
+ double anAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ attribute(ANGLE_ID()))->value();
+ // Convert angle to radians
+ anAngle *= PI / 180.0;
+
+ // Wait all objects being created, then send update events
+ static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+ bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
+ if (isUpdateFlushed)
+ Events_Loop::loop()->setFlushed(anUpdateEvent, false);
+
+ std::shared_ptr<ModelAPI_Data> aData = data();
+ AttributeRefListPtr aRefListOfShapes = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ AttributeRefListPtr aRefListOfRotated = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ int aCurrentNbCopies = aRefListOfShapes->size() ?
+ aRefListOfRotated->size() / aRefListOfShapes->size() - 1 : 0;
+ std::list<ObjectPtr> anInitialList = aRefListOfShapes->list();
+ std::list<ObjectPtr> aTargetList = aRefListOfRotated->list();
+ std::list<ResultPtr> anAddition;
+ std::vector<bool> isUsed(anInitialList.size(), false);
+ // collect new items and check the items to remove
+ for(int anInd = 0; anInd < aRotationObjectRefs->size(); anInd++) {
+ std::shared_ptr<ModelAPI_AttributeSelection> aSelect = aRotationObjectRefs->value(anInd);
+ std::list<ObjectPtr>::const_iterator anIt = anInitialList.begin();
+ std::vector<bool>::iterator aUsedIt = isUsed.begin();
+ for (; anIt != anInitialList.end(); anIt++, aUsedIt++)
+ if (*anIt == aSelect->context()) {
+ *aUsedIt = true;
+ break;
+ }
+ if (anIt == anInitialList.end())
+ anAddition.push_back(aSelect->context());
+ }
+ // remove unused items
+ std::list<ObjectPtr>::iterator anInitIter = anInitialList.begin();
+ std::list<ObjectPtr>::iterator aTargetIter = aTargetList.begin();
+ std::vector<bool>::iterator aUsedIter = isUsed.begin();
+ for (; aUsedIter != isUsed.end(); aUsedIter++) {
+ if (!(*aUsedIter)) {
+ aRefListOfShapes->remove(*anInitIter);
+ for (int i = 0; i < aCurrentNbCopies && aTargetIter != aTargetList.end(); i++, aTargetIter++) {
+ aRefListOfRotated->remove(*aTargetIter);
+ // remove the corresponding feature from the sketch
+ ResultConstructionPtr aRC =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aTargetIter);
+ DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
+ FeaturePtr aFeature = aDoc ? aDoc->feature(aRC) : FeaturePtr();
+ if (aFeature)
+ aDoc->removeFeature(aFeature);
+ }
+ } else {
+ for (int i = 0; i <= aNbCopies && aTargetIter != aTargetList.end(); i++)
+ aTargetIter++;
+ }
+ if (anInitIter != anInitialList.end())
+ anInitIter++;
+ }
+ // change number of copies
+ if (aCurrentNbCopies != 0 && aNbCopies != aCurrentNbCopies) {
+ bool isAdd = aNbCopies > aCurrentNbCopies;
+ int aMinCopies = isAdd ? aCurrentNbCopies : aNbCopies;
+ int aMaxCopies = isAdd ? aNbCopies : aCurrentNbCopies;
+ int ind = 0;
+
+ aTargetList = aRefListOfRotated->list();
+ aTargetIter = aTargetList.begin();
+ ObjectPtr anObjToCopy = *aTargetIter;
+ while (aTargetIter != aTargetList.end()) {
+ aRefListOfRotated->remove(*aTargetIter);
+ aTargetIter++;
+ ind++;
+ if (ind > aMinCopies && ind <=aMaxCopies) {
+ while (ind <= aMaxCopies) {
+ if (isAdd) {
+ // Add new shifted item
+ ObjectPtr anObject = copyFeature(anObjToCopy);
+ aTargetList.insert(aTargetIter, anObject);
+ } else {
+ // remove object
+ std::list<ObjectPtr>::iterator aRemoveIt = aTargetIter++;
+ ObjectPtr anObject = *aRemoveIt;
+ aTargetList.erase(aRemoveIt);
+ aRefListOfRotated->remove(anObject);
+ // remove the corresponding feature from the sketch
+ ResultConstructionPtr aRC =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(anObject);
+ DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
+ FeaturePtr aFeature = aDoc ? aDoc->feature(aRC) : FeaturePtr();
+ if (aFeature)
+ aDoc->removeFeature(aFeature);
+ }
+ ind++;
+ }
+ ind = 0;
+ if (aTargetIter != aTargetList.end())
+ anObjToCopy = *aTargetIter;
+ }
+ }
+
+ for (aTargetIter = aTargetList.begin(); aTargetIter != aTargetList.end(); aTargetIter++)
+ aRefListOfRotated->append(*aTargetIter);
+ }
+ // add new items
+ std::list<ResultPtr>::iterator anAddIter = anAddition.begin();
+ for (; anAddIter != anAddition.end(); anAddIter++) {
+ aRefListOfShapes->append(*anAddIter);
+ aRefListOfRotated->append(*anAddIter);
+ for (int i = 0; i < aNbCopies; i++) {
+ ObjectPtr anObject = copyFeature(*anAddIter);
+ aRefListOfRotated->append(anObject);
+ }
+ }
+
+//// if (fabs(anAngle) > 1.e-12) {
+//// // Recalculate positions of features
+//// aTargetList = aRefListOfRotated->list();
+//// aTargetIter = aTargetList.begin();
+//// while (aTargetIter != aTargetList.end()) {
+//// ObjectPtr anInitialObject = *aTargetIter++;
+//// for (int i = 0; i < aNbCopies && aTargetIter != aTargetList.end(); i++, aTargetIter++)
+//// rotateFeature(anInitialObject, *aTargetIter, aCenter->x(), aCenter->y(), anAngle * (i + 1));
+//// }
+//// }
+
+ // send events to update the sub-features by the solver
+ if (isUpdateFlushed)
+ Events_Loop::loop()->setFlushed(anUpdateEvent, true);
+}
+
+AISObjectPtr SketchPlugin_MultiRotation::getAISObject(AISObjectPtr thePrevious)
+{
+ if (!sketch())
+ return thePrevious;
+
+ AISObjectPtr anAIS = thePrevious;
+ if (!anAIS) {
+ anAIS = SketcherPrs_Factory::rotateConstraint(this, sketch()->coordinatePlane());
+ }
+ return anAIS;
+}
+
+
+ObjectPtr SketchPlugin_MultiRotation::copyFeature(ObjectPtr theObject)
+{
+ ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theObject);
+ FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
+ if (!aFeature || !aResult)
+ return ObjectPtr();
+
+ FeaturePtr aNewFeature = sketch()->addFeature(aFeature->getKind());
+ aFeature->data()->copyTo(aNewFeature->data());
+ aNewFeature->execute();
+
+ static Events_ID aRedisplayEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ ModelAPI_EventCreator::get()->sendUpdated(aNewFeature, aRedisplayEvent);
+
+ std::shared_ptr<GeomAPI_Shape> aShapeIn = aResult->shape();
+ const std::list<ResultPtr>& aResults = aNewFeature->results();
+ std::list<ResultPtr>::const_iterator anIt = aResults.begin();
+ for (; anIt != aResults.end(); anIt++) {
+ ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anIt);
+ if (!aRC) continue;
+ std::shared_ptr<GeomAPI_Shape> aShapeOut = aRC->shape();
+ if ((aShapeIn->isVertex() && aShapeOut->isVertex()) ||
+ (aShapeIn->isEdge() && aShapeOut->isEdge()) ||
+ (aShapeIn->isFace() && aShapeOut->isFace()))
+ return aRC;
+ }
+ return ObjectPtr();
+}
+
+void SketchPlugin_MultiRotation::rotateFeature(
+ ObjectPtr theInitial, ObjectPtr theTarget,
+ double theCenterX, double theCenterY, double theAngle)
+{
+ std::shared_ptr<GeomAPI_Pnt2d> aCenter(new GeomAPI_Pnt2d(theCenterX, theCenterY));
+ double cosA = std::cos(theAngle);
+ double sinA = std::sin(theAngle);
+
+ FeaturePtr anInitialFeature = ModelAPI_Feature::feature(theInitial);
+ FeaturePtr aTargetFeature = ModelAPI_Feature::feature(theTarget);
+
+ // block feature update
+ aTargetFeature->data()->blockSendAttributeUpdated(true);
+
+ std::list<AttributePtr> anInitAttrList =
+ anInitialFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
+ std::list<AttributePtr> aTargetAttrList =
+ aTargetFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
+ std::list<AttributePtr>::iterator anInitIt = anInitAttrList.begin();
+ std::list<AttributePtr>::iterator aTargetIt = aTargetAttrList.begin();
+ for (; anInitIt != anInitAttrList.end(); anInitIt++, aTargetIt++) {
+ std::shared_ptr<GeomDataAPI_Point2D> aPointFrom =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anInitIt);
+ std::shared_ptr<GeomDataAPI_Point2D> aPointTo =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aTargetIt);
+ std::shared_ptr<GeomAPI_XY> aPnt = aPointFrom->pnt()->xy();
+ if (aPnt->distance(aCenter->xy()) > 1.e-7) {
+ std::shared_ptr<GeomAPI_XY> aDir = aPnt->decreased(aCenter->xy());
+ double dx = cosA * aDir->x() - sinA * aDir->y();
+ double dy = sinA * aDir->x() + cosA * aDir->y();
+ aPnt->setX(aCenter->x() + dx);
+ aPnt->setY(aCenter->y() + dy);
+ }
+ aPointTo->setValue(aPnt->x(), aPnt->y());
+ }
+
+ // unblock feature update
+ aTargetFeature->data()->blockSendAttributeUpdated(false);
+}
+
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File: SketchPlugin_MultiRotation.h
+// Created: 21 Apr 2015
+// Author: Artem ZHIDKOV
+
+#ifndef SketchPlugin_MultiRotation_H_
+#define SketchPlugin_MultiRotation_H_
+
+#include "SketchPlugin.h"
+#include <SketchPlugin_Sketch.h>
+#include "SketchPlugin_ConstraintBase.h"
+
+/** \class SketchPlugin_MultiRotation
+ * \ingroup Plugins
+ * \brief Feature for creation of a number of rotated copies of a list of objects
+ *
+ * This constraint has two attributes:
+ * SketchPlugin_Constraint::ENTITY_A() for initial list of objects and
+ * SketchPlugin_Constraint::ENTITY_B() for the list of created objects
+ *
+ * The list of created objects contains a number of copies of each object given in
+ * the NUMBER_OF_COPIES_ID() attribute plus 1 (the initial objects are stored into this
+ * attribute too). At the start of the list, there are collected N copies
+ * of first object from initial list, then N copies of second object etc.
+ */
+class SketchPlugin_MultiRotation : public SketchPlugin_ConstraintBase
+{
+ public:
+ /// Multi-rotation kind
+ inline static const std::string& ID()
+ {
+ static const std::string MY_CONSTRAINT_ROTATION_ID("SketchMultiRotation");
+ return MY_CONSTRAINT_ROTATION_ID;
+ }
+ /// \brief Returns the kind of a feature
+ SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = SketchPlugin_MultiRotation::ID();
+ return MY_KIND;
+ }
+
+ /// List of objects to be mirrored
+ inline static const std::string& ROTATION_LIST_ID()
+ {
+ static const std::string MY_ROTATION_LIST_ID("MultiRotationList");
+ return MY_ROTATION_LIST_ID;
+ }
+
+ /// Center of rotation
+ inline static const std::string& CENTER_ID()
+ {
+ static const std::string MY_CENTER_ID("MultiRotationCenter");
+ return MY_CENTER_ID;
+ }
+ /// End point of translation
+ inline static const std::string& ANGLE_ID()
+ {
+ static const std::string MY_ANGLE_ID("MultiRotationAngle");
+ return MY_ANGLE_ID;
+ }
+ /// Number of translated objects
+ inline static const std::string& NUMBER_OF_COPIES_ID()
+ {
+ static const std::string MY_NUMBER_OF_COPIES_ID("MultiRotationCopies");
+ return MY_NUMBER_OF_COPIES_ID;
+ }
+
+ /// \brief Creates a new part document if needed
+ SKETCHPLUGIN_EXPORT virtual void execute();
+
+ /// \brief Request for initialization of data model of the feature: adding all attributes
+ SKETCHPLUGIN_EXPORT virtual void initAttributes();
+
+ /// Returns the AIS preview
+ SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
+
+ /// \brief Use plugin manager for features creation
+ SketchPlugin_MultiRotation();
+
+private:
+ ObjectPtr copyFeature(ObjectPtr theObject);
+ void rotateFeature(ObjectPtr theInitial, ObjectPtr theTarget,
+ double theCenterX, double theCenterY, double theAngle);
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File: SketchPlugin_MultiTranslation.cpp
+// Created: 21 Apr 2015
+// Author: Artem ZHIDKOV
+
+#include "SketchPlugin_MultiTranslation.h"
+
+#include <GeomAPI_XY.h>
+#include <GeomDataAPI_Point2D.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_Events.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+
+#include <SketcherPrs_Factory.h>
+
+SketchPlugin_MultiTranslation::SketchPlugin_MultiTranslation()
+{
+}
+
+void SketchPlugin_MultiTranslation::initAttributes()
+{
+ data()->addAttribute(START_POINT_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(END_POINT_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(NUMBER_OF_COPIES_ID(), ModelAPI_AttributeInteger::typeId());
+ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefList::typeId());
+ data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefList::typeId());
+ AttributeSelectionListPtr aSelection =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
+ TRANSLATION_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
+ aSelection->setSelectionType("EDGE");
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_A());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_B());
+}
+
+void SketchPlugin_MultiTranslation::execute()
+{
+ AttributeSelectionListPtr aTranslationObjectRefs = selectionList(TRANSLATION_LIST_ID());
+ int aNbCopies = integer(NUMBER_OF_COPIES_ID())->value();
+
+ // Calculate shift vector
+ std::shared_ptr<GeomDataAPI_Point2D> aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ attribute(START_POINT_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ attribute(END_POINT_ID()));
+ if (!aStart || !aEnd || !aStart->isInitialized() || !aEnd->isInitialized())
+ return;
+
+ // make a visible points
+ SketchPlugin_Sketch::createPoint2DResult(this, sketch(), START_POINT_ID(), 0);
+ SketchPlugin_Sketch::createPoint2DResult(this, sketch(), END_POINT_ID(), 1);
+
+ std::shared_ptr<GeomAPI_XY> aShiftVec(new GeomAPI_XY(aEnd->x() - aStart->x(), aEnd->y() - aStart->y()));
+
+ // Wait all objects being created, then send update events
+ static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+ bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
+ if (isUpdateFlushed)
+ Events_Loop::loop()->setFlushed(anUpdateEvent, false);
+
+ std::shared_ptr<ModelAPI_Data> aData = data();
+ AttributeRefListPtr aRefListOfShapes = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ AttributeRefListPtr aRefListOfTranslated = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ int aCurrentNbCopies = aRefListOfShapes->size() ?
+ aRefListOfTranslated->size() / aRefListOfShapes->size() - 1 : 0;
+ std::list<ObjectPtr> anInitialList = aRefListOfShapes->list();
+ std::list<ObjectPtr> aTargetList = aRefListOfTranslated->list();
+ std::list<ResultPtr> anAddition;
+ std::vector<bool> isUsed(anInitialList.size(), false);
+ // collect new items and check the items to remove
+ for(int anInd = 0; anInd < aTranslationObjectRefs->size(); anInd++) {
+ std::shared_ptr<ModelAPI_AttributeSelection> aSelect = aTranslationObjectRefs->value(anInd);
+ std::list<ObjectPtr>::const_iterator anIt = anInitialList.begin();
+ std::vector<bool>::iterator aUsedIt = isUsed.begin();
+ for (; anIt != anInitialList.end(); anIt++, aUsedIt++)
+ if (*anIt == aSelect->context()) {
+ *aUsedIt = true;
+ break;
+ }
+ if (anIt == anInitialList.end())
+ anAddition.push_back(aSelect->context());
+ }
+ // remove unused items
+ std::list<ObjectPtr>::iterator anInitIter = anInitialList.begin();
+ std::list<ObjectPtr>::iterator aTargetIter = aTargetList.begin();
+ std::vector<bool>::iterator aUsedIter = isUsed.begin();
+ for (; aUsedIter != isUsed.end(); aUsedIter++) {
+ if (!(*aUsedIter)) {
+ aRefListOfShapes->remove(*anInitIter);
+ for (int i = 0; i < aCurrentNbCopies && aTargetIter != aTargetList.end(); i++, aTargetIter++) {
+ aRefListOfTranslated->remove(*aTargetIter);
+ // remove the corresponding feature from the sketch
+ ResultConstructionPtr aRC =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aTargetIter);
+ DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
+ FeaturePtr aFeature = aDoc ? aDoc->feature(aRC) : FeaturePtr();
+ if (aFeature)
+ aDoc->removeFeature(aFeature);
+ }
+ } else {
+ for (int i = 0; i <= aNbCopies && aTargetIter != aTargetList.end(); i++)
+ aTargetIter++;
+ }
+ if (anInitIter != anInitialList.end())
+ anInitIter++;
+ }
+ // change number of copies
+ if (aCurrentNbCopies != 0 && aNbCopies != aCurrentNbCopies) {
+ bool isAdd = aNbCopies > aCurrentNbCopies;
+ int aMinCopies = isAdd ? aCurrentNbCopies : aNbCopies;
+ int aMaxCopies = isAdd ? aNbCopies : aCurrentNbCopies;
+ int ind = 0;
+
+ aTargetList = aRefListOfTranslated->list();
+ aTargetIter = aTargetList.begin();
+ ObjectPtr anObjToCopy = *aTargetIter;
+ while (aTargetIter != aTargetList.end()) {
+ aRefListOfTranslated->remove(*aTargetIter);
+ aTargetIter++;
+ ind++;
+ if (ind > aMinCopies && ind <=aMaxCopies) {
+ while (ind <= aMaxCopies) {
+ if (isAdd) {
+ // Add new shifted item
+ ObjectPtr anObject = copyFeature(anObjToCopy);
+ aTargetList.insert(aTargetIter, anObject);
+ } else {
+ // remove object
+ std::list<ObjectPtr>::iterator aRemoveIt = aTargetIter++;
+ ObjectPtr anObject = *aRemoveIt;
+ aTargetList.erase(aRemoveIt);
+ aRefListOfTranslated->remove(anObject);
+ // remove the corresponding feature from the sketch
+ ResultConstructionPtr aRC =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(anObject);
+ DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
+ FeaturePtr aFeature = aDoc ? aDoc->feature(aRC) : FeaturePtr();
+ if (aFeature)
+ aDoc->removeFeature(aFeature);
+ }
+ ind++;
+ }
+ ind = 0;
+ if (aTargetIter != aTargetList.end())
+ anObjToCopy = *aTargetIter;
+ }
+ }
+
+ for (aTargetIter = aTargetList.begin(); aTargetIter != aTargetList.end(); aTargetIter++)
+ aRefListOfTranslated->append(*aTargetIter);
+ }
+ // add new items
+ std::list<ResultPtr>::iterator anAddIter = anAddition.begin();
+ for (; anAddIter != anAddition.end(); anAddIter++) {
+ aRefListOfShapes->append(*anAddIter);
+ aRefListOfTranslated->append(*anAddIter);
+ for (int i = 0; i < aNbCopies; i++) {
+ ObjectPtr anObject = copyFeature(*anAddIter);
+ aRefListOfTranslated->append(anObject);
+ }
+ }
+
+ // send events to update the sub-features by the solver
+ if (isUpdateFlushed)
+ Events_Loop::loop()->setFlushed(anUpdateEvent, true);
+}
+
+AISObjectPtr SketchPlugin_MultiTranslation::getAISObject(AISObjectPtr thePrevious)
+{
+ if (!sketch())
+ return thePrevious;
+
+ AISObjectPtr anAIS = thePrevious;
+ if (!anAIS) {
+ anAIS = SketcherPrs_Factory::translateConstraint(this, sketch()->coordinatePlane());
+ }
+ return anAIS;
+}
+
+ObjectPtr SketchPlugin_MultiTranslation::copyFeature(ObjectPtr theObject)
+{
+ ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theObject);
+ FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
+ if (!aFeature || !aResult)
+ return ObjectPtr();
+
+ FeaturePtr aNewFeature = sketch()->addFeature(aFeature->getKind());
+ aFeature->data()->copyTo(aNewFeature->data());
+ aNewFeature->execute();
+
+ static Events_ID aRedisplayEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ ModelAPI_EventCreator::get()->sendUpdated(aNewFeature, aRedisplayEvent);
+
+ std::shared_ptr<GeomAPI_Shape> aShapeIn = aResult->shape();
+ const std::list<ResultPtr>& aResults = aNewFeature->results();
+ std::list<ResultPtr>::const_iterator anIt = aResults.begin();
+ for (; anIt != aResults.end(); anIt++) {
+ ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anIt);
+ if (!aRC) continue;
+ std::shared_ptr<GeomAPI_Shape> aShapeOut = aRC->shape();
+ if ((aShapeIn->isVertex() && aShapeOut->isVertex()) ||
+ (aShapeIn->isEdge() && aShapeOut->isEdge()) ||
+ (aShapeIn->isFace() && aShapeOut->isFace()))
+ return aRC;
+ }
+ return ObjectPtr();
+}
+
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File: SketchPlugin_MultiTranslation.h
+// Created: 21 Apr 2015
+// Author: Artem ZHIDKOV
+
+#ifndef SketchPlugin_MultiTranslation_H_
+#define SketchPlugin_MultiTranslation_H_
+
+#include "SketchPlugin.h"
+#include <SketchPlugin_Sketch.h>
+#include "SketchPlugin_ConstraintBase.h"
+
+/** \class SketchPlugin_MultiTranslation
+ * \ingroup Plugins
+ * \brief Feature for creation of a number of shifted copies of a list of objects
+ *
+ * This constraint has two attributes:
+ * SketchPlugin_Constraint::ENTITY_A() for initial list of objects and
+ * SketchPlugin_Constraint::ENTITY_B() for the list of created objects
+ *
+ * The list of created objects contains a number of copies of each object given in
+ * the NUMBER_OF_COPIES_ID() attribute plus 1 (the initial objects are stored into this
+ * attribute too). At the start of the list, there are collected N copies
+ * of first object from initial list, then N copies of second object etc.
+ */
+class SketchPlugin_MultiTranslation : public SketchPlugin_ConstraintBase
+{
+ public:
+ /// Multi-translation kind
+ inline static const std::string& ID()
+ {
+ static const std::string MY_CONSTRAINT_TRANSLATION_ID("SketchMultiTranslation");
+ return MY_CONSTRAINT_TRANSLATION_ID;
+ }
+ /// \brief Returns the kind of a feature
+ SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = SketchPlugin_MultiTranslation::ID();
+ return MY_KIND;
+ }
+
+ /// List of objects to be mirrored
+ inline static const std::string& TRANSLATION_LIST_ID()
+ {
+ static const std::string MY_TRANSLATION_LIST_ID("MultiTranslationList");
+ return MY_TRANSLATION_LIST_ID;
+ }
+
+ /// Start point of translation
+ inline static const std::string& START_POINT_ID()
+ {
+ static const std::string MY_START_POINT_ID("MultiTranslationStartPoint");
+ return MY_START_POINT_ID;
+ }
+ /// End point of translation
+ inline static const std::string& END_POINT_ID()
+ {
+ static const std::string MY_END_POINT_ID("MultiTranslationEndPoint");
+ return MY_END_POINT_ID;
+ }
+ /// Number of translated objects
+ inline static const std::string& NUMBER_OF_COPIES_ID()
+ {
+ static const std::string MY_NUMBER_OF_COPIES_ID("MultiTranslationCopies");
+ return MY_NUMBER_OF_COPIES_ID;
+ }
+
+ /// \brief Creates a new part document if needed
+ SKETCHPLUGIN_EXPORT virtual void execute();
+
+ /// \brief Request for initialization of data model of the feature: adding all attributes
+ SKETCHPLUGIN_EXPORT virtual void initAttributes();
+
+ /// Returns the AIS preview
+ SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
+
+ /// \brief Use plugin manager for features creation
+ SketchPlugin_MultiTranslation();
+
+private:
+ ObjectPtr copyFeature(ObjectPtr theObject);
+};
+
+#endif
#include <SketchPlugin_ConstraintRigid.h>
#include <SketchPlugin_ConstraintTangent.h>
#include <SketchPlugin_ConstraintVertical.h>
+#include <SketchPlugin_MultiRotation.h>
+#include <SketchPlugin_MultiTranslation.h>
#include <SketchPlugin_Validators.h>
#include <SketchPlugin_ExternalValidator.h>
new SketchPlugin_EqualAttrValidator);
aFactory->registerValidator("SketchPlugin_MirrorAttr",
new SketchPlugin_MirrorAttrValidator);
+ aFactory->registerValidator("SketchPlugin_CoincidenceAttr",
+ new SketchPlugin_CoincidenceAttrValidator);
+ aFactory->registerValidator("SketchPlugin_CopyValidator",
+ new SketchPlugin_CopyValidator);
// register this plugin
ModelAPI_Session::get()->registerPlugin(this);
return FeaturePtr(new SketchPlugin_ConstraintMirror);
} else if (theFeatureID == SketchPlugin_ConstraintFillet::ID()) {
return FeaturePtr(new SketchPlugin_ConstraintFillet);
+ } else if (theFeatureID == SketchPlugin_MultiTranslation::ID()) {
+ return FeaturePtr(new SketchPlugin_MultiTranslation);
+ } else if (theFeatureID == SketchPlugin_MultiRotation::ID()) {
+ return FeaturePtr(new SketchPlugin_MultiRotation);
}
// feature of such kind is not found
return FeaturePtr();
#include <GeomAlgoAPI_FaceBuilder.h>
+#include <GeomDataAPI_Point2D.h>
+#include <GeomAlgoAPI_PointBuilder.h>
+
#include <ModelAPI_AttributeRefList.h>
#include <ModelAPI_Data.h>
#include <ModelAPI_Document.h>
#include <ModelAPI_ResultConstruction.h>
#include <ModelAPI_Validator.h>
#include <ModelAPI_Session.h>
+#include <ModelAPI_Events.h>
#include <SketchPlugin_Sketch.h>
#include <SketchPlugin_Feature.h>
#include <SketchPlugin_SketchEntity.h>
+#include <Events_Loop.h>
+
#include <memory>
#include <math.h>
std::shared_ptr<ModelAPI_Feature> SketchPlugin_Sketch::addFeature(std::string theID)
{
- std::shared_ptr<ModelAPI_Feature> aNew = document()->addFeature(theID);
+ std::shared_ptr<ModelAPI_Feature> aNew = document()->addFeature(theID, false);
if (aNew) {
std::dynamic_pointer_cast<SketchPlugin_Feature>(aNew)->setSketch(this);
data()->reflist(SketchPlugin_Sketch::FEATURES_ID())->append(aNew);
}
+ // set as current also after it becomes sub to set correctly enabled for other sketch subs
+ document()->setCurrentFeature(aNew, false);
return aNew;
}
std::shared_ptr<GeomAPI_Dir> aDir = aPlane->direction();
}
}
+ } else if (theID == SketchPlugin_Sketch::NORM_ID() || theID == SketchPlugin_Sketch::DIRX_ID()) {
+ // send all sub-elements are also updated: all entities become created on different plane
+ static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+ std::list<ObjectPtr> aSubs = data()->reflist(SketchPlugin_Sketch::FEATURES_ID())->list();
+ std::list<ObjectPtr>::iterator aSub = aSubs.begin();
+ for(; aSub != aSubs.end(); aSub++) {
+ ModelAPI_EventCreator::get()->sendUpdated(*aSub, anUpdateEvent);
+ }
}
}
+
+void SketchPlugin_Sketch::createPoint2DResult(ModelAPI_Feature* theFeature,
+ SketchPlugin_Sketch* theSketch,
+ const std::string& theAttributeID, const int theIndex)
+{
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(theAttributeID));
+
+ if (!aPoint || !aPoint->isInitialized())
+ return;
+
+ std::shared_ptr<GeomAPI_Pnt> aCenter(theSketch->to3D(aPoint->x(), aPoint->y()));
+ //std::cout<<"Execute circle "<<aCenter->x()<<" "<<aCenter->y()<<" "<<aCenter->z()<<std::endl;
+ // make a visible point
+ std::shared_ptr<GeomAPI_Shape> aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter);
+ std::shared_ptr<ModelAPI_ResultConstruction> aResult = theFeature->document()->createConstruction(
+ theFeature->data(), theIndex);
+ aResult->setShape(aCenterPointShape);
+ aResult->setIsInHistory(false);
+
+ theFeature->setResult(aResult, theIndex);
+}
#include <GeomAPI_Pnt.h>
#include <GeomAPI_Pln.h>
#include <GeomAPI_IPresentable.h>
+#include <GeomAPI_ICustomPrs.h>
+
#include <GeomAPI_Ax3.h>
#include <GeomAPI_XYZ.h>
#include <GeomDataAPI_Point.h>
#include <GeomDataAPI_Dir.h>
#include <list>
-#define YZ_PLANE_COLOR "#ff0000"
-#define XZ_PLANE_COLOR "#00ff00"
-#define XY_PLANE_COLOR "#0000ff"
+#define YZ_PLANE_COLOR "225,0,0"
+#define XZ_PLANE_COLOR "0,225,0"
+#define XY_PLANE_COLOR "0,0,225"
/**\class SketchPlugin_Sketch
* \ingroup Plugins
* \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_ICustomPrs//, public GeomAPI_IPresentable
{
public:
/// Sketch feature kind
SKETCHPLUGIN_EXPORT virtual bool isPersistentResult() {return false;}
SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+ /// \brief Create a result for the point in the attribute if the attribute is initialized
+ /// \param theAttributeID an attribute string
+ /// \param theIndex an index of the result
+ static void createPoint2DResult(ModelAPI_Feature* theFeature,
+ SketchPlugin_Sketch* theSketch,
+ const std::string& theAttributeID, const int theIndex);
+ /// Customize presentation of the feature
+ virtual bool customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
+ std::shared_ptr<GeomAPI_ICustomPrs> theDefaultPrs)
+ {
+ bool isCustomized = false;
+ // apply the color of the result to the presentation
+ if (theDefaultPrs.get())
+ isCustomized = theDefaultPrs->customisePresentation(theResult, thePrs, theDefaultPrs);
+ // set the sketch presentation bold
+ isCustomized = thePrs->setWidth(2) || isCustomized;
+
+ return isCustomized;
+ }
+
};
#endif
#include <Config_PropManager.h>
-#define SKETCH_ENTITY_COLOR "#ff0000"
-#define SKETCH_EXTERNAL_COLOR "#00ff00"
-#define SKETCH_AUXILIARY_COLOR "#000000"
+#define SKETCH_ENTITY_COLOR "225,0,0"
+#define SKETCH_EXTERNAL_COLOR "170,0,225"
+#define SKETCH_AUXILIARY_COLOR "0,85,0"
/**\class SketchPlugin_SketchEntity
* \ingroup Plugins
#include "SketchPlugin_Line.h"
#include "SketchPlugin_Arc.h"
#include "SketchPlugin_Circle.h"
+#include "SketchPlugin_Point.h"
#include "SketcherPrs_Tools.h"
#include <ModelAPI_AttributeSelectionList.h>
#include <ModelAPI_Session.h>
-#include <GeomValidators_Edge.h>
+#include <GeomValidators_ShapeType.h>
#include <GeomDataAPI_Point2D.h>
// 1. check whether the references object is a linear
ObjectPtr anObject = aRefAttr->object();
- const ModelAPI_AttributeValidator* anEdgeValidator =
- dynamic_cast<const GeomValidators_Edge*>(aFactory->validator("GeomValidators_Edge"));
+ const ModelAPI_AttributeValidator* aShapeValidator =
+ dynamic_cast<const GeomValidators_ShapeType*>(aFactory->validator("GeomValidators_ShapeType"));
std::list<std::string> anArguments;
anArguments.push_back("circle");
- bool anEdgeValid = anEdgeValidator->isValid(aRefAttr, anArguments);
+ bool aShapeValid = aShapeValidator->isValid(aRefAttr, anArguments);
// the circle line is not a valid case
- if (anEdgeValid)
+ if (aShapeValid)
return false;
anArguments.clear();
anArguments.push_back("line");
- anEdgeValid = anEdgeValidator->isValid(aRefAttr, anArguments);
+ aShapeValid = aShapeValidator->isValid(aRefAttr, anArguments);
// if the attribute value is not a line, that means it is a vertex. A vertex is always valid
- if (!anEdgeValid)
+ if (!aShapeValid)
return true;
FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
return true;
}
+
+bool SketchPlugin_CoincidenceAttrValidator::isValid(
+ const AttributePtr& theAttribute, const std::list<std::string>& theArguments ) const
+{
+ // there is a check whether the feature contains a point and a linear edge or two point values
+ std::string aParamA = theArguments.front();
+ SessionPtr aMgr = ModelAPI_Session::get();
+ ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
+
+ FeaturePtr aConstraint = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+ AttributeRefAttrPtr aRefAttrA = aConstraint->data()->refattr(aParamA);
+ if (!aRefAttrA)
+ return false;
+
+ AttributeRefAttrPtr aRefAttrB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
+ if (!aRefAttrB)
+ return false;
+
+ // first attribute is a point, it may coincide with any object
+ if (!aRefAttrA->isObject())
+ return true;
+ else {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttrA->object());
+ if (!aFeature)
+ return false;
+ if (aFeature->getKind() == SketchPlugin_Point::ID())
+ return true;
+ }
+
+ // second attribute is a point, it may coincide with any object
+ if (!aRefAttrB->isObject())
+ return true;
+ else {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttrB->object());
+ if (!aFeature)
+ return false;
+ if (aFeature->getKind() == SketchPlugin_Point::ID())
+ return true;
+ }
+
+ return false;
+}
+
+
+bool SketchPlugin_CopyValidator::isValid(
+ const AttributePtr& theAttribute, const std::list<std::string>& theArguments ) const
+{
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+ AttributeSelectionListPtr aSelAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+ if (!aSelAttr)
+ return false;
+
+ AttributeRefListPtr aRefListOfInitial = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ aFeature->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ AttributeRefListPtr aRefListOfCopied = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ aFeature->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ std::list<ObjectPtr> anInitialObjects = aRefListOfInitial->list();
+ std::list<ObjectPtr> aCopiedObjects = aRefListOfCopied->list();
+
+ std::list<ObjectPtr>::iterator anObjIter;
+ for(int anInd = 0; anInd < aSelAttr->size(); anInd++) {
+ std::shared_ptr<ModelAPI_AttributeSelection> aSelect = aSelAttr->value(anInd);
+ anObjIter = anInitialObjects.begin();
+ for (; anObjIter != anInitialObjects.end(); anObjIter++)
+ if (aSelect->context() == *anObjIter)
+ break;
+ if (anObjIter != anInitialObjects.end())
+ continue;
+ anObjIter = aCopiedObjects.begin();
+ for (; anObjIter != aCopiedObjects.end(); anObjIter++)
+ if (aSelect->context() == *anObjIter)
+ return false;
+ }
+ return true;
+}
+
};
+/**\class SketchPlugin_CoincidenceAttrValidator
+ * \ingroup Validators
+ * \brief Validator for the coincidence constraint input.
+ *
+ * It checks that attributes of the Coincidence constraint are correct.
+ */
+class SketchPlugin_CoincidenceAttrValidator : public ModelAPI_AttributeValidator
+{
+ public:
+ //! returns true if attribute is valid
+ //! \param theAttribute the checked attribute
+ //! \param theArguments arguments of the attribute (not used)
+ virtual bool isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments) const;
+};
+
+
+/**\class SketchPlugin_CopyValidator
+ * \ingroup Validators
+ * \brief Validator for the constraints which create features.
+ *
+ * Applicable only for features, which creates another features. It verifies the produced
+ * features of current constraint don't become into the list of initial features
+ */
+class SketchPlugin_CopyValidator : public ModelAPI_AttributeValidator
+{
+ public:
+ //! returns true if attribute is valid
+ //! \param theAttribute the checked attribute
+ //! \param theArguments arguments of the attribute (not used)
+ virtual bool isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments) const;
+};
+
#endif
<group id="Basic">
<feature
id="Sketch"
- nested="SketchPoint SketchLine SketchCircle SketchArc SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintParallel SketchConstraintPerpendicular SketchConstraintRigid SketchConstraintHorizontal SketchConstraintVertical SketchConstraintEqual SketchConstraintTangent SketchConstraintFillet SketchConstraintCoincidence SketchConstraintMirror"
+ nested="SketchPoint SketchLine SketchCircle SketchArc SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintParallel SketchConstraintPerpendicular SketchConstraintRigid SketchConstraintHorizontal SketchConstraintVertical SketchConstraintEqual SketchConstraintTangent SketchConstraintFillet SketchConstraintCoincidence SketchConstraintMirror SketchMultiRotation SketchMultiTranslation"
when_nested="accept abort"
title="Sketch"
tooltip="Create sketch"
shape_types="edge vertex">
<validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
<validator id="PartSet_DifferentObjects"/>
- <validator id="GeomValidators_EdgeOrVertex"/>
+ <validator id="GeomValidators_ShapeType" parameters="vertex,line"/>
</sketch_shape_selector>/>
<sketch_shape_selector
id="ConstraintEntityB"
<validator id="PartSet_DifferentObjects"/>
<validator id="SketchPlugin_DistanceAttr" parameters="ConstraintEntityA"/>
<validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
- <validator id="GeomValidators_EdgeOrVertex"/>
+ <validator id="GeomValidators_ShapeType" parameters="vertex,line"/>
</sketch_shape_selector>
<sketch-2dpoint_selector id="ConstraintFlyoutValuePnt" default="computed" internal="1" obligatory="0"/>
<label title="Select a line on which to calculate length" tooltip="Select a line on which to calculate length"/>
<shape_selector id="ConstraintEntityA" label="Line" tooltip="Select an line"
shape_types="edge" >
- <validator id="GeomValidators_Edge" parameters="line"/>
+ <validator id="GeomValidators_ShapeType" parameters="line"/>
</shape_selector>
<sketch-2dpoint_selector id="ConstraintFlyoutValuePnt" default="computed" internal="1" obligatory="0"/>
<doublevalue_editor label="Value" tooltip="Length" id="ConstraintValue" default="computed">
<label title="Select a circle or an arc on which to calculate radius" tooltip="Select a circle or an arc on which to calculate radius"/>
<shape_selector id="ConstraintEntityA" label="Circle or Arc" tooltip="Select a circle or an arc"
shape_types="edge">
- <validator id="GeomValidators_Edge" parameters="circle"/>
+ <validator id="GeomValidators_ShapeType" parameters="circle"/>
</shape_selector>
<sketch-2dpoint_selector id="ConstraintFlyoutValuePnt" default="computed" internal="1" obligatory="0"/>
<doublevalue_editor label="Value" tooltip="Radius" id="ConstraintValue" default="computed"/>
<feature id="SketchConstraintParallel" title="Parallel" tooltip="Create constraint defining two parallel lines" icon=":icons/parallel.png">
<sketch_shape_selector id="ConstraintEntityA"
label="First line" tooltip="Select a line" shape_types="edge">
- <validator id="GeomValidators_Edge" parameters="line"/>
+ <validator id="GeomValidators_ShapeType" parameters="line"/>
<validator id="PartSet_DifferentObjects"/>
<validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
</sketch_shape_selector>
<sketch_shape_selector id="ConstraintEntityB" label="Second line" tooltip="Select a line"
shape_types="edge">
- <validator id="GeomValidators_Edge" parameters="line"/>
+ <validator id="GeomValidators_ShapeType" parameters="line"/>
<validator id="PartSet_DifferentObjects"/>
<validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
</sketch_shape_selector>
shape_types="edge">
<validator id="PartSet_DifferentObjects"/>
<validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
- <validator id="GeomValidators_Edge" parameters="line"/>
+ <validator id="GeomValidators_ShapeType" parameters="line"/>
</sketch_shape_selector>
<sketch_shape_selector id="ConstraintEntityB"
shape_types="edge">
<validator id="PartSet_DifferentObjects"/>
<validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
- <validator id="GeomValidators_Edge" parameters="line"/>
+ <validator id="GeomValidators_ShapeType" parameters="line"/>
</sketch_shape_selector>
<validator id="PartSet_PerpendicularSelection"/>
</feature>
<!-- SketchConstraintCoincedence -->
- <feature id="SketchConstraintCoincidence" title="Coincident" tooltip="Create constraint for the coincidence of two points" icon=":icons/coincedence.png">
- <sketch_shape_selector id="ConstraintEntityA" label="First point" tooltip="Select a first point" shape_types="vertex">
+ <feature id="SketchConstraintCoincidence" title="Coincident" tooltip="Create constraint for the coincidence of two points or point on line or circle" icon=":icons/coincedence.png">
+ <sketch_shape_selector id="ConstraintEntityA" label="First object" tooltip="Select a first object" shape_types="vertex edge">
<validator id="PartSet_DifferentObjects"/>
<validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
</sketch_shape_selector>
- <sketch_shape_selector id="ConstraintEntityB" label="Second point" tooltip="Select a second point" shape_types="vertex">
+ <sketch_shape_selector id="ConstraintEntityB" label="Second object" tooltip="Select a second object" shape_types="vertex edge">
<validator id="PartSet_DifferentObjects"/>
<validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
+ <validator id="SketchPlugin_CoincidenceAttr" parameters="ConstraintEntityA"/>
</sketch_shape_selector>
<validator id="PartSet_CoincidentSelection"/>
</feature>
<!-- SketchConstraintRigid -->
<feature id="SketchConstraintRigid" title="Fixed" tooltip="Fix an object" icon=":icons/fixed.png">
- <shape_selector id="ConstraintEntityA" label="Object" tooltip="Select an object"
- shape_types="edge vertex">
- <validator id="PartSet_SketchEntityValidator" parameters="SketchPoint,SketchLine,SketchCircle,SketchArc"/>
+ <sketch_shape_selector id="ConstraintEntityA" label="Object"
+ tooltip="Select point, line end point, line, center of circle or arc."
+ shape_types="edge vertex">
+ <validator id="GeomValidators_ShapeType" parameters="vertex,line,circle"/>
<validator id="SketchPlugin_NotFixed"/>
- </shape_selector>
+ </sketch_shape_selector>
<validator id="PartSet_RigidSelection"/>
</feature>
-
- <!-- SketchConstraintHorizontal -->
+
+ <!-- SketchConstraintHorizontal -->
<feature id="SketchConstraintHorizontal" title="Horizontal" tooltip="Create constraint defining horizontal line" icon=":icons/horisontal.png">
<sketch_shape_selector id="ConstraintEntityA"
label="Line" tooltip="Select a line" shape_types="edge" use_external="false">
- <validator id="GeomValidators_Edge" parameters="line"/>
+ <validator id="GeomValidators_ShapeType" parameters="line"/>
</sketch_shape_selector>
<validator id="PartSet_HVDirSelection"/>
</feature>
<feature id="SketchConstraintVertical" title="Vertical" tooltip="Create constraint defining vertical line" icon=":icons/vertical.png">
<sketch_shape_selector id="ConstraintEntityA"
label="Line" tooltip="Select a line" shape_types="edge" use_external="false">
- <validator id="GeomValidators_Edge" parameters="line"/>
+ <validator id="GeomValidators_ShapeType" parameters="line"/>
</sketch_shape_selector>
<validator id="PartSet_HVDirSelection"/>
</feature>
tooltip="Create constraint, mirroring group of objects">
<sketch_shape_selector id="ConstraintEntityA"
label="Mirror line" tooltip="Select mirror line" shape_types="edge">
- <validator id="GeomValidators_Edge" parameters="line"/>
+ <validator id="GeomValidators_ShapeType" parameters="line"/>
</sketch_shape_selector>
<sketch_multi_selector id="ConstraintMirrorList"
label="List of objects"
<validator id="SketchPlugin_MirrorAttr" />
</sketch_multi_selector>
</feature>
+ <!-- SketchMultiTranslation -->
+ <feature
+ id="SketchMultiTranslation"
+ title="Translation" icon=":icons/translate.png"
+ tooltip="Make a number of shifted copies of a group of objects">
+ <sketch_multi_selector id="MultiTranslationList"
+ label="List of objects"
+ tooltip="Select list of translating objects"
+ type_choice="Edges"
+ use_external="true">
+ <validator id="SketchPlugin_CopyValidator" />
+ </sketch_multi_selector>
+ <groupbox title="Direction">
+ <sketch-2dpoint_selector
+ id="MultiTranslationStartPoint"
+ title="Start point"
+ tooltip="Start point of translation"/>
+ <sketch-2dpoint_selector
+ id="MultiTranslationEndPoint"
+ title="End point"
+ tooltip="Final point of translation"/>
+ </groupbox>
+ <integervalue id="MultiTranslationCopies"
+ label="Number of copies"
+ tooltip="Number of copies"
+ default="1" min="1">
+ <validator id="GeomValidators_Positive"/>
+ </integervalue>
+ </feature>
+ <!-- SketchMultiRotation -->
+ <feature
+ id="SketchMultiRotation"
+ title="Rotation" icon=":icons/rotate.png"
+ tooltip="Make a number of rotated copies of a group of objects">
+ <sketch_multi_selector id="MultiRotationList"
+ label="List of objects"
+ tooltip="Select list of rotating objects"
+ type_choice="Edges"
+ use_external="true">
+ <validator id="SketchPlugin_CopyValidator" />
+ </sketch_multi_selector>
+ <sketch-2dpoint_selector
+ id="MultiRotationCenter"
+ title="Center of rotation"
+ tooltip="Center of rotation"/>
+ <point2dangle id="MultiRotationAngle"
+ first_point="MultiRotationCenter"
+ label="Angle"
+ icon=":icons/angle.png"
+ tooltip="Rotation angle"
+ default="90"/>
+ <integervalue id="MultiRotationCopies"
+ label="Number of copies"
+ tooltip="Number of copies"
+ default="1" min="1">
+ <validator id="GeomValidators_Positive"/>
+ </integervalue>
+ </feature>
</group>
</workbench>
</plugin>
SketchSolver_ConstraintMirror.h
SketchSolver_ConstraintRigid.h
SketchSolver_ConstraintTangent.h
+ SketchSolver_ConstraintMultiRotation.h
+ SketchSolver_ConstraintMultiTranslation.h
SketchSolver_Builder.h
SketchSolver_Group.h
SketchSolver_ConstraintManager.h
SketchSolver_ConstraintMirror.cpp
SketchSolver_ConstraintRigid.cpp
SketchSolver_ConstraintTangent.cpp
+ SketchSolver_ConstraintMultiRotation.cpp
+ SketchSolver_ConstraintMultiTranslation.cpp
SketchSolver_Builder.cpp
SketchSolver_Group.cpp
SketchSolver_ConstraintManager.cpp
/// Tolerance for value of parameters
const double tolerance = 1.e-10;
+#define PI 3.1415926535897932
+
#endif
#include <SketchSolver_ConstraintMirror.h>
#include <SketchSolver_ConstraintRigid.h>
#include <SketchSolver_ConstraintTangent.h>
+#include <SketchSolver_ConstraintMultiRotation.h>
+#include <SketchSolver_ConstraintMultiTranslation.h>
#include <SketchSolver_Error.h>
#include <GeomAPI_Edge.h>
#include <SketchPlugin_ConstraintRigid.h>
#include <SketchPlugin_ConstraintTangent.h>
#include <SketchPlugin_ConstraintVertical.h>
+#include <SketchPlugin_MultiRotation.h>
+#include <SketchPlugin_MultiTranslation.h>
#include <math.h>
return SolverConstraintPtr(new SketchSolver_ConstraintVertical(theConstraint));
} else if (theConstraint->getKind() == SketchPlugin_ConstraintRigid::ID()) {
return SolverConstraintPtr(new SketchSolver_ConstraintRigid(theConstraint));
+ } else if (theConstraint->getKind() == SketchPlugin_MultiTranslation::ID()) {
+ return SolverConstraintPtr(new SketchSolver_ConstraintMultiTranslation(theConstraint));
+ } else if (theConstraint->getKind() == SketchPlugin_MultiRotation::ID()) {
+ return SolverConstraintPtr(new SketchSolver_ConstraintMultiRotation(theConstraint));
}
return aResult;
}
#include <SketchPlugin_Line.h>
#include <SketchPlugin_Point.h>
+#include <GeomAPI_Dir2d.h>
#include <GeomDataAPI_Point.h>
#include <GeomDataAPI_Point2D.h>
#include <ModelAPI_AttributeDouble.h>
getAttributes(aValue, anAttributes);
if (!myErrorMsg.empty())
return;
+ if (aConstrType == SLVS_C_UNKNOWN)
+ aConstrType = getType();
Slvs_hGroup aGroupID = myGroup->getId();
Slvs_hEntity aWorkplaneID = myGroup->getWorkplaneId();
return;
}
- double xStart = anArcPoint[1][0] / aRad, xEnd = anArcPoint[2][0] / aRad;
- double yStart = anArcPoint[1][1] / aRad, yEnd = anArcPoint[2][1] / aRad;
- double aTanStart = abs(xStart) < tolerance ? yStart : yStart / xStart;
- double aTanEnd = abs(xEnd) < tolerance ? yEnd : yEnd / xEnd;
- double aCotStart = abs(yStart) < tolerance ? xStart : xStart / yStart;
- double aCotEnd = abs(yEnd) < tolerance ? xEnd : xEnd / yEnd;
- if (anArcPoint[1][0] * anArcPoint[2][0] < 0.0) {
- if (anArcPoint[1][0] > 0.0)
- yEnd = 2.0 - yEnd;
- else
- yStart = -2.0 - yStart;
- } else {
- if (aTanStart > aTanEnd) {
- if (yStart > yEnd) {
- yStart = 2.0 - yStart;
- yEnd = -2.0 - yEnd;
- } else {
- yStart = -2.0 - yStart;
- yEnd = 2.0 - yEnd;
- }
- }
- }
- if (anArcPoint[1][1] * anArcPoint[2][1] < 0.0) {
- if (anArcPoint[1][1] > 0.0)
- xEnd = 2.0 - xEnd;
- else
- xStart = -2.0 - xStart;
- } else {
- if (aCotStart < aCotEnd) {
- if (xStart > xEnd) {
- xStart = 2.0 - xStart;
- xEnd = -2.0 - xEnd;
- } else {
- xStart = -2.0 - xStart;
- xEnd = 2.0 - xEnd;
- }
- }
- }
- x = (1.0 - theCoeff) * xStart + theCoeff * xEnd;
- y = (1.0 - theCoeff) * yStart + theCoeff * yEnd;
- if (x > 1.0) x = 2.0 - x;
- if (x < -1.0) x = -2.0 - x;
- if (y > 1.0) y = 2.0 - y;
- if (y < -1.0) y = -2.0 - y;
-
- aNorm = sqrt(x*x + y*y);
- if (aNorm >= tolerance) {
- x *= aRad / aNorm;
- y *= aRad / aNorm;
- } else {
- x = -0.5 * (anArcPoint[2][1] + anArcPoint[1][1]);
- y = -0.5 * (anArcPoint[2][0] + anArcPoint[1][0]);
- }
- theX = anArcPoint[0][0] + x;
- theY = anArcPoint[0][1] + y;
+ std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1]));
+ std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1]));
+ double anAngle = aStartDir->angle(aEndDir);
+ if (anAngle < 0)
+ anAngle += 2.0 * PI;
+ anAngle *= theCoeff;
+ double aCos = cos(anAngle);
+ double aSin = sin(anAngle);
+ theX = anArcPoint[0][0] + anArcPoint[1][0] * aCos - anArcPoint[1][1] * aSin;
+ theY = anArcPoint[0][1] + anArcPoint[1][0] * aSin + anArcPoint[1][1] * aCos;
}
}
#include <map>
+void SketchSolver_ConstraintCoincidence::getAttributes(
+ double& theValue,
+ std::vector<Slvs_hEntity>& theAttributes)
+{
+ SketchSolver_Constraint::getAttributes(theValue, theAttributes);
+ if (!myErrorMsg.empty() || theAttributes[0] == SLVS_E_UNKNOWN)
+ return;
+
+ if (theAttributes[1] != SLVS_E_UNKNOWN)
+ myType = SLVS_C_POINTS_COINCIDENT;
+ else if (theAttributes[2] != SLVS_E_UNKNOWN) {
+ // check the type of entity (line or circle)
+ Slvs_Entity anEnt = myStorage->getEntity(theAttributes[2]);
+ if (anEnt.type == SLVS_E_LINE_SEGMENT)
+ myType = SLVS_C_PT_ON_LINE;
+ else if (anEnt.type == SLVS_E_CIRCLE || anEnt.type == SLVS_E_ARC_OF_CIRCLE)
+ myType = SLVS_C_PT_ON_CIRCLE;
+ else
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ } else
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+}
+
+
bool SketchSolver_ConstraintCoincidence::hasConstraint(ConstraintPtr theConstraint) const
{
if (myBaseConstraint == theConstraint)
bool SketchSolver_ConstraintCoincidence::isCoincide(
std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint) const
{
+ // Multi-coincidence allowed for two points only
+ if (getType() != theConstraint->getType() || getType() != SLVS_C_POINTS_COINCIDENT)
+ return false;
+
std::set<AttributePtr>::const_iterator anAttrIter = theConstraint->myCoincidentPoints.begin();
for (; anAttrIter != theConstraint->myCoincidentPoints.end(); anAttrIter++)
if (myCoincidentPoints.find(*anAttrIter) != myCoincidentPoints.end())
{
public:
SketchSolver_ConstraintCoincidence(ConstraintPtr theConstraint) :
- SketchSolver_Constraint(theConstraint)
+ SketchSolver_Constraint(theConstraint),
+ myType(SLVS_C_UNKNOWN)
{}
virtual int getType() const
- { return SLVS_C_POINTS_COINCIDENT; }
+ { return myType; }
/// \brief Tries to remove constraint
/// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
/// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
virtual void process();
+ /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
+ /// \param[out] theValue numerical characteristic of constraint (e.g. distance)
+ /// \param[out] theAttributes list of attributes to be filled
+ virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes);
+
private:
/// \brief Creates new coincidence constraint
Slvs_hConstraint addConstraint(Slvs_hEntity thePoint1, Slvs_hEntity thePoint2);
void addConstraint(ConstraintPtr theConstraint);
private:
+ int myType; ///< type of constraint (applicable SLVS_C_POINTS_COINCIDENT or SLVS_C_PT_ON_LINE or SLVS_C_PT_ON_CIRCLE)
std::map<Slvs_hConstraint, ConstraintPtr> myExtraCoincidence; ///< multiple coincidence of points
std::set<AttributePtr> myCoincidentPoints; ///< list of points under the Coincidence constraint
};
#include <GeomAPI_Dir2d.h>
#include <GeomAPI_XY.h>
+#include <cmath>
void SketchSolver_ConstraintMirror::getAttributes(
Slvs_Entity& theMirrorLine,
}
}
}
-
- // Set the mirror line unchanged during constraint recalculation
- for (int i = 0; i < 2; i++) {
- if (myStorage->isPointFixed(aMirrorLine.point[i], aConstraint.h, true))
- continue;
- aConstraint = Slvs_MakeConstraint(
- SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
- aMirrorLine.point[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
- aConstraint.h = myStorage->addConstraint(aConstraint);
- mySlvsConstraints.push_back(aConstraint.h);
- }
}
Slvs_hEntity aTmp = aMirrorPoint[2];
aMirrorPoint[2] = aMirrorPoint[1];
aMirrorPoint[1] = aTmp;
+ adjustArcPoints(theBase);
}
if (theBase.type == SLVS_E_POINT_IN_2D || theBase.type == SLVS_E_POINT_IN_3D) {
aBasePoint[0] = theBase.h;
// orthogonal direction
aDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aDir->y(), -aDir->x()));
+ Slvs_hConstraint aFixed; // transient variable
for (int i = 0; i < 4; i++) {
if (aBasePoint[i] == SLVS_E_UNKNOWN || aMirrorPoint[i] == SLVS_E_UNKNOWN)
continue;
+ // check the mirror point is not fixed
+ if (myStorage->isPointFixed(aMirrorPoint[i], aFixed, true))
+ continue;
+
Slvs_Entity aPointEnt = myStorage->getEntity(aBasePoint[i]);
double aBaseX = myStorage->getParameter(aPointEnt.param[0]).val;
double aBaseY = myStorage->getParameter(aPointEnt.param[1]).val;
}
}
-void SketchSolver_ConstraintMirror::adjustConstraint()
+void SketchSolver_ConstraintMirror::adjustArcPoints(const Slvs_Entity& theArc) const
{
- // Search mirror between middle points on the arcs and recompute their coordinates
- std::list<Slvs_Constraint> aPonCirc = myStorage->getConstraintsByType(SLVS_C_PT_ON_CIRCLE);
- if (aPonCirc.empty())
- return;
+ Slvs_Param aParam;
+ Slvs_Entity aPoint;
+ double anArcParams[3][2];
+ for (int i = 0; i < 3; i++) {
+ aPoint = myStorage->getEntity(theArc.point[i]);
+ for (int j = 0; j < 2; j++) {
+ aParam = myStorage->getParameter(aPoint.param[j]);
+ anArcParams[i][j] = aParam.val;
+ if (i > 0)
+ anArcParams[i][j] -= anArcParams[0][j];
+ }
+ }
+ double aRad2 = anArcParams[1][0] * anArcParams[1][0] + anArcParams[1][1] * anArcParams[1][1];
+ double aDist2 = anArcParams[2][0] * anArcParams[2][0] + anArcParams[2][1] * anArcParams[2][1];
+ if (std::fabs(aRad2 - aDist2) < tolerance)
+ return; // nothing to update (last point already on the arc)
+ if (aDist2 < tolerance)
+ return; // unable to update
+ double aCoeff = std::sqrt(aRad2 / aDist2);
+ anArcParams[2][0] *= aCoeff;
+ anArcParams[2][1] *= aCoeff;
+
+ // Update last point
+ aPoint = myStorage->getEntity(theArc.point[2]);
+ for (int i = 0; i < 2; i++) {
+ aParam = Slvs_MakeParam(aPoint.param[i], myGroup->getId(),
+ anArcParams[0][i] + anArcParams[2][i]);
+ myStorage->updateParameter(aParam);
+ }
+}
+void SketchSolver_ConstraintMirror::adjustConstraint()
+{
AttributeRefAttrPtr aMirLineAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
if (!aMirLineAttr || !aMirLineAttr->isInitialized() || !aMirLineAttr->isObject()) {
return;
Slvs_Entity aMirrorLine = myStorage->getEntity(aMirLineIter->second);
+ Slvs_Constraint aMirror;
double aStartEnd[4];
for (int i = 0; i < 2; i++) {
Slvs_Entity aPoint = myStorage->getEntity(aMirrorLine.point[i]);
aStartEnd[2*i+j] = myStorage->getParameter(aPoint.param[j]).val;
}
- Slvs_Constraint aMirror;
+ // Search mirror between middle points on the arcs and recompute their coordinates
+ std::map<Slvs_hEntity, Slvs_hEntity> aPointsOnCircles;
+ std::list<Slvs_Constraint> aMirrorPonCirc;
+ std::list<Slvs_Constraint> aPonCirc = myStorage->getConstraintsByType(SLVS_C_PT_ON_CIRCLE);
std::vector<Slvs_hConstraint>::iterator aConstrIter = mySlvsConstraints.begin();
for (; aConstrIter != mySlvsConstraints.end(); aConstrIter++) {
aMirror = myStorage->getConstraint(*aConstrIter);
}
if (aPonCircA.h == SLVS_E_UNKNOWN || aPonCircB.h == SLVS_E_UNKNOWN)
continue;
+ aMirrorPonCirc.push_back(aMirror);
+ // Store point IDs to avoid their recalculation twice
+ aPointsOnCircles[aPonCircA.ptA] = aPonCircA.entityA;
+ aPointsOnCircles[aPonCircB.ptA] = aPonCircB.entityA;
+ }
+
+ // Recalculate positions of mirroring points
+ std::list<Slvs_Constraint> aMirrorList = myStorage->getConstraintsByType(SLVS_C_SYMMETRIC_LINE);
+ std::list<Slvs_Constraint>::iterator aMirIter = aMirrorList.begin();
+ for (; aMirIter != aMirrorList.end(); aMirIter++) {
+ if (aPointsOnCircles.find(aMirIter->ptA) != aPointsOnCircles.end())
+ continue; // Avoid mirroring points on circles
+ Slvs_Entity aBase = myStorage->getEntity(aMirIter->ptA);
+ Slvs_Entity aMirror = myStorage->getEntity(aMirIter->ptB);
+ makeMirrorEntity(aBase, aMirror, aStartEnd);
+ }
- bool aNeedToResolve = myStorage->isNeedToResolve();
+ bool aNeedToResolve = myStorage->isNeedToResolve();
+ for (aMirIter = aMirrorPonCirc.begin(); aMirIter != aMirrorPonCirc.end(); aMirIter++) {
// Calculate middle point for base arc and mirrored point on mirror arc
- Slvs_Entity aBaseArc = myStorage->getEntity(aPonCircA.entityA);
- Slvs_Entity aBasePoint = myStorage->getEntity(aPonCircA.ptA);
+ Slvs_Entity aBaseArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptA]);
+ Slvs_Entity aBasePoint = myStorage->getEntity(aMirIter->ptA);
Slvs_Param aParamX = myStorage->getParameter(aBasePoint.param[0]);
Slvs_Param aParamY = myStorage->getParameter(aBasePoint.param[1]);
calculateMiddlePoint(aBaseArc, 0.5, aParamX.val, aParamY.val);
myStorage->updateParameter(aParamX);
myStorage->updateParameter(aParamY);
- Slvs_Entity aMirrorArc = myStorage->getEntity(aPonCircB.entityA);
- Slvs_Entity aMirrorPoint = myStorage->getEntity(aPonCircB.ptA);
+ Slvs_Entity aMirrorArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptB]);
+ Slvs_Entity aMirrorPoint = myStorage->getEntity(aMirIter->ptB);
aParamX = myStorage->getParameter(aMirrorPoint.param[0]);
aParamY = myStorage->getParameter(aMirrorPoint.param[1]);
calculateMiddlePoint(aMirrorArc, 0.5, aParamX.val, aParamY.val);
myStorage->updateParameter(aParamX);
myStorage->updateParameter(aParamY);
- // To avoid looped recalculations of sketch
- myStorage->setNeedToResolve(aNeedToResolve);
+ // make centers of arcs symmetric
+ aBasePoint = myStorage->getEntity(aBaseArc.point[0]);
+ aMirrorPoint = myStorage->getEntity(aMirrorArc.point[0]);
+ makeMirrorEntity(aBasePoint, aMirrorPoint, aStartEnd);
}
+ // Restore previous value to avoid looped recalculations of sketch
+ myStorage->setNeedToResolve(aNeedToResolve);
}
const Slvs_Entity& theMirror,
const double theMirrorLine[]) const;
+ /// \brief Precisely update last point to be on arc
+ void adjustArcPoints(const Slvs_Entity& theArc) const;
+
private:
size_t myNumberOfObjects; ///< number of previously mirrored objects
};
--- /dev/null
+#include <SketchSolver_ConstraintMultiRotation.h>
+#include <SketchSolver_Group.h>
+#include <SketchSolver_Error.h>
+
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_MultiRotation.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_ResultConstruction.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
+
+#include <math.h>
+
+void SketchSolver_ConstraintMultiRotation::getAttributes(
+ Slvs_hEntity& theCenter, double& theAngle,
+ std::vector<std::vector<Slvs_hEntity> >& thePoints,
+ std::vector<std::vector<Slvs_hEntity> >& theCircular)
+{
+ DataPtr aData = myBaseConstraint->data();
+ theAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ aData->attribute(SketchPlugin_MultiRotation::ANGLE_ID()))->value();
+
+ AttributePtr aCenterAttr = aData->attribute(SketchPlugin_MultiRotation::CENTER_ID());
+ if (!aCenterAttr || !aCenterAttr->isInitialized()) {
+ myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+ return;
+ }
+ int aType = SLVS_E_UNKNOWN; // type of created entity
+ Slvs_hEntity anEntityID = myGroup->getAttributeId(aCenterAttr);
+ if (anEntityID == SLVS_E_UNKNOWN)
+ anEntityID = changeEntity(aCenterAttr, aType);
+ theCenter = anEntityID;
+
+ // Lists of objects and number of copies
+ AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ myNumberOfObjects = anInitialRefList->size();
+ myNumberOfCopies = (size_t) aData->integer(SketchPlugin_MultiRotation::NUMBER_OF_COPIES_ID())->value();
+ AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ if (!aRefList) {
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ return;
+ }
+
+ // Obtain all points of initial features and store them into separate lists
+ // containing their translated copies.
+ // Also all circles and arc collected too, because they will be constrained by equal radii.
+ FeaturePtr aFeature;
+ ResultConstructionPtr aRC;
+ std::vector<Slvs_hEntity> aPoints[2]; // lists of points of features
+ std::vector<Slvs_hEntity> aCircs; // list of circular objects
+ std::list<ObjectPtr> anObjectList = aRefList->list();
+ std::list<ObjectPtr>::iterator anObjectIter = anObjectList.begin();
+ while (anObjectIter != anObjectList.end()) {
+ aPoints[0].clear();
+ aPoints[1].clear();
+ aCircs.clear();
+
+ for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) {
+ aFeature = ModelAPI_Feature::feature(*anObjectIter);
+ if (!aFeature)
+ continue;
+ anEntityID = changeEntity(aFeature, aType);
+ Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
+ switch (aType) {
+ case SLVS_E_POINT_IN_2D:
+ case SLVS_E_POINT_IN_3D:
+ aPoints[0].push_back(anEntityID);
+ break;
+ case SLVS_E_LINE_SEGMENT:
+ aPoints[0].push_back(anEntity.point[0]); // start point of line
+ aPoints[1].push_back(anEntity.point[1]); // end point of line
+ break;
+ case SLVS_E_CIRCLE:
+ aPoints[0].push_back(anEntity.point[0]); // center of circle
+ aCircs.push_back(anEntityID);
+ break;
+ case SLVS_E_ARC_OF_CIRCLE:
+ aPoints[0].push_back(anEntity.point[1]); // start point of arc
+ aPoints[1].push_back(anEntity.point[2]); // end point of arc
+ aCircs.push_back(anEntityID);
+ break;
+ default:
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ return;
+ }
+ }
+
+ if (!aPoints[0].empty())
+ thePoints.push_back(aPoints[0]);
+ if (!aPoints[1].empty())
+ thePoints.push_back(aPoints[1]);
+ if (!aCircs.empty())
+ theCircular.push_back(aCircs);
+ }
+}
+
+void SketchSolver_ConstraintMultiRotation::process()
+{
+ cleanErrorMsg();
+ if (!myBaseConstraint || !myStorage || myGroup == 0) {
+ /// TODO: Put error message here
+ return;
+ }
+ if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+ update(myBaseConstraint);
+
+ Slvs_hEntity aCenter;
+ std::vector<std::vector<Slvs_hEntity> > aPointsAndCopies;
+ std::vector<std::vector<Slvs_hEntity> > aCircsAndCopies;
+ getAttributes(aCenter, myAngle, aPointsAndCopies, aCircsAndCopies);
+ if (!myErrorMsg.empty())
+ return;
+
+ // Create lines between neighbor rotated points and make angle between them equal to anAngle.
+ // Also these lines should have equal lengths.
+ Slvs_Constraint aConstraint;
+ myRotationCenter = aCenter;
+ Slvs_Entity aPrevLine;
+ std::vector<std::vector<Slvs_hEntity> >::iterator aCopyIter = aPointsAndCopies.begin();
+ for (; aCopyIter != aPointsAndCopies.end(); aCopyIter++) {
+ size_t aSize = aCopyIter->size();
+ if (aSize <= 1) continue;
+
+ aPrevLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
+ myGroup->getWorkplaneId(), aCenter, (*aCopyIter)[0]);
+ aPrevLine.h = myStorage->addEntity(aPrevLine);
+ for (size_t i = 1; i < aSize; i++) {
+ Slvs_Entity aLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
+ myGroup->getWorkplaneId(), aCenter, (*aCopyIter)[i]);
+ aLine.h = myStorage->addEntity(aLine);
+ // Equal length constraint
+ aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+ SLVS_C_EQUAL_LENGTH_LINES, myGroup->getWorkplaneId(), 0.0,
+ SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aPrevLine.h, aLine.h);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ // Angle constraint
+ aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+ SLVS_C_ANGLE, myGroup->getWorkplaneId(), fabs(myAngle), SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
+ aPrevLine.h, aLine.h);
+ if (myAngle < 0.0) // clockwise rotation
+ aConstraint.other = true;
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+
+ aPrevLine = aLine;
+ }
+ }
+ // Equal radii constraints
+ for (aCopyIter = aCircsAndCopies.begin(); aCopyIter != aCircsAndCopies.end(); aCopyIter++) {
+ size_t aSize = aCopyIter->size();
+ for (size_t i = 0; i < aSize - 1; i++) {
+ aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+ SLVS_C_EQUAL_RADIUS, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
+ (*aCopyIter)[i], (*aCopyIter)[i+1]);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ }
+ }
+
+ // Set the rotation center unchanged during constraint recalculation
+ if (!myStorage->isPointFixed(myRotationCenter, aConstraint.h, true)) {
+ aConstraint = Slvs_MakeConstraint(
+ SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
+ myRotationCenter, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ }
+
+ adjustConstraint();
+}
+
+void SketchSolver_ConstraintMultiRotation::update(ConstraintPtr theConstraint)
+{
+ cleanErrorMsg();
+ if (!theConstraint || theConstraint == myBaseConstraint) {
+ AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ AttributeIntegerPtr aNbCopies = myBaseConstraint->integer(SketchPlugin_MultiRotation::NUMBER_OF_COPIES_ID());
+ if (anInitialRefList->size() != myNumberOfObjects || aNbCopies->value() != myNumberOfCopies) {
+ remove(myBaseConstraint);
+ process();
+ return;
+ }
+ }
+
+ // update angle value
+ myAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ myBaseConstraint->attribute(SketchPlugin_MultiRotation::ANGLE_ID()))->value();
+
+ SketchSolver_Constraint::update();
+}
+
+bool SketchSolver_ConstraintMultiRotation::remove(ConstraintPtr theConstraint)
+{
+ cleanErrorMsg();
+ if (theConstraint && theConstraint != myBaseConstraint)
+ return false;
+ bool isFullyRemoved = true;
+ std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
+ for (; aCIter != mySlvsConstraints.end(); aCIter++)
+ isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
+ mySlvsConstraints.clear();
+
+ std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
+ for (; aFeatIt != myFeatureMap.end(); aFeatIt++)
+ myStorage->removeEntity(aFeatIt->second);
+
+ if (isFullyRemoved) {
+ myFeatureMap.clear();
+ myAttributeMap.clear();
+ myValueMap.clear();
+ } else
+ cleanRemovedEntities();
+ return true;
+}
+
+void SketchSolver_ConstraintMultiRotation::adjustConstraint()
+{
+ if (abs(myAngle) < tolerance) {
+ myStorage->setNeedToResolve(false);
+ return;
+ }
+
+ // Obtain coordinates of rotation center
+ Slvs_Entity aRotCenter = myStorage->getEntity(myRotationCenter);
+ double aCenterXY[2];
+ for (int i = 0; i < 2; i++)
+ aCenterXY[i] = myStorage->getParameter(aRotCenter.param[i]).val;
+
+ double cosA = cos(myAngle * PI / 180.0);
+ double sinA = sin(myAngle * PI / 180.0);
+
+ // Update positions of all points to satisfy angles
+ std::list<Slvs_Constraint> aConstrAngle = myStorage->getConstraintsByType(SLVS_C_ANGLE);
+ std::list<Slvs_Constraint>::iterator anAngIt = aConstrAngle.begin();
+ std::vector<Slvs_hConstraint>::iterator aCIt;
+ Slvs_hConstraint aFixed; // temporary variable
+ double aVec[2]; // coordinates of vector defining a line
+ Slvs_Param aTarget[2]; // parameter to be changed
+ for (; anAngIt != aConstrAngle.end(); anAngIt++) {
+ for (aCIt = mySlvsConstraints.begin(); aCIt != mySlvsConstraints.end(); aCIt++)
+ if (anAngIt->h == *aCIt)
+ break;
+ if (aCIt == mySlvsConstraints.end())
+ continue;
+ Slvs_Entity aLineA = myStorage->getEntity(anAngIt->entityA);
+ Slvs_Entity aLineB = myStorage->getEntity(anAngIt->entityB);
+ if (myStorage->isPointFixed(aLineB.point[1], aFixed))
+ continue;
+ Slvs_Entity aPointA = myStorage->getEntity(aLineA.point[1]);
+ Slvs_Entity aPointB = myStorage->getEntity(aLineB.point[1]);
+ for (int i = 0; i < 2; i++) {
+ aVec[i] = myStorage->getParameter(aPointA.param[i]).val - aCenterXY[i];
+ aTarget[i] = myStorage->getParameter(aPointB.param[i]);
+ }
+ aTarget[0].val = aCenterXY[0] + aVec[0] * cosA - aVec[1] * sinA;
+ aTarget[1].val = aCenterXY[1] + aVec[0] * sinA + aVec[1] * cosA;
+ myStorage->updateParameter(aTarget[0]);
+ myStorage->updateParameter(aTarget[1]);
+
+ anAngIt->valA = myAngle;
+ myStorage->updateConstraint(*anAngIt);
+ }
+
+ // update positions of centers of arcs for correct radius calculation
+ std::list<Slvs_Constraint> aRadii = myStorage->getConstraintsByType(SLVS_C_EQUAL_RADIUS);
+ std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt;
+ for (anAngIt = aRadii.begin(); anAngIt != aRadii.end(); anAngIt++) {
+ int aNbFound = 0; // number of arcs used in translation
+ for (aFeatIt = myFeatureMap.begin(); aFeatIt != myFeatureMap.end(); aFeatIt++)
+ if (aFeatIt->second == anAngIt->entityA || aFeatIt->second == anAngIt->entityB) {
+ if (aFeatIt->first->getKind() == SketchPlugin_Arc::ID())
+ aNbFound++;
+ else
+ break;
+ }
+ if (aNbFound != 2)
+ continue;
+ // two arcs were found, update their centers
+ Slvs_Entity anArcA = myStorage->getEntity(anAngIt->entityA);
+ Slvs_Entity anArcB = myStorage->getEntity(anAngIt->entityB);
+ if (myStorage->isPointFixed(anArcB.point[0], aFixed))
+ continue;
+ Slvs_Entity aCenterA = myStorage->getEntity(anArcA.point[0]);
+ Slvs_Entity aCenterB = myStorage->getEntity(anArcB.point[0]);
+ for (int i = 0; i < 2; i++) {
+ aVec[i] = myStorage->getParameter(aCenterA.param[i]).val - aCenterXY[i];
+ aTarget[i] = myStorage->getParameter(aCenterB.param[i]);
+ }
+ aTarget[0].val = aCenterXY[0] + aVec[0] * cosA - aVec[1] * sinA;
+ aTarget[1].val = aCenterXY[1] + aVec[0] * sinA + aVec[1] * cosA;
+ myStorage->updateParameter(aTarget[0]);
+ myStorage->updateParameter(aTarget[1]);
+ }
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: SketchSolver_ConstraintMultiRotation.h
+// Created: 1 Apr 2015
+// Author: Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintMultiRotation_H_
+#define SketchSolver_ConstraintMultiRotation_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_Constraint.h>
+
+/** \class SketchSolver_ConstraintMultiRotation
+ * \ingroup Plugins
+ * \brief Convert rotated features to the list of SolveSpace constraints
+ */
+class SketchSolver_ConstraintMultiRotation : public SketchSolver_Constraint
+{
+public:
+ SketchSolver_ConstraintMultiRotation(ConstraintPtr theConstraint) :
+ SketchSolver_Constraint(theConstraint),
+ myNumberOfObjects(0),
+ myNumberOfCopies(0)
+ {}
+
+ virtual int getType() const
+ { return SLVS_C_MULTI_ROTATION; }
+
+ /// \brief Update constraint
+ virtual void update(ConstraintPtr theConstraint = ConstraintPtr());
+
+ /// \brief Tries to remove constraint
+ /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
+ virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
+
+protected:
+ /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+ virtual void process();
+
+ /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
+ /// \param[out] theValue numerical characteristic of constraint (e.g. distance)
+ /// \param[out] theAttributes list of attributes to be filled
+ virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes)
+ { /* do nothing here */ }
+
+ /// \brief Generate list of rotated entities
+ /// \param[out] theCenter ID of central point of rotation
+ /// \param[out] theAngle rotation angle
+ /// \param[out] thePoints list of IDs of initial points and their rotated copies
+ /// \param[out] theCircular list of IDs of arcs and circles and their copies
+ void getAttributes(Slvs_hEntity& theCenter, double& theAngle,
+ std::vector<std::vector<Slvs_hEntity> >& thePoints,
+ std::vector<std::vector<Slvs_hEntity> >& theCircular);
+
+ /// \brief This method is used in derived objects to check consistence of constraint.
+ virtual void adjustConstraint();
+
+private:
+ size_t myNumberOfObjects; ///< number of previous initial objects
+ size_t myNumberOfCopies; ///< number of previous copies of initial objects
+ Slvs_hEntity myRotationCenter; ///< ID of center of rotation
+ double myAngle; ///< angle of rotation
+};
+
+#endif
--- /dev/null
+#include <SketchSolver_ConstraintMultiTranslation.h>
+#include <SketchSolver_Group.h>
+#include <SketchSolver_Error.h>
+
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_MultiTranslation.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Data.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
+
+#include <math.h>
+
+
+void SketchSolver_ConstraintMultiTranslation::getAttributes(
+ Slvs_hEntity& theStartPoint, Slvs_hEntity& theEndPoint,
+ std::vector<std::vector<Slvs_hEntity> >& thePoints,
+ std::vector<std::vector<Slvs_hEntity> >& theCircular)
+{
+ DataPtr aData = myBaseConstraint->data();
+ AttributePtr aStartPointAttr = aData->attribute(SketchPlugin_MultiTranslation::START_POINT_ID());
+ AttributePtr aEndPointAttr = aData->attribute(SketchPlugin_MultiTranslation::END_POINT_ID());
+ if (!aStartPointAttr || !aStartPointAttr->isInitialized() ||
+ !aEndPointAttr || !aEndPointAttr->isInitialized()) {
+ myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+ return;
+ }
+
+ int aType = SLVS_E_UNKNOWN; // type of created entity
+ Slvs_hEntity anEntityID = myGroup->getAttributeId(aStartPointAttr);
+ if (anEntityID == SLVS_E_UNKNOWN)
+ anEntityID = changeEntity(aStartPointAttr, aType);
+ theStartPoint = anEntityID;
+ anEntityID = myGroup->getAttributeId(aEndPointAttr);
+ if (anEntityID == SLVS_E_UNKNOWN)
+ anEntityID = changeEntity(aEndPointAttr, aType);
+ theEndPoint = anEntityID;
+
+ // Lists of objects and number of copies
+ AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ myNumberOfObjects = anInitialRefList->size();
+ myNumberOfCopies = (size_t) aData->integer(SketchPlugin_MultiTranslation::NUMBER_OF_COPIES_ID())->value();
+ AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ if (!aRefList) {
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ return;
+ }
+
+ // Obtain all points of initial features and store them into separate lists
+ // containing their translated copies.
+ // Also all circles and arc collected too, because they will be constrained by equal radii.
+ FeaturePtr aFeature;
+ ResultConstructionPtr aRC;
+ std::vector<Slvs_hEntity> aPoints[2]; // lists of points of features
+ std::vector<Slvs_hEntity> aCircs; // list of circular objects
+ std::list<ObjectPtr> anObjectList = aRefList->list();
+ std::list<ObjectPtr>::iterator anObjectIter = anObjectList.begin();
+ while (anObjectIter != anObjectList.end()) {
+ aPoints[0].clear();
+ aPoints[1].clear();
+ aCircs.clear();
+
+ for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) {
+ aFeature = ModelAPI_Feature::feature(*anObjectIter);
+ if (!aFeature)
+ continue;
+ anEntityID = changeEntity(aFeature, aType);
+ Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
+ switch (aType) {
+ case SLVS_E_POINT_IN_2D:
+ case SLVS_E_POINT_IN_3D:
+ aPoints[0].push_back(anEntityID);
+ break;
+ case SLVS_E_LINE_SEGMENT:
+ aPoints[0].push_back(anEntity.point[0]); // start point of line
+ aPoints[1].push_back(anEntity.point[1]); // end point of line
+ break;
+ case SLVS_E_CIRCLE:
+ aPoints[0].push_back(anEntity.point[0]); // center of circle
+ aCircs.push_back(anEntityID);
+ break;
+ case SLVS_E_ARC_OF_CIRCLE:
+ aPoints[0].push_back(anEntity.point[1]); // start point of arc
+ aPoints[1].push_back(anEntity.point[2]); // end point of arc
+ aCircs.push_back(anEntityID);
+ break;
+ default:
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ return;
+ }
+ }
+
+ if (!aPoints[0].empty())
+ thePoints.push_back(aPoints[0]);
+ if (!aPoints[1].empty())
+ thePoints.push_back(aPoints[1]);
+ if (!aCircs.empty())
+ theCircular.push_back(aCircs);
+ }
+}
+
+void SketchSolver_ConstraintMultiTranslation::process()
+{
+ cleanErrorMsg();
+ if (!myBaseConstraint || !myStorage || myGroup == 0) {
+ /// TODO: Put error message here
+ return;
+ }
+ if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+ update(myBaseConstraint);
+
+ Slvs_hEntity aStartPoint, aEndPoint;
+ std::vector<std::vector<Slvs_hEntity> > aPointsAndCopies;
+ std::vector<std::vector<Slvs_hEntity> > aCircsAndCopies;
+ getAttributes(aStartPoint, aEndPoint, aPointsAndCopies, aCircsAndCopies);
+ if (!myErrorMsg.empty())
+ return;
+
+ // Create lines between neighbor translated points and make them parallel to the translation line.
+ // Also these lines should have equal lengths.
+ Slvs_Constraint aConstraint;
+ Slvs_Entity aTranslationLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
+ myGroup->getWorkplaneId(), aStartPoint, aEndPoint);
+ aTranslationLine.h = myStorage->addEntity(aTranslationLine);
+ myTranslationLine = aTranslationLine.h;
+ std::vector<std::vector<Slvs_hEntity> >::iterator aCopyIter = aPointsAndCopies.begin();
+ for (; aCopyIter != aPointsAndCopies.end(); aCopyIter++) {
+ size_t aSize = aCopyIter->size();
+ for (size_t i = 0; i < aSize - 1; i++) {
+ Slvs_Entity aLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
+ myGroup->getWorkplaneId(), (*aCopyIter)[i], (*aCopyIter)[i+1]);
+ aLine.h = myStorage->addEntity(aLine);
+ // Equal length constraint
+ aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+ SLVS_C_EQUAL_LENGTH_LINES, myGroup->getWorkplaneId(), 0.0,
+ SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aTranslationLine.h, aLine.h);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ // Parallel constraint
+ aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+ SLVS_C_PARALLEL, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
+ aTranslationLine.h, aLine.h);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ }
+ }
+ // Equal radii constraints
+ for (aCopyIter = aCircsAndCopies.begin(); aCopyIter != aCircsAndCopies.end(); aCopyIter++) {
+ size_t aSize = aCopyIter->size();
+ for (size_t i = 0; i < aSize - 1; i++) {
+ aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+ SLVS_C_EQUAL_RADIUS, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
+ (*aCopyIter)[i], (*aCopyIter)[i+1]);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ }
+ }
+
+ // Set the translation line unchanged during constraint recalculation
+ for (int i = 0; i < 2; i++) {
+ if (myStorage->isPointFixed(aTranslationLine.point[i], aConstraint.h, true))
+ continue;
+ aConstraint = Slvs_MakeConstraint(
+ SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
+ aTranslationLine.point[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ }
+
+ adjustConstraint();
+}
+
+void SketchSolver_ConstraintMultiTranslation::update(ConstraintPtr theConstraint)
+{
+ cleanErrorMsg();
+ if (!theConstraint || theConstraint == myBaseConstraint) {
+ AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ AttributeIntegerPtr aNbCopies = myBaseConstraint->integer(SketchPlugin_MultiTranslation::NUMBER_OF_COPIES_ID());
+ if (anInitialRefList->size() != myNumberOfObjects ||
+ (size_t)aNbCopies->value() != myNumberOfCopies) {
+ remove(myBaseConstraint);
+ process();
+ return;
+ }
+ }
+ SketchSolver_Constraint::update();
+}
+
+bool SketchSolver_ConstraintMultiTranslation::remove(ConstraintPtr theConstraint)
+{
+ cleanErrorMsg();
+ if (theConstraint && theConstraint != myBaseConstraint)
+ return false;
+ bool isFullyRemoved = true;
+ std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
+ for (; aCIter != mySlvsConstraints.end(); aCIter++)
+ isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
+ mySlvsConstraints.clear();
+
+ std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
+ for (; aFeatIt != myFeatureMap.end(); aFeatIt++)
+ myStorage->removeEntity(aFeatIt->second);
+
+ if (isFullyRemoved) {
+ myFeatureMap.clear();
+ myAttributeMap.clear();
+ myValueMap.clear();
+ } else
+ cleanRemovedEntities();
+ return true;
+}
+
+void SketchSolver_ConstraintMultiTranslation::adjustConstraint()
+{
+ Slvs_Entity aTranslationLine = myStorage->getEntity(myTranslationLine);
+ // Check if the distance between point is 0, no need to resolve constraints (just wait another values)
+ double aXY[4];
+ for (int i = 0; i < 2; i++) {
+ Slvs_Entity aPnt = myStorage->getEntity(aTranslationLine.point[i]);
+ aXY[2*i] = myStorage->getParameter(aPnt.param[0]).val;
+ aXY[2*i+1] = myStorage->getParameter(aPnt.param[1]).val;
+ }
+ double aDelta[2] = {aXY[2] - aXY[0], aXY[3] - aXY[1]};
+ if (fabs(aDelta[0]) + fabs(aDelta[1]) < tolerance) {
+ myStorage->setNeedToResolve(false);
+ return;
+ }
+
+ // Update positions of all points to satisfy distances
+ std::list<Slvs_Constraint> aParallel = myStorage->getConstraintsByType(SLVS_C_PARALLEL);
+ std::list<Slvs_Constraint>::iterator aParIt = aParallel.begin();
+ std::vector<Slvs_hConstraint>::iterator aCIt;
+ Slvs_hConstraint aFixed; // temporary variable
+ for (; aParIt != aParallel.end(); aParIt++) {
+ for (aCIt = mySlvsConstraints.begin(); aCIt != mySlvsConstraints.end(); aCIt++)
+ if (aParIt->h == *aCIt)
+ break;
+ if (aCIt == mySlvsConstraints.end())
+ continue;
+ Slvs_Entity aLine = myStorage->getEntity(aParIt->entityB);
+ if (myStorage->isPointFixed(aLine.point[1], aFixed))
+ continue;
+ Slvs_Entity aStart = myStorage->getEntity(aLine.point[0]);
+ Slvs_Entity aEnd = myStorage->getEntity(aLine.point[1]);
+ for (int i = 0; i < 2; i++) {
+ Slvs_Param aFrom = myStorage->getParameter(aStart.param[i]);
+ Slvs_Param aTo = myStorage->getParameter(aEnd.param[i]);
+ aTo.val = aFrom.val + aDelta[i];
+ myStorage->updateParameter(aTo);
+ }
+ }
+
+ // update positions of centers of arcs for correct radius calculation
+ std::list<Slvs_Constraint> aRadii = myStorage->getConstraintsByType(SLVS_C_EQUAL_RADIUS);
+ std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt;
+ for (aParIt = aRadii.begin(); aParIt != aRadii.end(); aParIt++) {
+ int aNbFound = 0; // number of arcs used in translation
+ for (aFeatIt = myFeatureMap.begin(); aFeatIt != myFeatureMap.end(); aFeatIt++)
+ if (aFeatIt->second == aParIt->entityA || aFeatIt->second == aParIt->entityB) {
+ if (aFeatIt->first->getKind() == SketchPlugin_Arc::ID())
+ aNbFound++;
+ else
+ break;
+ }
+ if (aNbFound != 2)
+ continue;
+ // two arcs were found, update their centers
+ Slvs_Entity anArcA = myStorage->getEntity(aParIt->entityA);
+ Slvs_Entity anArcB = myStorage->getEntity(aParIt->entityB);
+ if (myStorage->isPointFixed(anArcB.point[0], aFixed))
+ continue;
+ Slvs_Entity aCenterA = myStorage->getEntity(anArcA.point[0]);
+ Slvs_Entity aCenterB = myStorage->getEntity(anArcB.point[0]);
+ for (int i = 0; i < 2; i++) {
+ Slvs_Param aFrom = myStorage->getParameter(aCenterA.param[i]);
+ Slvs_Param aTo = myStorage->getParameter(aCenterB.param[i]);
+ aTo.val = aFrom.val + aDelta[i];
+ myStorage->updateParameter(aTo);
+ }
+ }
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: SketchSolver_ConstraintMultiTranslation.h
+// Created: 1 Apr 2015
+// Author: Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintMultiTranslation_H_
+#define SketchSolver_ConstraintMultiTranslation_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_Constraint.h>
+
+/** \class SketchSolver_ConstraintMultiTranslation
+ * \ingroup Plugins
+ * \brief Convert translated features to the list of SolveSpace constraints
+ */
+class SketchSolver_ConstraintMultiTranslation : public SketchSolver_Constraint
+{
+public:
+ SketchSolver_ConstraintMultiTranslation(ConstraintPtr theConstraint) :
+ SketchSolver_Constraint(theConstraint),
+ myNumberOfObjects(0),
+ myNumberOfCopies(0)
+ {}
+
+ virtual int getType() const
+ { return SLVS_C_MULTI_TRANSLATION; }
+
+ /// \brief Update constraint
+ virtual void update(ConstraintPtr theConstraint = ConstraintPtr());
+
+ /// \brief Tries to remove constraint
+ /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
+ virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
+
+protected:
+ /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+ virtual void process();
+
+ /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
+ /// \param[out] theValue numerical characteristic of constraint (e.g. distance)
+ /// \param[out] theAttributes list of attributes to be filled
+ virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes)
+ { /* do nothing here */ }
+
+ /// \brief Generate list of translated entities
+ /// \param[out] theStartPoint ID of start point of translation
+ /// \param[out] theEndPoint ID of final point of translation
+ /// \param[out] thePoints list of IDs of initial points and their translated copies
+ /// \param[out] theCircular list of IDs of arcs and circles and their copies
+ void getAttributes(Slvs_hEntity& theStartPoint, Slvs_hEntity& theEndPoint,
+ std::vector<std::vector<Slvs_hEntity> >& thePoints,
+ std::vector<std::vector<Slvs_hEntity> >& theCircular);
+
+ /// \brief This method is used in derived objects to check consistence of constraint.
+ virtual void adjustConstraint();
+
+private:
+ size_t myNumberOfObjects; ///< number of previous initial objects
+ size_t myNumberOfCopies; ///< number of previous copies of initial objects
+ Slvs_hEntity myTranslationLine; ///< ID of translation line
+};
+
+#endif
double aValue;
std::vector<Slvs_hEntity> anEntities;
getAttributes(aValue, anEntities);
- if (!myErrorMsg.empty() || myFeatureMap.empty())
+ if (!myErrorMsg.empty() || (myFeatureMap.empty() && myAttributeMap.empty()))
return;
- Slvs_hEntity anEntID = myFeatureMap.begin()->second;
+ Slvs_hEntity anEntID;
+ if (!myFeatureMap.empty())
+ anEntID = myFeatureMap.begin()->second;
+ else
+ anEntID = myAttributeMap.begin()->second;
if (myStorage->isEntityFixed(anEntID, true)) {
myErrorMsg = SketchSolver_Error::ALREADY_FIXED();
return;
}
- if (myFeatureMap.begin()->first->getKind() == SketchPlugin_Line::ID()) {
+ std::string aKind;
+ if (!myFeatureMap.empty())
+ aKind = myFeatureMap.begin()->first->getKind();
+ else
+ aKind = myAttributeMap.begin()->first->attributeType();
+
+ if (aKind == SketchPlugin_Line::ID()) {
Slvs_Entity aLine = myStorage->getEntity(anEntID);
fixLine(aLine);
}
- else if (myFeatureMap.begin()->first->getKind() == SketchPlugin_Arc::ID()) {
+ else if (aKind == SketchPlugin_Arc::ID()) {
Slvs_Entity anArc = myStorage->getEntity(anEntID);
fixArc(anArc);
}
- else if (myFeatureMap.begin()->first->getKind() == SketchPlugin_Circle::ID()) {
+ else if (aKind == SketchPlugin_Circle::ID()) {
Slvs_Entity aCirc = myStorage->getEntity(anEntID);
fixCircle(aCirc);
}
- else if (myFeatureMap.begin()->first->getKind() == SketchPlugin_Point::ID()) {
+ else if (aKind == SketchPlugin_Point::ID() || aKind == GeomDataAPI_Point2D::typeId()) {
fixPoint(anEntID);
}
}
setTemporary(aConstraint);
}
}
- //// Fix base features for mirror
- //if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
- // AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
- // theConstraint->attribute(SketchPlugin_ConstraintMirror::ENTITY_B()));
- // fixFeaturesList(aRefList);
- //}
+ // Fix mirror line
+ if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ theConstraint->attribute(SketchPlugin_ConstraintMirror::ENTITY_A()));
+ if (aRefAttr && aRefAttr->isObject()) {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+ SolverConstraintPtr aConstraint =
+ SketchSolver_Builder::getInstance()->createRigidConstraint(aFeature);
+ if (aConstraint) {
+ aConstraint->setGroup(this);
+ aConstraint->setStorage(myStorage);
+ setTemporary(aConstraint);
+ }
+ }
+ }
if (!myFeatureStorage)
myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage);
void SketchSolver_Group::moveFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
{
- updateFeature(theFeature);
- // Temporary rigid constraint
+ // Firstly, create temporary rigid constraint
SolverConstraintPtr aConstraint =
SketchSolver_Builder::getInstance()->createRigidConstraint(theFeature);
if (!aConstraint)
aConstraint->setStorage(myStorage);
if (aConstraint->error().empty())
setTemporary(aConstraint);
+ // Secondly, update the feature
+ updateFeature(theFeature);
}
// ============================================================================
// Unknown constraint (for error reporting)
#define SLVS_C_UNKNOWN 0
// Fillet constraint identifier
-#define SLVS_C_FILLET 100100
+#define SLVS_C_FILLET 100100
+// Multi-rotation constraint identifier
+#define SLVS_C_MULTI_ROTATION 100101
+// Multi-translation constraint identifier
+#define SLVS_C_MULTI_TRANSLATION 100102
// Unknown entity
#define SLVS_E_UNKNOWN 0
// Unknown group
SketcherPrs_Radius.h
SketcherPrs_LengthDimension.h
SketcherPrs_Mirror.h
+ SketcherPrs_Transformation.h
)
SET(PROJECT_SOURCES
SketcherPrs_Radius.cpp
SketcherPrs_LengthDimension.cpp
SketcherPrs_Mirror.cpp
+ SketcherPrs_Transformation.cpp
)
SET(PROJECT_LIBRARIES
Config
ModelAPI
GeomAPI
+ Events
${CAS_KERNEL}
${CAS_MODELER}
${CAS_VIEWER}
icons/equal.png
icons/tangent.png
icons/mirror.png
+ icons/rotate.png
+ icons/translate.png
)
ADD_DEFINITIONS(-DSKETCHERPRS_EXPORTS ${CAS_DEFINITIONS})
INCLUDE_DIRECTORIES(
${PROJECT_SOURCE_DIR}/src/Config
+ ${PROJECT_SOURCE_DIR}/src/Events
${PROJECT_SOURCE_DIR}/src/ModelAPI
${PROJECT_SOURCE_DIR}/src/GeomAPI
${PROJECT_SOURCE_DIR}/src/GeomDataAPI
{
std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(myConstraint,
SketchPlugin_Constraint::ENTITY_A());
+ if (aPnt.get() == NULL)
+ aPnt = SketcherPrs_Tools::getPoint(myConstraint, SketchPlugin_Constraint::ENTITY_B());
if (aPnt.get() == NULL)
return;
static Handle(Graphic3d_AspectMarker3d) aPtA;
if (aPtA.IsNull()) {
aPtA = new Graphic3d_AspectMarker3d ();
- aPtA->SetType(Aspect_TOM_RING1);
- aPtA->SetScale(2.);
- aPtA->SetColor(myOwnColor);
}
+ aPtA->SetType(Aspect_TOM_RING3);
+ aPtA->SetScale(2.);
+ aPtA->SetColor(Quantity_NOC_YELLOW);
+
Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup(thePresentation);
aGroup->SetPrimitivesAspect(aPtA);
Handle(Graphic3d_ArrayOfPoints) aPntArray = new Graphic3d_ArrayOfPoints(1);
aPntArray->AddVertex (aPoint->x(), aPoint->y(), aPoint->z());
aGroup->AddPrimitiveArray (aPntArray);
+
+ aPtA->SetType(Aspect_TOM_RING1);
+ aPtA->SetScale(1.);
+ aPtA->SetColor(Quantity_NOC_BLACK);
+ aGroup->SetPrimitivesAspect(aPtA);
+ aGroup->AddPrimitiveArray (aPntArray);
+
+ aPtA->SetType(Aspect_TOM_POINT);
+ aPtA->SetScale(5.);
+ aGroup->SetPrimitivesAspect(aPtA);
+ aGroup->AddPrimitiveArray (aPntArray);
}
#include "SketcherPrs_Radius.h"
#include "SketcherPrs_LengthDimension.h"
#include "SketcherPrs_Mirror.h"
+#include "SketcherPrs_Transformation.h"
#define CONSTRAINT_PRS_IMPL(NAME, CLASS) \
AISObjectPtr SketcherPrs_Factory::NAME(ModelAPI_Feature* theConstraint, \
aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aPrs));
return aAISObj;
}
+
+AISObjectPtr SketcherPrs_Factory::translateConstraint(ModelAPI_Feature* theConstraint,
+ const std::shared_ptr<GeomAPI_Ax3>& thePlane)
+{
+ std::shared_ptr<GeomAPI_AISObject> aAISObj = AISObjectPtr(new GeomAPI_AISObject());
+ Handle(SketcherPrs_Transformation) aPrs = new SketcherPrs_Transformation(theConstraint, thePlane, true);
+ aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aPrs));
+ return aAISObj;
+}
+
+AISObjectPtr SketcherPrs_Factory::rotateConstraint(ModelAPI_Feature* theConstraint,
+ const std::shared_ptr<GeomAPI_Ax3>& thePlane)
+{
+ std::shared_ptr<GeomAPI_AISObject> aAISObj = AISObjectPtr(new GeomAPI_AISObject());
+ Handle(SketcherPrs_Transformation) aPrs = new SketcherPrs_Transformation(theConstraint, thePlane, false);
+ aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aPrs));
+ return aAISObj;
+}
/// \param thePlane the current sketch plane
GET_CONSTRAINT_PRS(coincidentConstraint)
- /// Creates coincedent parallel presentation
+ /// Creates parallel constraint presentation
/// \param theConstraint the constraint
/// \param thePlane the current sketch plane
GET_CONSTRAINT_PRS(parallelConstraint)
/// \param thePlane the current sketch plane
GET_CONSTRAINT_PRS(perpendicularConstraint)
- /// Creates coincedent perpendicular presentation
+ /// Creates rigid constraint presentation
/// \param theConstraint the constraint
/// \param thePlane the current sketch plane
GET_CONSTRAINT_PRS(rigidConstraint)
- /// Creates coincedent perpendicular presentation
+ /// Creates horizontal constraint presentation
/// \param theConstraint the constraint
/// \param thePlane the current sketch plane
GET_CONSTRAINT_PRS(horisontalConstraint)
- /// Creates coincedent perpendicular presentation
+ /// Creates vertical constraint presentation
/// \param theConstraint the constraint
/// \param thePlane the current sketch plane
GET_CONSTRAINT_PRS(verticalConstraint)
- /// Creates coincedent perpendicular presentation
+ /// Creates equal constraint presentation
/// \param theConstraint the constraint
/// \param thePlane the current sketch plane
GET_CONSTRAINT_PRS(equalConstraint)
- /// Creates coincedent perpendicular presentation
+ /// Creates tangent constraiont presentation
/// \param theConstraint the constraint
/// \param thePlane the current sketch plane
GET_CONSTRAINT_PRS(tangentConstraint)
- /// Creates coincedent perpendicular presentation
+ /// Creates radius dimension presentation
/// \param theConstraint the constraint
/// \param thePlane the current sketch plane
GET_CONSTRAINT_PRS(radiusConstraint)
- /// Creates coincedent perpendicular presentation
+ /// Creates length dimension presentation
/// \param theConstraint the constraint
/// \param thePlane the current sketch plane
GET_CONSTRAINT_PRS(lengthDimensionConstraint)
- /// Creates coincedent perpendicular presentation
+ /// Creates mirror constraint presentation
/// \param theConstraint the constraint
/// \param thePlane the current sketch plane
GET_CONSTRAINT_PRS(mirrorConstraint)
+
+ /// Creates translate constraint presentation
+ /// \param theConstraint the constraint
+ /// \param thePlane the current sketch plane
+ GET_CONSTRAINT_PRS(translateConstraint)
+
+ /// Creates rotate constraint presentation
+ /// \param theConstraint the constraint
+ /// \param thePlane the current sketch plane
+ GET_CONSTRAINT_PRS(rotateConstraint)
};
#endif
#include <SketchPlugin_Constraint.h>
-#include <ModelAPI_AttributeRefList.h>
-
#include <Graphic3d_AspectLine3d.hxx>
#include <Prs3d_Root.hxx>
if (anAttrC.get() == NULL)
return;
- SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
int aNb = anAttrB->size();
if (aNb != anAttrC->size())
return;
addLine(aGroup, SketchPlugin_Constraint::ENTITY_A());
// Draw source objects
- int i;
- ObjectPtr aObj;
- for (i = 0; i < aNb; i++) {
- aObj = anAttrB->object(i);
- std::shared_ptr<GeomAPI_Shape> aShape = SketcherPrs_Tools::getShape(aObj);
- if (aShape.get() != NULL)
- drawShape(aShape, thePrs);
- }
+ drawListOfShapes(anAttrB, thePrs);
+
// draw mirrored objects
- for (i = 0; i < aNb; i++) {
- aObj = anAttrC->object(i);
- std::shared_ptr<GeomAPI_Shape> aShape = SketcherPrs_Tools::getShape(aObj);
- if (aShape.get() != NULL)
- drawShape(aShape, thePrs);
- }
+ drawListOfShapes(anAttrC, thePrs);
}
#include <GeomAPI_Curve.h>
#include <GeomAPI_Vertex.h>
+#include <ModelAPI_AttributeRefAttr.h>
+
#include <SketchPlugin_Constraint.h>
#include <AIS_Drawer.hxx>
bool SketcherPrs_Rigid::updatePoints(double theStep) const
{
- ObjectPtr aObj = SketcherPrs_Tools::getResult(myConstraint, SketchPlugin_Constraint::ENTITY_A());
- if (SketcherPrs_Tools::getShape(aObj).get() == NULL)
- return false;
-
- SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
- gp_Pnt aP1 = aMgr->getPosition(aObj, this, theStep);
- myPntArray->SetVertice(1, aP1);
+ std::shared_ptr<ModelAPI_Data> aData = myConstraint->data();
+ std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = aData->refattr(SketchPlugin_Constraint::ENTITY_A());
+ AttributePtr aRefAttr = anAttr->attr();
+ if (anAttr->isObject()) {
+ ObjectPtr aObj = anAttr->object();
+ if (SketcherPrs_Tools::getShape(aObj).get() == NULL)
+ return false;
+
+ SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
+ gp_Pnt aP1 = aMgr->getPosition(aObj, this, theStep);
+ myPntArray->SetVertice(1, aP1);
+ } else {
+ std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(myConstraint, SketchPlugin_Constraint::ENTITY_A());
+ if (aPnt.get() == NULL)
+ return false;
+ std::shared_ptr<GeomAPI_Pnt> aPoint = myPlane->to3D(aPnt->x(), aPnt->y() + theStep);
+ myPntArray->SetVertice(1, aPoint->impl<gp_Pnt>());
+ }
return true;
}
void SketcherPrs_Rigid::drawLines(const Handle(Prs3d_Presentation)& thePrs, Quantity_Color theColor) const
{
ObjectPtr aObj = SketcherPrs_Tools::getResult(myConstraint, SketchPlugin_Constraint::ENTITY_A());
- std::shared_ptr<GeomAPI_Shape> aShape = SketcherPrs_Tools::getShape(aObj);
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+ std::shared_ptr<GeomAPI_Shape> aShape;
+ if (aFeature.get()) {
+ const std::list<ResultPtr>& aResults = aFeature->results();
+ std::list<ResultPtr>::const_iterator aIt;
+ for (aIt = aResults.cbegin(); aIt != aResults.cend(); aIt++) {
+ aShape = (*aIt)->shape();
+ if (aShape->isEdge())
+ break;
+ }
+ } else {
+ aShape = SketcherPrs_Tools::getShape(aObj);
+ }
if (aShape.get() == NULL)
return;
#include <GeomAPI_Vertex.h>
#include <GeomAPI_Curve.h>
+#include <Events_Error.h>
+
#include <Graphic3d_ArrayOfSegments.hxx>
#include <Graphic3d_BndBox4f.hxx>
if (myIconsMap.count(iconName()) == 1) {
return myIconsMap[iconName()];
}
- TCollection_AsciiString aFile(getenv("NewGeomResources"));
- aFile += FSEP;
- aFile += iconName();
- Handle(Image_AlienPixMap) aPixMap = new Image_AlienPixMap();
- if (aPixMap->Load(aFile)) {
- myIconsMap[iconName()] = aPixMap;
- return aPixMap;
+ char* aEnv = getenv("NEWGEOM_ROOT_DIR");
+ if (aEnv != NULL) {
+ TCollection_AsciiString aFile(aEnv);
+ aFile+=FSEP;
+ aFile+="resources";
+ aFile += FSEP;
+ aFile += iconName();
+ Handle(Image_AlienPixMap) aPixMap = new Image_AlienPixMap();
+ if (aPixMap->Load(aFile)) {
+ myIconsMap[iconName()] = aPixMap;
+ return aPixMap;
+ }
}
+ static const char aMsg[] = "Error! constraint images are not found";
+ cout<<aMsg<<endl;
+ Events_Error::send(aMsg);
+ myIconsMap[iconName()] = Handle(Image_AlienPixMap)();
return Handle(Image_AlienPixMap)();
}
void SketcherPrs_SymbolPrs::prepareAspect()
{
if (myAspect.IsNull()) {
- myAspect = new Graphic3d_AspectMarker3d(icon());
+ Handle(Image_AlienPixMap) aIcon = icon();
+ if (aIcon.IsNull())
+ myAspect = new Graphic3d_AspectMarker3d();
+ else
+ myAspect = new Graphic3d_AspectMarker3d(aIcon);
}
}
int aNbVertex = myPntArray->VertexNumber();
if (myOwner.IsNull()) {
myOwner = new SelectMgr_EntityOwner(this);
- for (int i = 1; i <= aNbVertex; i++) {
- Handle(SketcherPrs_SensitivePoint) aSP = new SketcherPrs_SensitivePoint(myOwner, myPntArray, i);
- mySPoints.Append(aSP);
- }
+ }
+
+ mySPoints.Clear();
+ for (int i = 1; i <= aNbVertex; i++) {
+ Handle(SketcherPrs_SensitivePoint) aSP = new SketcherPrs_SensitivePoint(myOwner, myPntArray, i);
+ mySPoints.Append(aSP);
}
Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup(thePresentation);
StdPrs_Point::Add(thePrs, aPoint, myDrawer);
}
}
+
+void SketcherPrs_SymbolPrs::drawListOfShapes(const std::shared_ptr<ModelAPI_AttributeRefList>& theListAttr,
+ const Handle(Prs3d_Presentation)& thePrs) const
+{
+ int aNb = theListAttr->size();
+ if (aNb == 0)
+ return;
+ int i;
+ ObjectPtr aObj;
+ for (i = 0; i < aNb; i++) {
+ aObj = theListAttr->object(i);
+ std::shared_ptr<GeomAPI_Shape> aShape = SketcherPrs_Tools::getShape(aObj);
+ if (aShape.get() != NULL)
+ drawShape(aShape, thePrs);
+ }
+}
+
#include "SketcherPrs_SensitivePoint.h"
#include <ModelAPI_Feature.h>
+#include <ModelAPI_AttributeRefList.h>
#include <AIS_InteractiveObject.hxx>
#include <GeomAPI_Ax3.h>
void drawShape(const std::shared_ptr<GeomAPI_Shape>& theShape,
const Handle(Prs3d_Presentation)& thePrs) const;
+ /// Draw a list of shapes stored in a RefListAttribute
+ /// \param theListAttr the attribute of reference3s list
+ /// \param thePrs the presentation scene
+ void drawListOfShapes(const std::shared_ptr<ModelAPI_AttributeRefList>& theListAttr,
+ const Handle(Prs3d_Presentation)& thePrs) const;
protected:
/// Constraint feature
aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
aFeature->data()->attribute(SketchPlugin_Point::COORD_ID()));
- else if (aFeature && aFeature->getKind() == SketchPlugin_Circle::ID())
- aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID()));
-
else if (anAttr->attr()) {
aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
}
aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
aFeature->data()->attribute(SketchPlugin_Point::COORD_ID()));
- else if (aFeature && aFeature->getKind() == SketchPlugin_Circle::ID())
- aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID()));
-
else if (anAttr->attr()) {
aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: SketcherPrs_Transformation.cpp
+// Created: 16 February 2015
+// Author: Vitaly SMETANNIKOV
+
+#include "SketcherPrs_Transformation.h"
+#include "SketcherPrs_Tools.h"
+#include "SketcherPrs_PositionMgr.h"
+
+#include <SketchPlugin_Constraint.h>
+#include <ModelAPI_AttributeRefList.h>
+
+#include <Graphic3d_AspectLine3d.hxx>
+#include <Prs3d_Root.hxx>
+
+
+
+IMPLEMENT_STANDARD_HANDLE(SketcherPrs_Transformation, SketcherPrs_SymbolPrs);
+IMPLEMENT_STANDARD_RTTIEXT(SketcherPrs_Transformation, SketcherPrs_SymbolPrs);
+
+static Handle(Image_AlienPixMap) MyPixMap;
+
+SketcherPrs_Transformation::SketcherPrs_Transformation(ModelAPI_Feature* theConstraint,
+ const std::shared_ptr<GeomAPI_Ax3>& thePlane,
+ bool isTranslation)
+ : SketcherPrs_SymbolPrs(theConstraint, thePlane), myIsTranslation(isTranslation)
+{
+}
+
+bool SketcherPrs_Transformation::updatePoints(double theStep) const
+{
+ std::shared_ptr<ModelAPI_Data> aData = myConstraint->data();
+ std::shared_ptr<ModelAPI_AttributeRefList> anAttrB = aData->reflist(SketchPlugin_Constraint::ENTITY_B());
+ if (anAttrB.get() == NULL)
+ return false;
+
+ int aNbB = anAttrB->size();
+ if (aNbB == 0)
+ return false;
+
+ SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
+ myPntArray = new Graphic3d_ArrayOfPoints(aNbB);
+
+ int i;
+ ObjectPtr aObj;
+ gp_Pnt aP1;
+ for (i = 0; i < aNbB; i++) {
+ aObj = anAttrB->object(i);
+ aP1 = aMgr->getPosition(aObj, this, theStep);
+ myPntArray->SetVertice(i + 1, aP1);
+ }
+
+ return true;
+}
+
+void SketcherPrs_Transformation::drawLines(const Handle(Prs3d_Presentation)& thePrs, Quantity_Color theColor) const
+{
+ std::shared_ptr<ModelAPI_Data> aData = myConstraint->data();
+ std::shared_ptr<ModelAPI_AttributeRefList> anAttrB = aData->reflist(SketchPlugin_Constraint::ENTITY_B());
+ if (anAttrB.get() == NULL)
+ return;
+
+ Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup(thePrs);
+
+ Handle(Graphic3d_AspectLine3d) aLineAspect = new Graphic3d_AspectLine3d(theColor, Aspect_TOL_SOLID, 2);
+ aGroup->SetPrimitivesAspect(aLineAspect);
+
+ drawListOfShapes(anAttrB, thePrs);
+}
+
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: SketcherPrs_Transformation.h
+// Created: 16 February 2015
+// Author: Vitaly SMETANNIKOV
+
+#ifndef SketcherPrs_Transformation_H
+#define SketcherPrs_Transformation_H
+
+#include "SketcherPrs_SymbolPrs.h"
+#include <ModelAPI_Feature.h>
+
+
+DEFINE_STANDARD_HANDLE(SketcherPrs_Transformation, SketcherPrs_SymbolPrs)
+
+/**
+* \ingroup GUI
+* A redefinition of standard AIS Interactive Object in order to provide
+* presentation of parallel constraint
+*/
+class SketcherPrs_Transformation: public SketcherPrs_SymbolPrs
+{
+public:
+ /// Constructor
+ /// \param theConstraint a constraint feature
+ /// \param thePlane a coordinate plane of current sketch
+ Standard_EXPORT SketcherPrs_Transformation(ModelAPI_Feature* theConstraint,
+ const std::shared_ptr<GeomAPI_Ax3>& thePlane,
+ bool isTranslation);
+
+ DEFINE_STANDARD_RTTI(SketcherPrs_Transformation)
+protected:
+ virtual const char* iconName() const { return myIsTranslation? "translate.png" : "rotate.png"; }
+
+ /// Redefine this function in order to add additiona lines of constraint base
+ /// \param thePrs a presentation
+ /// \param theColor a color of additiona lines
+ virtual void drawLines(const Handle(Prs3d_Presentation)& thePrs, Quantity_Color theColor) const;
+
+ /// Update myPntArray according to presentation positions
+ /// \return true in case of success
+ virtual bool updatePoints(double theStep) const;
+
+private:
+ bool myIsTranslation;
+};
+
+#endif
\ No newline at end of file
SET(PROJECT_HEADERS
XGUI.h
XGUI_ActionsMgr.h
+ XGUI_ColorDialog.h
XGUI_ContextMenuMgr.h
XGUI_CustomPrs.h
- XGUI_DataTreeModel.h
XGUI_Displayer.h
- XGUI_DocumentDataModel.h
XGUI_ErrorDialog.h
XGUI_ModuleConnector.h
XGUI_ObjectsBrowser.h
XGUI_OperationMgr.h
- XGUI_PartDataModel.h
XGUI_PropertyPanel.h
XGUI_QtEvents.h
XGUI_SalomeConnector.h
SET(PROJECT_SOURCES
XGUI_ActionsMgr.cpp
+ XGUI_ColorDialog.cpp
XGUI_ContextMenuMgr.cpp
XGUI_CustomPrs.cpp
XGUI_Displayer.cpp
- XGUI_DocumentDataModel.cpp
XGUI_ErrorDialog.cpp
XGUI_ModuleConnector.cpp
XGUI_ObjectsBrowser.cpp
XGUI_OperationMgr.cpp
- XGUI_PartDataModel.cpp
XGUI_PropertyPanel.cpp
XGUI_QtEvents.cpp
XGUI_Selection.cpp
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: XGUI_ColorDialog.cpp
+// Created: 27 Apr 2015
+// Author: Natalia ERMOLAEVA
+
+#include <XGUI_ColorDialog.h>
+
+#include <ModelAPI_Tools.h>
+
+#include <QtxColorButton.h>
+
+#include <QLabel>
+#include <QButtonGroup>
+#include <QGridLayout>
+#include <QRadioButton>
+#include <QDialogButtonBox>
+
+XGUI_ColorDialog::XGUI_ColorDialog(QWidget* theParent)
+ : QDialog(theParent)
+{
+ setWindowTitle("Color");
+ QGridLayout* aLay = new QGridLayout(this);
+
+ QRadioButton* aRandomChoiceBtn = new QRadioButton(this);
+ QRadioButton* aColorChoiceBtn = new QRadioButton(this);
+ aColorChoiceBtn->setChecked(true);
+ myButtonGroup = new QButtonGroup(this);
+ myButtonGroup->setExclusive(true);
+ myButtonGroup->addButton(aColorChoiceBtn, 0);
+ myButtonGroup->addButton(aRandomChoiceBtn, 1);
+
+ aLay->addWidget(aColorChoiceBtn, 0, 0);
+ aLay->addWidget(aRandomChoiceBtn, 1, 0);
+
+ myColorButton = new QtxColorButton(this);
+ myColorButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ aLay->addWidget(myColorButton, 0, 1);
+
+ QLabel* aRandomLabel = new QLabel("Random", this);
+ aLay->addWidget(aRandomLabel, 1, 1);
+
+ QDialogButtonBox* aButtons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
+ Qt::Horizontal, this);
+ connect(aButtons, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(aButtons, SIGNAL(rejected()), this, SLOT(reject()));
+ aLay->addWidget(aButtons, 2, 0, 1, 2);
+}
+
+bool XGUI_ColorDialog::isRandomColor() const
+{
+ int anId = myButtonGroup->checkedId();
+
+ return myButtonGroup->checkedId() == 1;
+}
+
+void XGUI_ColorDialog::setColor(const std::vector<int>& theValue)
+{
+ if (theValue.size() != 3)
+ return;
+
+ myColorButton->setColor(QColor(theValue[0], theValue[1], theValue[2]));
+}
+
+std::vector<int> XGUI_ColorDialog::getColor() const
+{
+ std::vector<int> aValues;
+ if (isRandomColor()) {
+ ModelAPI_Tools::findRandomColor(aValues);
+ }
+ else {
+ QColor aColorResult = myColorButton->color();
+ aValues.push_back(aColorResult.red());
+ aValues.push_back(aColorResult.green());
+ aValues.push_back(aColorResult.blue());
+ }
+ return aValues;
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: XGUI_ColorDialog.hxx
+// Created: 27 Apr 2015
+// Author: Natalia ERMOLAEVA
+
+#ifndef XGUI_ColorDialog_H
+#define XGUI_ColorDialog_H
+
+#include "XGUI.h"
+
+#include <QDialog>
+
+class QButtonGroup;
+class QtxColorButton;
+
+/**
+* \ingroup GUI
+* A class of dialog to chose a color. The color can be set in two ways: use a random value or
+* a certain color. There is a radio button to provide this choice. The color button is visualized to
+* select a certain color.
+*/
+class XGUI_ColorDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ /// Constructor
+ /// \param theParent a parent widget for the dialog
+ XGUI_EXPORT XGUI_ColorDialog(QWidget* theParent);
+
+ XGUI_EXPORT virtual ~XGUI_ColorDialog() {};
+
+ /// Returns whether the random state of color is chosen
+ /// \return a boolean value
+ bool isRandomColor() const;
+
+ /// Initializes the dialog with the given value. Set choice on certain value and fill it by.
+ /// \param theValue an RGB components value
+ void setColor(const std::vector<int>& theValue);
+
+ /// Returns a container with the current color value. These are tree int values for RGB definition.
+ /// These value is depend on the random choice and eighter a next random color or a certain color.
+ /// \return a vector of values
+ std::vector<int> getColor() const;
+
+private:
+ QButtonGroup* myButtonGroup; /// a group, contained random and certain color radio button choice
+ QtxColorButton* myColorButton; /// a control to select a color
+};
+
+#endif
#include "XGUI_ViewerProxy.h"
#include "XGUI_Selection.h"
#include "XGUI_SalomeConnector.h"
-#include "XGUI_Tools.h"
#include <AppElements_MainWindow.h>
#include <ModelAPI_Data.h>
#include <ModelAPI_AttributeDocRef.h>
#include <ModelAPI_Object.h>
-#include <ModelAPI_ResultPart.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_ResultGroup.h>
#include <ModelAPI_ResultParameter.h>
#include <ModuleBase_IModule.h>
+#include <ModuleBase_Tools.h>
#include <QAction>
#include <QContextMenuEvent>
void XGUI_ContextMenuMgr::createActions()
{
- QAction* aAction = new QAction(QIcon(":pictures/edit.png"), tr("Edit..."), this);
- addAction("EDIT_CMD", aAction);
-
- aAction = new QAction(QIcon(":pictures/activate.png"), tr("Activate"), this);
- addAction("ACTIVATE_PART_CMD", aAction);
-
- aAction = new QAction(QIcon(":pictures/assembly.png"), tr("Deactivate"), this);
- addAction("DEACTIVATE_PART_CMD", aAction);
-
- aAction = new QAction(QIcon(":pictures/delete.png"), tr("Delete"), this);
+ QAction* aAction = new QAction(QIcon(":pictures/delete.png"), tr("Delete"), this);
QMainWindow* aDesktop = myWorkshop->mainWindow();
if (!aDesktop)
aDesktop = myWorkshop->salomeConnector()->desktop();
bool hasResult = false;
bool hasFeature = false;
bool hasParameter = false;
- XGUI_Tools::checkObjects(aObjects, hasResult, hasFeature, hasParameter);
+ ModuleBase_Tools::checkObjects(aObjects, hasResult, hasFeature, hasParameter);
//Process Feature
if (aSelected == 1) {
ObjectPtr aObject = aObjects.first();
if (aObject) {
- ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);
- if (aPart) {
- if (aMgr->activeDocument() == aPart->partDoc())
- aMenu->addAction(action("DEACTIVATE_PART_CMD"));
- else
- aMenu->addAction(action("ACTIVATE_PART_CMD"));
- } else if (hasFeature && aObject->document() == aMgr->activeDocument()) {
- aMenu->addAction(action("EDIT_CMD"));
- } else {
- if (aDisplayer->isVisible(aObject)) {
+ if (!hasFeature) {
+ if (aObject->isDisplayed()) {
if (aDisplayer->canBeShaded(aObject)) {
if (aDisplayer->displayMode(aObject) == XGUI_Displayer::Shading)
aMenu->addAction(action("WIREFRAME_CMD"));
}
aMenu->addSeparator();
aMenu->addAction(action("HIDE_CMD"));
- } else if (!hasParameter) {
+ } else if (hasResult && (!hasParameter)) {
aMenu->addAction(action("SHOW_CMD"));
}
- if (hasParameter)
- aMenu->addAction(action("EDIT_CMD"));
- else
+ if (!(hasParameter || hasFeature))
aMenu->addAction(action("SHOW_ONLY_CMD"));
}
- } else { // If feature is 0 the it means that selected root object (document)
- if (aMgr->activeDocument() != aMgr->moduleDocument())
- aMenu->addAction(action("ACTIVATE_PART_CMD"));
- }
+ }
} else {
if (hasResult && (!hasParameter)) {
aMenu->addAction(action("SHOW_CMD"));
aMenu->addAction(action("COLOR_CMD"));
aMenu->addSeparator();
+ ModuleBase_IModule* aModule = myWorkshop->module();
+ if (aModule) {
+ aModule->addObjectBrowserMenu(aMenu);
+ aMenu->addSeparator();
+ }
aMenu->addActions(myWorkshop->objectBrowser()->actions());
- ModuleBase_IModule* aModule = myWorkshop->module();
- if (aModule)
- aModule->addObjectBrowserItems(aMenu);
if (aMenu->actions().size() > 0) {
return aMenu;
QMenu* XGUI_ContextMenuMgr::viewerMenu() const
{
QMenu* aMenu = new QMenu();
- addViewerItems(aMenu);
+ addViewerMenu(aMenu);
if (aMenu->actions().size() > 0) {
return aMenu;
}
return 0;
}
-void XGUI_ContextMenuMgr::addViewerItems(QMenu* theMenu) const
+void XGUI_ContextMenuMgr::addViewerMenu(QMenu* theMenu) const
{
bool aIsDone = false;
ModuleBase_IModule* aModule = myWorkshop->module();
if (aModule)
- aIsDone = aModule->addViewerItems(theMenu, myActions);
+ aIsDone = aModule->addViewerMenu(theMenu, myActions);
if (!aIsDone) {
XGUI_SelectionMgr* aSelMgr = myWorkshop->selector();
QObjectPtrList aObjects = aSelMgr->selection()->selectedObjects();
if (aObjects.size() > 0) {
- //if (aObjects.size() == 1)
- // theMenu->addAction(action("EDIT_CMD"));
bool isVisible = false;
bool isShading = false;
bool canBeShaded = false;
foreach(ObjectPtr aObject, aObjects)
{
ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObject);
- if (aRes && myWorkshop->displayer()->isVisible(aRes)) {
+ if (aRes && aRes->isDisplayed()) {
isVisible = true;
canBeShaded = myWorkshop->displayer()->canBeShaded(aObject);
isShading = (myWorkshop->displayer()->displayMode(aObject) == XGUI_Displayer::Shading);
theMenu->addAction(action("HIDE_CMD"));
} else
theMenu->addAction(action("SHOW_CMD"));
- //theMenu->addAction(action("DELETE_CMD"));
}
if (myWorkshop->displayer()->objectsCount() > 0)
theMenu->addAction(action("HIDEALL_CMD"));
/// Add menu atems for viewer into the given menu (used in SALOME mode)
/// \param theMenu a popup menu to be shown in the viewer
- void addViewerItems(QMenu* theMenu) const;
+ void addViewerMenu(QMenu* theMenu) const;
signals:
/// Signal aabout triggered action
#include <XGUI_CustomPrs.h>
#include <ModelAPI_AttributeIntArray.h>
+#include <ModelAPI_Session.h>
#include <Config_PropManager.h>
#include <Events_Error.h>
#include <vector>
+#include <QColor>
void getColor(ResultPtr theResult, std::vector<int>& theColor)
if (aColor.empty())
getDefaultColor(theResult, thePrs, aColor);
+ SessionPtr aMgr = ModelAPI_Session::get();
+ if (aMgr->activeDocument() != theResult->document()) {
+ QColor aQColor(aColor[0], aColor[1], aColor[2]);
+ QColor aNewColor = QColor::fromHsvF(aQColor.hueF(), aQColor.saturationF()/3., aQColor.valueF());
+ aColor[0] = aNewColor.red();
+ aColor[1] = aNewColor.green();
+ aColor[2] = aNewColor.blue();
+ }
return !aColor.empty() && thePrs->setColor(aColor[0], aColor[1], aColor[2]);
}
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
-
-#ifndef XGUI_DataTreeModel_H
-#define XGUI_DataTreeModel_H
-
-#include "XGUI.h"
-
-#include <ModelAPI_Document.h>
-#include <ModelAPI_Feature.h>
-#include <ModelAPI_ResultPart.h>
-
-#include <QAbstractItemModel>
-#include <QColor>
-
-/**\class XGUI_FeaturesModel
- * \ingroup GUI
- * \brief Abstaract class of model object which operates with features data.
- */
-class XGUI_EXPORT XGUI_FeaturesModel : public QAbstractItemModel
-{
- public:
- /// Constructor
- /// \param theParent a parent object
- XGUI_FeaturesModel(QObject* theParent)
- : QAbstractItemModel(theParent),
- myItemsColor(Qt::black)
- {
- }
-
- //! Returns Feature object by the given Model index.
- //! Returns 0 if the given index is not index of a feature
- /// \param theIndex a model index
- virtual ObjectPtr object(const QModelIndex& theIndex) const = 0;
-
- //! Returns QModelIndex which corresponds to the given feature
- //! If the feature is not found then index is not valid
- virtual QModelIndex objectIndex(const ObjectPtr& theFeature) const = 0;
-
- //! Returns parent index of the given feature
- virtual QModelIndex findParent(const ObjectPtr& theObject) const = 0;
-
- //! Returns index corresponded to the group
- //! \param theGroup a group name
- virtual QModelIndex findGroup(const std::string& theGroup) const = 0;
-
- //! Set color of items
- void setItemsColor(const QColor& theColor)
- {
- myItemsColor = theColor;
- }
-
- //! Returns color of items
- QColor itemsColor() const
- {
- return myItemsColor;
- }
-
- protected:
- /// Color of items
- QColor myItemsColor;
-};
-
-/**\class XGUI_PartModel
- * \ingroup GUI
- * \brief Abstaract class of model object which operates with parts data.
- */
-class XGUI_PartModel : public XGUI_FeaturesModel
-{
- public:
- /// Constructor
- /// \param theParent a parent object
- XGUI_PartModel(QObject* theParent)
- : XGUI_FeaturesModel(theParent)
- {
- }
-
- /// Set part id
- /// \param theId a new id
- void setPartId(int theId)
- {
- myId = theId;
- }
-
- //! Returns true if the given document is a sub-document of this tree
- //! \param theDoc a document to check
- virtual bool hasDocument(const DocumentPtr& theDoc) const = 0;
-
- //! Return a Part object
- virtual ResultPartPtr part() const = 0;
-
- protected:
- //! Id of the current part object in the document
- int myId;
-};
-
-#endif
//#define DEBUG_ACTIVATE
//#define DEBUG_FEATURE_REDISPLAY
//#define DEBUG_SELECTION_FILTERS
+//#define DEBUG_USE_CLEAR_OUTDATED_SELECTION
// Workaround for bug #25637
void displayedObjects(const Handle(AIS_InteractiveContext)& theAIS, AIS_ListOfInteractive& theList)
AISObjectPtr anObj = myResult2AISObjectMap[theObject];
Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
aContext->Deactivate(anAIS);
+#ifdef DEBUG_USE_CLEAR_OUTDATED_SELECTION
+ aContext->LocalContext()->ClearOutdatedSelection(anAIS, true);
+ updateViewer();
+#endif
}
}
for(aLIt.Initialize(aPrsList); aLIt.More(); aLIt.Next()){
anAISIO = aLIt.Value();
aContext->Deactivate(anAISIO);
+#ifdef DEBUG_USE_CLEAR_OUTDATED_SELECTION
+ aContext->LocalContext()->ClearOutdatedSelection(anAISIO, true);
+ updateViewer();
+#endif
}
}
return aModes.Extent() > 0;
}
-void XGUI_Displayer::setSelected(const QObjectPtrList& theResults, const bool isUpdateViewer)
+void XGUI_Displayer::setSelected(const QList<ModuleBase_ViewerPrs>& theValues, bool isUpdateViewer)
{
Handle(AIS_InteractiveContext) aContext = AISContext();
if (aContext.IsNull())
if (aContext->HasOpenedContext()) {
aContext->UnhilightSelected();
aContext->ClearSelected();
- foreach(ObjectPtr aResult, theResults) {
- if (isVisible(aResult)) {
- AISObjectPtr anObj = myResult2AISObjectMap[aResult];
- Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
- if (!anAIS.IsNull())
- aContext->SetSelected(anAIS, false);
+ //if (aSelected.size() > 0) {
+ foreach (ModuleBase_ViewerPrs aPrs, theValues) {
+ const TopoDS_Shape& aShape = aPrs.shape();
+ if (!aShape.IsNull()) {
+ aContext->AddOrRemoveSelected(aShape, false);
+ } else {
+ ObjectPtr anObject = aPrs.object();
+ ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
+ if (aResult.get() && isVisible(aResult)) {
+ AISObjectPtr anObj = myResult2AISObjectMap[aResult];
+ Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
+ if (!anAIS.IsNull()) {
+ // The methods are replaced in order to provide multi-selection, e.g. restore selection
+ // by activating multi selector widget. It also gives an advantage that the multi
+ // selection in OB gives multi-selection in the viewer
+ //aContext->SetSelected(anAIS, false);
+ // The selection in the context was cleared, so the method sets the objects are selected
+ aContext->AddOrRemoveSelected(anAIS, false);
+ }
+ }
}
}
} else {
aContext->UnhilightCurrents();
aContext->ClearCurrents();
- foreach(ObjectPtr aResult, theResults) {
- if (isVisible(aResult)) {
+ foreach (ModuleBase_ViewerPrs aPrs, theValues) {
+ ObjectPtr anObject = aPrs.object();
+ ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
+ if (aResult.get() && isVisible(aResult)) {
AISObjectPtr anObj = myResult2AISObjectMap[aResult];
Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
if (!anAIS.IsNull())
updateViewer();
}
-
void XGUI_Displayer::clearSelected()
{
Handle(AIS_InteractiveContext) aContext = AISContext();
return aWasEnabled;
}
-void XGUI_Displayer::updateViewer()
+void XGUI_Displayer::updateViewer() const
{
Handle(AIS_InteractiveContext) aContext = AISContext();
if (!aContext.IsNull() && myEnableUpdateViewer)
aContext->ActivatedModes(theIO, aTColModes);
TColStd_ListIteratorOfListOfInteger itr( aTColModes );
QIntList aModesActivatedForIO;
+ //bool isDeactivated = false;
for (; itr.More(); itr.Next() ) {
Standard_Integer aMode = itr.Value();
if (!theModes.contains(aMode)) {
qDebug(QString("deactivate: %1").arg(aMode).toStdString().c_str());
#endif
aContext->Deactivate(theIO, aMode);
+ //isDeactivated = true;
}
else {
aModesActivatedForIO.append(aMode);
#endif
}
}
+#ifdef DEBUG_USE_CLEAR_OUTDATED_SELECTION
+ if (isDeactivated) {
+ aContext->LocalContext()->ClearOutdatedSelection(theIO, true);
+ updateViewer();
+ }
+#endif
// loading the interactive object allowing the decomposition
if (aTColModes.IsEmpty())
aContext->Load(theIO, -1, true);
void redisplay(ObjectPtr theObject, bool isUpdateViewer = true);
/**
- * Add presentations which corresponds to the given features to current selection
- * \param theFeatures a list of features to be selected
+ * Add presentations to current selection. It unhighlight and deselect the current selection.
+ * The shape and result components are processed in the values. If the presentation shape is not
+ * empty, select it, otherwise select the result.
+ * \param theValues a list of presentation to be selected
* \param isUpdateViewer the parameter whether the viewer should be update immediatelly
*/
- void setSelected(const QObjectPtrList& theFeatures, bool isUpdateViewer = true);
+ void setSelected(const QList<ModuleBase_ViewerPrs>& theValues, bool isUpdateViewer = true);
/// Unselect all objects
bool enableUpdateViewer(const bool isEnabled);
/// Updates the viewer
- void updateViewer();
+ void updateViewer() const;
/// Searches the interactive object by feature
/// \param theObject the object or presentable feature
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
-
-#include "XGUI_DocumentDataModel.h"
-#include "XGUI_PartDataModel.h"
-#include "XGUI_Workshop.h"
-#include "XGUI_Tools.h"
-
-#include <ModelAPI_Session.h>
-#include <ModelAPI_Document.h>
-#include <ModelAPI_Feature.h>
-#include <ModelAPI_Data.h>
-#include <ModelAPI_ResultPart.h>
-#include <ModelAPI_Events.h>
-#include <ModelAPI_Object.h>
-
-#include <Events_Loop.h>
-
-#include <Config_FeatureMessage.h>
-
-#include <QIcon>
-#include <QString>
-#include <QBrush>
-
-#include <set>
-
-#define ACTIVE_COLOR QColor(0,72,140)
-#define PASSIVE_COLOR Qt::black
-
-XGUI_DocumentDataModel::XGUI_DocumentDataModel(QObject* theParent)
- : QAbstractItemModel(theParent),
- myActivePart(0)
-{
- // Register in event loop
- //Events_Loop* aLoop = Events_Loop::loop();
- //aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
- //aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
- //aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
-
- // Create a top part of data tree model
- myModel = new XGUI_TopDataModel(this);
- myModel->setItemsColor(ACTIVE_COLOR);
-}
-
-XGUI_DocumentDataModel::~XGUI_DocumentDataModel()
-{
- clearModelIndexes();
- clearSubModels();
-}
-
-void XGUI_DocumentDataModel::processEvent(const std::shared_ptr<Events_Message>& theMessage)
-{
- DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-
- // Created object event *******************
- if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
- std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
- std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
- std::set<ObjectPtr> aObjects = aUpdMsg->objects();
-
- std::set<ObjectPtr>::const_iterator aIt;
- for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
- ObjectPtr aObject = (*aIt);
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
- if (aFeature && (!aFeature->isInHistory()))
- continue;
-
- DocumentPtr aDoc = aObject->document();
- if (aDoc == aRootDoc) { // If root objects
- if (aObject->groupName() == ModelAPI_ResultPart::group()) { // Update only Parts group
- // Add a new part
- int aStart = myPartModels.size();
- XGUI_PartDataModel* aModel = new XGUI_PartDataModel(this);
- aModel->setPartId(myPartModels.count());
- myPartModels.append(aModel);
- insertRow(aStart, partFolderNode());
- } else { // Update top groups (other except parts
- QModelIndex aIndex = myModel->findParent(aObject);
- int aStart = myModel->rowCount(aIndex) - 1;
- if (aStart < 0)
- aStart = 0;
- aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
- insertRow(aStart, aIndex);
- }
- } else { // if sub-objects of first level nodes
- XGUI_PartModel* aPartModel = 0;
- foreach (XGUI_PartModel* aPart, myPartModels) {
- if (aPart->hasDocument(aDoc)) {
- aPartModel = aPart;
- break;
- }
- }
- if (aPartModel) {
- QModelIndex aIndex = aPartModel->findParent(aObject);
- int aStart = aPartModel->rowCount(aIndex); // check this index
- aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
- insertRow(aStart, aIndex);
- } else
- reset();
- }
- }
- // Deleted object event ***********************
- } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
- std::shared_ptr<ModelAPI_ObjectDeletedMessage> aUpdMsg =
- std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
- DocumentPtr aDoc = aUpdMsg->document();
- std::set<std::string> aGroups = aUpdMsg->groups();
-
- std::set<std::string>::const_iterator aIt;
- for (aIt = aGroups.begin(); aIt != aGroups.end(); ++aIt) {
- std::string aGroup = (*aIt);
- if (aDoc == aRootDoc) { // If root objects
- if (aGroup == ModelAPI_ResultPart::group()) { // Update only Parts group
- int aStart = myPartModels.size() - 1;
- if (aStart >= 0) {// MPV: this could be reproduced on close
- removeSubModel(aStart);
- removeRow(aStart, partFolderNode());
- if (myActivePart && (!isPartSubModel(myActivePart))) {
- myActivePart = 0;
- myActivePartIndex = QModelIndex();
- myModel->setItemsColor(ACTIVE_COLOR);
- }
- }
- } else { // Update top groups (other except parts
- QModelIndex aIndex = myModel->findGroup(aGroup);
- int aStart = myModel->rowCount(aIndex);
- aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
- removeRow(aStart, aIndex);
- }
- } else {
- XGUI_PartModel* aPartModel = 0;
- foreach (XGUI_PartModel* aPart, myPartModels) {
- if (aPart->hasDocument(aDoc)) {
- aPartModel = aPart;
- break;
- }
- }
- if (aPartModel) {
- QModelIndex aIndex = aPartModel->findGroup(aGroup);
- int aStart = aPartModel->rowCount(aIndex);
- aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
- removeRow(aStart, aIndex);
- }
- }
- }
- // Deleted object event ***********************
- } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
- //std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg = std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
- //ObjectPtr aFeature = aUpdMsg->feature();
- //DocumentPtr aDoc = aFeature->document();
-
- // TODO: Identify the necessary index by the modified feature
- QModelIndex aIndex;
- emit dataChanged(aIndex, aIndex);
-
- // Reset whole tree **************************
- } else {
- rebuildDataTree();
- }
-}
-
-void XGUI_DocumentDataModel::rebuildDataTree()
-{
- DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-
- beginResetModel();
- clearModelIndexes();
-
- int aNbParts = aRootDoc->size(ModelAPI_ResultPart::group());
- if (myPartModels.size() != aNbParts) { // resize internal models
- while (myPartModels.size() > aNbParts) {
- delete myPartModels.last();
- myPartModels.removeLast();
- }
- while (myPartModels.size() < aNbParts) {
- myPartModels.append(new XGUI_PartDataModel(this));
- }
- for (int i = 0; i < myPartModels.size(); i++)
- myPartModels.at(i)->setPartId(i);
- }
- endResetModel();
-}
-
-QVariant XGUI_DocumentDataModel::data(const QModelIndex& theIndex, int theRole) const
-{
- if (!theIndex.isValid())
- return QVariant();
- switch (theIndex.internalId()) {
- case PartsFolder:
- switch (theRole) {
- case Qt::DisplayRole:
- return tr("Parts") + QString(" (%1)").arg(rowCount(theIndex));
- case Qt::DecorationRole:
- return QIcon(":pictures/constr_folder.png");
- case Qt::ToolTipRole:
- return tr("Parts folder");
- case Qt::ForegroundRole:
- if (myActivePart)
- return QBrush(PASSIVE_COLOR);
- else
- return QBrush(ACTIVE_COLOR);
- default:
- return QVariant();
- }
- break;
- case HistoryNode:
- {
- int aOffset = historyOffset();
- DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
- ObjectPtr aObj = aRootDoc->object(ModelAPI_Feature::group(), theIndex.row() - aOffset);
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
- if (!aFeature)
- return QVariant();
- switch (theRole) {
- case Qt::DisplayRole:
- if (aFeature)
- return aFeature->data()->name().c_str();
- else
- return QVariant();
- case Qt::DecorationRole:
- return XGUI_Workshop::featureIcon(aFeature);
- case Qt::ToolTipRole:
- return tr("Feature object");
- case Qt::ForegroundRole:
- if (myActivePart)
- return QBrush(PASSIVE_COLOR);
- else
- return QBrush(ACTIVE_COLOR);
- default:
- return QVariant();
- }
- }
- break;
- }
- QModelIndex aParent = theIndex.parent();
- if (aParent.isValid() && (aParent.internalId() == PartsFolder)) {
- return myPartModels.at(theIndex.row())->data(QModelIndex(), theRole);
- }
- return toSourceModelIndex(theIndex)->data(theRole);
-}
-
-QVariant XGUI_DocumentDataModel::headerData(int theSection, Qt::Orientation theOrient,
- int theRole) const
-{
- return QVariant();
-}
-
-int XGUI_DocumentDataModel::rowCount(const QModelIndex& theParent) const
-{
- if (!theParent.isValid()) {
- DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
- // Size of external models
- int aVal = historyOffset();
- // Plus history size
- aVal += aRootDoc->size(ModelAPI_Feature::group());
- return aVal;
- }
- if (theParent.internalId() == PartsFolder) {
- int aSize = myPartModels.size();
- return myPartModels.size();
- }
- if (theParent.internalId() == HistoryNode) {
- return 0;
- }
- QModelIndex* aParent = toSourceModelIndex(theParent);
- const QAbstractItemModel* aModel = aParent->model();
- if (!isSubModel(aModel))
- return 0;
-
- /*if (isPartSubModel(aModel)) {
- if (aModel != myActivePart)
- return 0;
- }*/
- return aModel->rowCount(*aParent);
-}
-
-int XGUI_DocumentDataModel::columnCount(const QModelIndex& theParent) const
-{
- return 1;
-}
-
-QModelIndex XGUI_DocumentDataModel::index(int theRow, int theColumn,
- const QModelIndex& theParent) const
-{
- QModelIndex aIndex;
- if (!theParent.isValid()) {
- int aOffs = myModel->rowCount();
- if (theRow < aOffs) {
- aIndex = myModel->index(theRow, theColumn, theParent);
- aIndex = createIndex(theRow, theColumn, (void*) getModelIndex(aIndex));
- } else {
- if (theRow == aOffs) // Create Parts node
- aIndex = partFolderNode();
- else
- // create history node
- aIndex = createIndex(theRow, theColumn, HistoryNode);
- }
- } else {
- if (theParent.internalId() == PartsFolder) {
- aIndex = myPartModels.at(theRow)->index(0, theColumn, QModelIndex());
- } else {
- QModelIndex* aParent = (QModelIndex*) theParent.internalPointer();
- aIndex = aParent->model()->index(theRow, theColumn, (*aParent));
- }
- aIndex = createIndex(theRow, theColumn, (void*) getModelIndex(aIndex));
- }
- return aIndex;
-}
-
-QModelIndex XGUI_DocumentDataModel::parent(const QModelIndex& theIndex) const
-{
- if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
- return QModelIndex();
-
- QModelIndex* aIndex = toSourceModelIndex(theIndex);
- const QAbstractItemModel* aModel = aIndex->model();
- if (!isSubModel(aModel))
- return QModelIndex();
-
- if (isPartSubModel(aModel)) {
- if (!aModel->parent(*aIndex).isValid()) {
- return partFolderNode();
- }
- }
-
- QModelIndex aIndex1 = aModel->parent(*aIndex);
- if (aIndex1.isValid())
- return createIndex(aIndex1.row(), aIndex1.column(), (void*) getModelIndex(aIndex1));
- return aIndex1;
-}
-
-bool XGUI_DocumentDataModel::hasChildren(const QModelIndex& theParent) const
-{
- if (!theParent.isValid())
- return true;
- return rowCount(theParent) > 0;
-}
-
-QModelIndex* XGUI_DocumentDataModel::toSourceModelIndex(const QModelIndex& theProxy) const
-{
- QModelIndex* aIndexPtr = static_cast<QModelIndex*>(theProxy.internalPointer());
- return aIndexPtr;
-}
-
-QModelIndex* XGUI_DocumentDataModel::findModelIndex(const QModelIndex& theIndex) const
-{
- QList<QModelIndex*>::const_iterator aIt;
- for (aIt = myIndexes.constBegin(); aIt != myIndexes.constEnd(); ++aIt) {
- QModelIndex* aIndex = (*aIt);
- if ((*aIndex) == theIndex)
- return aIndex;
- }
- return 0;
-}
-
-QModelIndex* XGUI_DocumentDataModel::getModelIndex(const QModelIndex& theIndex) const
-{
- QModelIndex* aIndexPtr = findModelIndex(theIndex);
- if (!aIndexPtr) {
- aIndexPtr = new QModelIndex(theIndex);
- XGUI_DocumentDataModel* that = (XGUI_DocumentDataModel*) this;
- that->myIndexes.append(aIndexPtr);
- }
- return aIndexPtr;
-}
-
-void XGUI_DocumentDataModel::clearModelIndexes()
-{
- foreach (QModelIndex* aIndex, myIndexes)
- delete aIndex;
- myIndexes.clear();
-}
-
-void XGUI_DocumentDataModel::clearSubModels()
-{
- foreach (XGUI_PartModel* aPart, myPartModels)
- delete aPart;
- myPartModels.clear();
-}
-
-ObjectPtr XGUI_DocumentDataModel::object(const QModelIndex& theIndex) const
-{
- if (theIndex.internalId() == PartsFolder)
- return ObjectPtr();
- if (theIndex.internalId() == HistoryNode) {
- DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
- int aOffset = historyOffset();
- return aRootDoc->object(ModelAPI_Feature::group(), theIndex.row() - aOffset);
- }
- QModelIndex* aIndex = toSourceModelIndex(theIndex);
- if (!isSubModel(aIndex->model()))
- return ObjectPtr();
-
- const XGUI_FeaturesModel* aModel = dynamic_cast<const XGUI_FeaturesModel*>(aIndex->model());
- return aModel->object(*aIndex);
-}
-
-bool XGUI_DocumentDataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
-{
- beginInsertRows(theParent, theRow, theRow + theCount - 1);
- //endInsertRows();
-
- // Update history
- QModelIndex aRoot;
- int aRow = rowCount(aRoot);
- beginInsertRows(aRoot, aRow, aRow);
- endInsertRows();
-
- return true;
-}
-
-bool XGUI_DocumentDataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
-{
- beginRemoveRows(theParent, theRow, theRow + theCount - 1);
- endRemoveRows();
- return true;
-}
-
-void XGUI_DocumentDataModel::removeSubModel(int theModelId)
-{
- XGUI_PartModel* aModel = myPartModels.at(theModelId);
- QIntList aToRemove;
- for (int i = 0; i < myIndexes.size(); i++) {
- if (myIndexes.at(i)->model() == aModel)
- aToRemove.append(i);
- }
- int aId;
- while (aToRemove.size() > 0) {
- aId = aToRemove.last();
- delete myIndexes.at(aId);
- myIndexes.removeAt(aId);
- aToRemove.removeLast();
- }
- delete aModel;
- myPartModels.removeAt(theModelId);
-}
-
-bool XGUI_DocumentDataModel::isSubModel(const QAbstractItemModel* theModel) const
-{
- if (theModel == myModel)
- return true;
- return isPartSubModel(theModel);
-}
-
-bool XGUI_DocumentDataModel::isPartSubModel(const QAbstractItemModel* theModel) const
-{
- return myPartModels.contains((XGUI_PartModel*) theModel);
-}
-
-QModelIndex XGUI_DocumentDataModel::partFolderNode() const
-{
- int aPos = myModel->rowCount(QModelIndex());
- return createIndex(aPos, columnCount() - 1, PartsFolder);
-}
-
-int XGUI_DocumentDataModel::historyOffset() const
-{
- // Nb of rows of top model + Parts folder
- return myModel->rowCount(QModelIndex()) + 1;
-}
-
-bool XGUI_DocumentDataModel::activatedIndex(const QModelIndex& theIndex)
-{
- if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
- return false;
-
- QModelIndex* aIndex = toSourceModelIndex(theIndex);
- if (!aIndex)
- return false;
-
- const QAbstractItemModel* aModel = aIndex->model();
-
- if (isPartSubModel(aModel)) {
- // if this is root node (Part item index)
- if (!aIndex->parent().isValid()) {
- if (myActivePart)
- myActivePart->setItemsColor(PASSIVE_COLOR);
-
- if (myActivePart == aModel) {
- myActivePart = 0;
- myActivePartIndex = QModelIndex();
- } else {
- myActivePart = (XGUI_PartModel*)aModel;
- myActivePartIndex = theIndex;
- }
-
- if (myActivePart) {
- myActivePart->setItemsColor(ACTIVE_COLOR);
- myModel->setItemsColor(PASSIVE_COLOR);
- } else
- myModel->setItemsColor(ACTIVE_COLOR);
- return true;
- }
- }
- return false;
-}
-
-ResultPartPtr XGUI_DocumentDataModel::activePart() const
-{
- if (myActivePart)
- return myActivePart->part();
- return ResultPartPtr();
-}
-
-void XGUI_DocumentDataModel::deactivatePart()
-{
- if (myActivePart)
- myActivePart->setItemsColor(PASSIVE_COLOR);
- myActivePart = 0;
- myActivePartIndex = QModelIndex();
- myModel->setItemsColor(ACTIVE_COLOR);
- }
-
-Qt::ItemFlags XGUI_DocumentDataModel::flags(const QModelIndex& theIndex) const
-{
- Qt::ItemFlags aFlags = QAbstractItemModel::flags(theIndex);
- if (object(theIndex)) {
- aFlags |= Qt::ItemIsEditable;
- }
- return aFlags;
-}
-
-QModelIndex XGUI_DocumentDataModel::partIndex(const ResultPartPtr& theObject) const
-{
- int aRow = -1;
- XGUI_PartModel* aModel = 0;
- foreach (XGUI_PartModel* aPartModel, myPartModels)
- {
- aRow++;
- if (aPartModel->part() == theObject) {
- aModel = aPartModel;
- break;
- }
- }
- if (aModel) {
- return createIndex(aRow, 0, (void*) getModelIndex(aModel->index(0, 0, QModelIndex())));
- }
- return QModelIndex();
-}
-
-QModelIndex XGUI_DocumentDataModel::objectIndex(const ObjectPtr theObject) const
-{
- // Check that this feature belongs to root document
- DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
- DocumentPtr aDoc = theObject->document();
- if (aDoc == aRootDoc) {
- // This feature belongs to histrory or top model
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
- if (aFeature) {
- int aId;
- int aNb = aRootDoc->size(ModelAPI_Feature::group());
- for (aId = 0; aId < aNb; aId++) {
- if (theObject == aRootDoc->object(ModelAPI_Feature::group(), aId))
- break;
- }
- if (aId < aNb)
- return index(aId + historyOffset(), 0, QModelIndex());
- } else {
- QModelIndex aIndex = myModel->objectIndex(theObject);
- return
- aIndex.isValid() ?
- createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex)) :
- QModelIndex();
- }
- } else {
- XGUI_PartModel* aPartModel = 0;
- foreach(XGUI_PartModel* aModel, myPartModels)
- {
- if (aModel->hasDocument(aDoc)) {
- aPartModel = aModel;
- break;
- }
- }
- if (aPartModel) {
- QModelIndex aIndex = aPartModel->objectIndex(theObject);
- return
- aIndex.isValid() ?
- createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex)) :
- QModelIndex();
- }
- }
- return QModelIndex();
-}
-
-
-void XGUI_DocumentDataModel::clear()
-{
- clearModelIndexes();
- clearSubModels();
- myActivePart = 0;
- myActivePartIndex = QModelIndex();
- myModel->setItemsColor(ACTIVE_COLOR);
-}
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
-
-#ifndef XGUI_DocumentDataModel_H
-#define XGUI_DocumentDataModel_H
-
-#include "XGUI.h"
-#include <ModuleBase_Definitions.h>
-#include <ModelAPI_ResultPart.h>
-
-#include <Events_Listener.h>
-
-#include <QAbstractItemModel>
-#include <QList>
-
-class ModelAPI_Document;
-class XGUI_PartModel;
-class XGUI_TopDataModel;
-
-/**\class XGUI_DocumentDataModel
- * \ingroup GUI
- * \brief This is a proxy data model for Object Browser (QTreeView).
- * It contains several sub-models for generation of each sub-part of data tree.
- */
-class XGUI_EXPORT XGUI_DocumentDataModel : public QAbstractItemModel, public Events_Listener
-{
-Q_OBJECT
- public:
- /// Constructor
- /// \param theParent a parent object
- XGUI_DocumentDataModel(QObject* theParent);
- virtual ~XGUI_DocumentDataModel();
-
- /// Event Listener method
- /// \param theMessage an event message
- virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
-
- /// Returns the data stored under the given role for the item referred to by the index.
- /// \param theIndex a model index
- /// \param theRole a data role (see Qt::ItemDataRole)
- virtual QVariant data(const QModelIndex& theIndex, int theRole) const;
-
- /// Returns the data for the given role and section in the header with the specified orientation.
- /// \param theSection a section
- /// \param theOrient an orientation
- /// \param theRole a data role (see Qt::ItemDataRole)
- virtual QVariant headerData(int theSection, Qt::Orientation theOrient, int theRole =
- Qt::DisplayRole) const;
-
- /// Returns the number of rows under the given parent. When the parent is valid it means that
- /// rowCount is returning the number of children of parent.
- /// \param theParent a parent model index
- virtual int rowCount(const QModelIndex& theParent = QModelIndex()) const;
-
- /// Returns the number of columns for the children of the given parent.
- /// It has a one column
- /// \param theParent a parent model index
- virtual int columnCount(const QModelIndex& theParent = QModelIndex()) const;
-
- /// Returns the index of the item in the model specified by the given row, column and parent index.
- /// \param theRow a row
- /// \param theColumn a column
- /// \param theParent a parent model index
- virtual QModelIndex index(int theRow, int theColumn, const QModelIndex &theParent =
- QModelIndex()) const;
-
- /// Returns the parent of the model item with the given index.
- /// If the item has no parent, an invalid QModelIndex is returned.
- /// \param theIndex a model index
- virtual QModelIndex parent(const QModelIndex& theIndex) const;
-
- /// Returns true if parent has any children; otherwise returns false.
- /// \param theParent a parent model index
- virtual bool hasChildren(const QModelIndex& theParent = QModelIndex()) const;
-
- /// Inserts count rows into the model before the given row.
- /// Items in the new row will be children of the item represented by the parent model index.
- /// \param theRow a start row
- /// \param theCount a nember of rows to insert
- /// \param theParent a parent model index
- bool insertRows(int theRow, int theCount, const QModelIndex& theParent = QModelIndex());
-
- /// Removes count rows starting with the given row under parent parent from the model.
- /// \param theRow a start row
- /// \param theCount a nember of rows to remove
- /// \param theParent a parent model index
- bool removeRows(int theRow, int theCount, const QModelIndex& theParent = QModelIndex());
-
- /// Returns the item flags for the given index.
- /// \param theIndex a model index
- Qt::ItemFlags flags(const QModelIndex& theIndex) const;
-
- //! Returns an object by the given Model index.
- //! Returns 0 if the given index is not index of an object
- ObjectPtr object(const QModelIndex& theIndex) const;
-
- //! Returns index of the object
- //! \param theObject object to find
- QModelIndex objectIndex(const ObjectPtr theObject) const;
-
- //! Returns QModelIndex which corresponds to the given part
- //! If the object is not found then index is not valid
- //! \param thePart a part for analysis
- QModelIndex partIndex(const ResultPartPtr& thePart) const;
-
- //! Activates a part data model if the index is a Part node index.
- //! Returns true if active part changed.
- //! \param theIndex a model index
- bool activatedIndex(const QModelIndex& theIndex);
-
- //! Retrurns active part
- ResultPartPtr activePart() const;
-
- //! Retrurns QModelIndex of active part
- QModelIndex activePartIndex() const
- {
- return myActivePartIndex;
- }
-
- //! Deactivates a Part
- void deactivatePart();
-
- //! Rebuild data tree
- void rebuildDataTree();
-
- //! Clear internal data
- void clear();
-
-
- private:
-
- enum
- {
- PartsFolder,
- HistoryNode
- };
-
- //! Converts QModelIndex of this model to QModelIndex of a one of sub-models.
- QModelIndex* toSourceModelIndex(const QModelIndex& theProxy) const;
-
- //! Finds a pointer on QModelIndex which is equal to the given one
- QModelIndex* findModelIndex(const QModelIndex& theIndex) const;
-
- //! Returns pointer on QModelIndex which is equal to the given one.
- QModelIndex* getModelIndex(const QModelIndex& theIndex) const;
-
- //! Deletes all saved pointers on QModelIndex objects.
- void clearModelIndexes();
-
- //! Deletes all saved pointers on QModelIndex objects.
- void clearSubModels();
-
- //! Removes sub-model on removing a part object. Also it removes QModelIndex-es which refer to this model
- void removeSubModel(int theModelId);
-
- //! Returns true if the given model is a one of sub-models (of both types)
- bool isSubModel(const QAbstractItemModel* theModel) const;
-
- //! Returns true if the given model is a one of sub-models of Part type
- bool isPartSubModel(const QAbstractItemModel* theModel) const;
-
- //! Returns Parts Folder node
- QModelIndex partFolderNode() const;
-
- int historyOffset() const;
-
- //! Data model of top part of data tree (not parts object)
- XGUI_TopDataModel* myModel;
-
- //! Data models for Parts data tree representation (one data model per a one part)
- QList<XGUI_PartModel*> myPartModels;
-
- //! Active part in part editing mode
- XGUI_PartModel* myActivePart;
-
- QModelIndex myActivePartIndex;
-
- //! List of saved QModelIndexes created by sub-models
- QList<QModelIndex*> myIndexes;
-
-};
-
-#endif
#include "XGUI_Displayer.h"
#include "XGUI_PropertyPanel.h"
+#include <ModuleBase_IModule.h>
+
#include <AIS_Shape.hxx>
XGUI_Displayer* aDisp = myWorkshop->displayer();
// Clear selection modes
QIntList aModes;
+ // TODO: check on OCC6.9.0
+ // the module current active modes should not be deactivated in order to save the objects selected
+ // the deactivate object in the mode of selection leads to the object is deselected in the viewer.
+ // But, in OCC6.8.0 this deselection does not happened automatically. It is necessary to call
+ // ClearOutdatedSelection, but this method has an error in the realization, which should be fixed in
+ // the OCC6.9.0 release. Moreother, it is possible that ClearOutdatedSelection will be called inside
+ // Deactivate method of AIS_InteractiveContext. In this case, we need not call it.
+ module()->activeSelectionModes(aModes);
aDisp->activateObjects(aModes);
// The document limitation selection has to be only during operation
//aDisp->removeSelectionFilter(myDocumentShapeFilter);
return aDisp->getObject(theAIS);
}
-void XGUI_ModuleConnector::setSelected(const QObjectPtrList& theFeatures)
+void XGUI_ModuleConnector::setSelected(const QList<ModuleBase_ViewerPrs>& theValues)
{
XGUI_Displayer* aDisp = myWorkshop->displayer();
- if (theFeatures.isEmpty()) {
+ if (theValues.isEmpty()) {
myWorkshop->selector()->clearSelection();
} else {
- aDisp->setSelected(theFeatures);
+ aDisp->setSelected(theValues);
}
}
//! Select features clearing previous selection.
//! If the list is empty then selection will be cleared
- virtual void setSelected(const QObjectPtrList& theFeatures);
+ virtual void setSelected(const QList<ModuleBase_ViewerPrs>& theValues);
//! Returns workshop
XGUI_Workshop* workshop() const { return myWorkshop; }
// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
#include "XGUI_ObjectsBrowser.h"
-#include "XGUI_DocumentDataModel.h"
#include "XGUI_Tools.h"
#include <ModelAPI_Data.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_Document.h>
-#include <ModelAPI_Object.h>
#include <ModuleBase_Tools.h>
+#include <ModuleBase_IDocumentDataModel.h>
#include <QLayout>
#include <QLabel>
#include <QAction>
#include <QStyledItemDelegate>
+
+/// Width of second column (minimum acceptable = 27)
+#define SECOND_COL_WIDTH 30
+
+
/**
* \ingroup GUI
* Tree item delegate for definition of data in column items editor
{
QLineEdit* aEditor = dynamic_cast<QLineEdit*>(editor);
if (aEditor) {
- XGUI_DocumentDataModel* aModel = myTreedView->dataModel();
+ ModuleBase_IDocumentDataModel* aModel = myTreedView->dataModel();
ObjectPtr aObj = aModel->object(index);
if (aObj.get() != NULL) {
aEditor->setText(aObj->data()->name().c_str());
: QTreeView(theParent)
{
setHeaderHidden(true);
- setModel(new XGUI_DocumentDataModel(this));
setEditTriggers(QAbstractItemView::NoEditTriggers);
setSelectionBehavior(QAbstractItemView::SelectRows);
setSelectionMode(QAbstractItemView::ExtendedSelection);
setItemDelegateForColumn(0, new XGUI_TreeViewItemDelegate(this));
-
- connect(selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
- this, SLOT(onSelectionChanged(const QItemSelection&, const QItemSelection&)));
}
XGUI_DataTree::~XGUI_DataTree()
{
}
-XGUI_DocumentDataModel* XGUI_DataTree::dataModel() const
-{
- return static_cast<XGUI_DocumentDataModel*>(model());
-}
-
-void XGUI_DataTree::onSelectionChanged(const QItemSelection& theSelected,
- const QItemSelection& theDeselected)
-{
- mySelectedData.clear();
- QModelIndexList aIndexes = selectionModel()->selectedIndexes();
- XGUI_DocumentDataModel* aModel = dataModel();
- QModelIndexList::const_iterator aIt;
- for (aIt = aIndexes.constBegin(); aIt != aIndexes.constEnd(); ++aIt) {
- ObjectPtr aObject = aModel->object(*aIt);
- if (aObject)
- mySelectedData.append(aObject);
- }
- emit selectionChanged();
-}
-
-void XGUI_DataTree::mouseDoubleClickEvent(QMouseEvent* theEvent)
+ModuleBase_IDocumentDataModel* XGUI_DataTree::dataModel() const
{
- if (theEvent->button() == Qt::LeftButton) {
- QModelIndex aIndex = currentIndex();
- XGUI_DocumentDataModel* aModel = dataModel();
- ObjectPtr aObject = aModel->object(aIndex);
- ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);
- if (aPart) {
- aPart->activate();
- }
- } else
- QTreeView::mouseDoubleClickEvent(theEvent);
+ return static_cast<ModuleBase_IDocumentDataModel*>(model());
}
void XGUI_DataTree::contextMenuEvent(QContextMenuEvent* theEvent)
QLineEdit* aEditor = dynamic_cast<QLineEdit*>(theEditor);
if (aEditor) {
QString aRes = aEditor->text();
- ObjectPtr aFeature = mySelectedData.first();
+ QModelIndexList aIndexList = selectionModel()->selectedIndexes();
+ ModuleBase_IDocumentDataModel* aModel = dataModel();
+ ObjectPtr aObj = aModel->object(aIndexList.first());
SessionPtr aMgr = ModelAPI_Session::get();
aMgr->startOperation("Rename");
- aFeature->data()->setName(qPrintable(aRes));
+ aObj->data()->setName(qPrintable(aRes));
aMgr->finishOperation();
}
}
void XGUI_DataTree::clear()
{
- mySelectedData.clear();
- XGUI_DocumentDataModel* aModel = dataModel();
+ ModuleBase_IDocumentDataModel* aModel = dataModel();
aModel->clear();
reset();
}
+void XGUI_DataTree::resizeEvent(QResizeEvent* theEvent)
+{
+ QSize aSize = theEvent->size();
+ if (aSize.isValid()) {
+ setColumnWidth(0, aSize.width() - SECOND_COL_WIDTH);
+ setColumnWidth(1, SECOND_COL_WIDTH);
+ }
+}
+
+
//********************************************************************
//********************************************************************
//********************************************************************
XGUI_ObjectsBrowser::XGUI_ObjectsBrowser(QWidget* theParent)
- : QWidget(theParent)
+ : QWidget(theParent), myDocModel(0)
{
QVBoxLayout* aLayout = new QVBoxLayout(this);
ModuleBase_Tools::zeroMargins(aLayout);
myTreeView = new XGUI_DataTree(this);
aLayout->addWidget(myTreeView);
- myDocModel = myTreeView->dataModel();
-
aLabelWgt->setFrameShape(myTreeView->frameShape());
aLabelWgt->setFrameShadow(myTreeView->frameShadow());
- connect(myTreeView, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
- connect(myTreeView, SIGNAL(activePartChanged(ObjectPtr)), this,
- SLOT(onActivePartChanged(ObjectPtr)));
- connect(myTreeView, SIGNAL(activePartChanged(ObjectPtr)), this,
- SIGNAL(activePartChanged(ObjectPtr)));
-
connect(myActiveDocLbl, SIGNAL(customContextMenuRequested(const QPoint&)), this,
SLOT(onLabelContextMenuRequested(const QPoint&)));
connect(myTreeView, SIGNAL(contextMenuRequested(QContextMenuEvent*)), this,
SLOT(onContextMenuRequested(QContextMenuEvent*)));
- onActivePartChanged(ObjectPtr());
-
// Create internal actions
QAction* aAction = new QAction(QIcon(":pictures/rename_edit.png"), tr("Rename"), this);
aAction->setData("RENAME_CMD");
{
}
-//***************************************************
-void XGUI_ObjectsBrowser::onActivePartChanged(ObjectPtr thePart)
-{
- QPalette aPalet = myActiveDocLbl->palette();
- if (thePart) {
- aPalet.setColor(QPalette::Text, Qt::black);
- } else {
- aPalet.setColor(QPalette::Text, QColor(0, 72, 140));
- }
- myActiveDocLbl->setPalette(aPalet);
-}
-
//***************************************************
bool XGUI_ObjectsBrowser::eventFilter(QObject* obj, QEvent* theEvent)
{
if (obj == myActiveDocLbl) {
- if (myActiveDocLbl->isReadOnly()) {
- if (theEvent->type() == QEvent::MouseButtonDblClick) {
- if (myDocModel->activePartIndex().isValid()) {
- myTreeView->setExpanded(myDocModel->activePartIndex(), false);
- }
- myDocModel->deactivatePart();
- onActivePartChanged(ObjectPtr());
- emit activePartChanged(ObjectPtr());
- }
- } else {
+ if (!myActiveDocLbl->isReadOnly()) {
// End of editing by mouse click
if (theEvent->type() == QEvent::MouseButtonRelease) {
QMouseEvent* aEvent = (QMouseEvent*) theEvent;
}
}
-//***************************************************
-void XGUI_ObjectsBrowser::activatePart(const ResultPartPtr& thePart)
-{
- if (thePart) {
- QModelIndex aIndex = myDocModel->partIndex(thePart);
-
- if ((myDocModel->activePartIndex() != aIndex) && myDocModel->activePartIndex().isValid()) {
- myTreeView->setExpanded(myDocModel->activePartIndex(), false);
- }
- bool isChanged = myDocModel->activatedIndex(aIndex);
- if (isChanged) {
- if (myDocModel->activePartIndex().isValid()) {
- myTreeView->setExpanded(aIndex.parent(), true);
- myTreeView->setExpanded(aIndex, true);
- onActivePartChanged(myDocModel->object(aIndex));
- } else {
- onActivePartChanged(ObjectPtr());
- }
- }
- } else {
- QModelIndex aIndex = myDocModel->activePartIndex();
- if (aIndex.isValid()) {
- myDocModel->activatedIndex(aIndex);
- myTreeView->setExpanded(aIndex, false);
- onActivePartChanged(ObjectPtr());
- }
- }
-}
-
//***************************************************
void XGUI_ObjectsBrowser::onContextMenuRequested(QContextMenuEvent* theEvent)
{
- myObjectsList = myTreeView->selectedObjects();
- bool toEnable = myObjectsList.size() == 1;
- foreach(QAction* aCmd, actions())
- {
+ QObjectPtrList aSelectedData = selectedObjects();
+ bool toEnable = aSelectedData.size() == 1;
+ foreach(QAction* aCmd, actions()) {
aCmd->setEnabled(toEnable);
}
emit contextMenuRequested(theEvent);
//***************************************************
void XGUI_ObjectsBrowser::onLabelContextMenuRequested(const QPoint& thePnt)
{
- myObjectsList.clear();
+ myTreeView->selectionModel()->clearSelection();
//Empty feature pointer means that selected root document
- myObjectsList.append(ObjectPtr());
-
- foreach(QAction* aCmd, actions())
- {
+ foreach(QAction* aCmd, actions()) {
aCmd->setEnabled(true);
}
QContextMenuEvent aEvent(QContextMenuEvent::Mouse, thePnt, myActiveDocLbl->mapToGlobal(thePnt));
//***************************************************
void XGUI_ObjectsBrowser::onEditItem()
{
- if (myObjectsList.size() > 0) {
- ObjectPtr aFeature = myObjectsList.first();
+ QObjectPtrList aSelectedData = selectedObjects();
+ if (aSelectedData.size() > 0) {
+ ObjectPtr aFeature = aSelectedData.first();
if (aFeature) { // Selection happens in TreeView
// Find index which corresponds the feature
QModelIndex aIndex;
- foreach(QModelIndex aIdx, selectedIndexes())
- {
+ foreach(QModelIndex aIdx, selectedIndexes()) {
ObjectPtr aFea = dataModel()->object(aIdx);
if (dataModel()->object(aIdx)->isSame(aFeature)) {
aIndex = aIdx;
myTreeView->setCurrentIndex(aIndex);
myTreeView->edit(aIndex);
}
- } else { //Selection happens in Upper label
- myActiveDocLbl->setReadOnly(false);
- myActiveDocLbl->setFocus();
- myActiveDocLbl->selectAll();
- myActiveDocLbl->grabMouse();
- myActiveDocLbl->setProperty("OldText", myActiveDocLbl->text());
+ return;
}
}
-}
-
-//***************************************************
-void XGUI_ObjectsBrowser::onSelectionChanged()
-{
- myObjectsList = myTreeView->selectedObjects();
- emit selectionChanged();
+ //Selection happens in Upper label
+ myActiveDocLbl->setReadOnly(false);
+ myActiveDocLbl->setFocus();
+ myActiveDocLbl->selectAll();
+ myActiveDocLbl->grabMouse();
+ myActiveDocLbl->setProperty("OldText", myActiveDocLbl->text());
}
//***************************************************
}
//***************************************************
-void XGUI_ObjectsBrowser::processEvent(const std::shared_ptr<Events_Message>& theMessage)
+void XGUI_ObjectsBrowser::clearContent()
{
- myDocModel->processEvent(theMessage);
+ myTreeView->clear();
}
+void XGUI_ObjectsBrowser::setDataModel(ModuleBase_IDocumentDataModel* theModel)
+{
+ myDocModel = theModel;
+ myTreeView->setModel(myDocModel);
+ QItemSelectionModel* aSelMod = myTreeView->selectionModel();
+ connect(aSelMod, SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
+ this, SLOT(onSelectionChanged(const QItemSelection&, const QItemSelection&)));
+}
-//***************************************************
-void XGUI_ObjectsBrowser::clearContent()
-{
- myObjectsList.clear();
- myTreeView->clear();
+void XGUI_ObjectsBrowser::onSelectionChanged(const QItemSelection& theSelected,
+ const QItemSelection& theDeselected)
+{
+ emit selectionChanged();
}
+
+QObjectPtrList XGUI_ObjectsBrowser::selectedObjects() const
+{
+ QObjectPtrList aList;
+ QModelIndexList aIndexes = selectedIndexes();
+ ModuleBase_IDocumentDataModel* aModel = dataModel();
+ QModelIndexList::const_iterator aIt;
+ for (aIt = aIndexes.constBegin(); aIt != aIndexes.constEnd(); ++aIt) {
+ if ((*aIt).column() == 0) {
+ ObjectPtr aObject = aModel->object(*aIt);
+ if (aObject)
+ aList.append(aObject);
+ }
+ }
+ return aList;
+}
\ No newline at end of file
#include <QWidget>
#include <QTreeView>
-class XGUI_DocumentDataModel;
+class ModuleBase_IDocumentDataModel;
class QLineEdit;
/**
/// Constructor
/// \param theParent a parent widget
XGUI_DataTree(QWidget* theParent);
- virtual ~XGUI_DataTree();
- //! Returns list of currently selected objects
- QObjectPtrList selectedObjects() const
- {
- return mySelectedData;
- }
+ virtual ~XGUI_DataTree();
/// Returns current data model
- XGUI_DocumentDataModel* dataModel() const;
+ ModuleBase_IDocumentDataModel* dataModel() const;
signals:
- //! Emited when selection is changed
- void selectionChanged();
-
- //! Emited when active part changed
- void activePartChanged(ObjectPtr thePart);
-
//! Emited on context menu request
void contextMenuRequested(QContextMenuEvent* theEvent);
virtual void clear();
protected slots:
- /// Commit modified data (used for renaming of objects)
+ /// Commit modified data (used for renaming of objects)
virtual void commitData(QWidget* theEditor);
protected:
- /// Redefinition of virtual method
- virtual void mouseDoubleClickEvent(QMouseEvent* theEvent);
-
/// Redefinition of virtual method
virtual void contextMenuEvent(QContextMenuEvent* theEvent);
- private slots:
- //! Called when selection in Data Tree is changed
- void onSelectionChanged(const QItemSelection& theSelected, const QItemSelection& theDeselected);
+ /// Redefinition of virtual method
+ virtual void resizeEvent(QResizeEvent* theEvent);
- private:
- //! List of currently selected data
- QObjectPtrList mySelectedData;
};
/**\class XGUI_ObjectsBrowser
virtual ~XGUI_ObjectsBrowser();
//! Returns Model which provides access to data objects
- XGUI_DocumentDataModel* dataModel() const
+ ModuleBase_IDocumentDataModel* dataModel() const
{
return myDocModel;
}
//! Returns list of currently selected objects
- QObjectPtrList selectedObjects() const
- {
- return myObjectsList;
- }
+ QObjectPtrList selectedObjects() const;
/// Set selected list of objects
/// \param theObjects list of objects to select
return myTreeView;
}
- //! Activates currently selected part. Signal activePartChanged will not be sent
- void activatePart(const ResultPartPtr& thePart);
+ /// Returns active doc label object
+ QLineEdit* activeDocLabel() const { return myActiveDocLbl; }
/// Rebuild data tree
void rebuildDataTree();
- /// Process application event
- /// \param theMessage an event message
- void processEvent(const std::shared_ptr<Events_Message>& theMessage);
-
/// Resets the object browser into initial state
void clearContent();
+ /// Set Data Model for the Object Browser
+ void setDataModel(ModuleBase_IDocumentDataModel* theModel);
+
signals:
//! Emited when selection is changed
void selectionChanged();
- //! Emited when current active document is changed
- void activePartChanged(ObjectPtr thePart);
-
//! Emited on context menu request
void contextMenuRequested(QContextMenuEvent* theEvent);
virtual bool eventFilter(QObject* obj, QEvent* theEvent);
private slots:
- /// Activate part
- /// \param thePart a part to activate
- void onActivePartChanged(ObjectPtr thePart);
-
/// Show context menu
/// \param theEvent a context menu event
void onContextMenuRequested(QContextMenuEvent* theEvent);
//! Called on Edit command request
void onEditItem();
- /// Process selection changed event
- void onSelectionChanged();
+ //! Called when selection in Data Tree is changed
+ void onSelectionChanged(const QItemSelection& theSelected, const QItemSelection& theDeselected);
private:
void closeDocNameEditing(bool toSave);
//! Internal model
- XGUI_DocumentDataModel* myDocModel;
+ ModuleBase_IDocumentDataModel* myDocModel;
QLineEdit* myActiveDocLbl;
XGUI_DataTree* myTreeView;
-
- QObjectPtrList myObjectsList;
};
#endif
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
-
-#include "XGUI_PartDataModel.h"
-#include "XGUI_Workshop.h"
-
-#include <ModelAPI_Session.h>
-#include <ModelAPI_Document.h>
-#include <ModelAPI_Feature.h>
-#include <ModelAPI_Result.h>
-#include <ModelAPI_Data.h>
-#include <ModelAPI_AttributeDocRef.h>
-#include <ModelAPI_Object.h>
-#include <ModelAPI_ResultPart.h>
-#include <ModelAPI_ResultConstruction.h>
-#include <ModelAPI_ResultParameter.h>
-#include <ModelAPI_ResultBody.h>
-#include <ModelAPI_ResultGroup.h>
-#include <ModelAPI_AttributeDouble.h>
-
-#include <QIcon>
-#include <QBrush>
-
-//ObjectPtr featureObj(const ObjectPtr& theFeature)
-//{
-// ObjectPtr aObject = std::dynamic_pointer_cast<ModelAPI_Object>(theFeature);
-// if (aObject)
-// return aObject->featureRef();
-// return theFeature;
-//}
-
-XGUI_TopDataModel::XGUI_TopDataModel(QObject* theParent)
- : XGUI_FeaturesModel(theParent)
-{
-}
-
-XGUI_TopDataModel::~XGUI_TopDataModel()
-{
-}
-
-QVariant XGUI_TopDataModel::data(const QModelIndex& theIndex, int theRole) const
-{
- switch (theRole) {
- case Qt::DisplayRole:
- // return a name
- switch (theIndex.internalId()) {
- case ParamsFolder:
- return tr("Parameters") + QString(" (%1)").arg(rowCount(theIndex));
- case ParamObject: {
- DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
- ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultParameter::group(), theIndex.row());
- if (aObject) {
- ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObject);
- AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
- QString aVal = QString::number(aValueAttribute->value());
- QString aTitle = QString(aObject->data()->name().c_str());
- return aTitle + " = " + aVal;
- }
- }
- break;
- case ConstructFolder:
- return tr("Constructions") + QString(" (%1)").arg(rowCount(theIndex));
- case ConstructObject: {
- DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
- ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultConstruction::group(),
- theIndex.row());
- if (aObject)
- return aObject->data()->name().c_str();
- }
- break;
- //case GroupsFolder:
- // return tr("Groups") + QString(" (%1)").arg(rowCount(theIndex));
- //case GroupObject: {
- // DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
- // ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultGroup::group(),
- // theIndex.row());
- // if (aObject)
- // return aObject->data()->name().c_str();
- //}
- // break;
- }
- break;
-
- case Qt::DecorationRole:
- {
- // return an Icon
- switch (theIndex.internalId()) {
- case ParamsFolder:
- return QIcon(":pictures/params_folder.png");
- case ConstructFolder:
- return QIcon(":pictures/constr_folder.png");
- case ConstructObject:
- return QIcon(":pictures/constr_object.png");
- //case GroupsFolder:
- // return QIcon(":pictures/constr_folder.png");
- }
- }
- break;
-
- case Qt::ToolTipRole:
- // return Tooltip
- break;
- case Qt::ForegroundRole:
- return QBrush(myItemsColor);
- break;
- }
- return QVariant();
-}
-
-QVariant XGUI_TopDataModel::headerData(int section, Qt::Orientation orientation, int role) const
-{
- return QVariant();
-}
-
-int XGUI_TopDataModel::rowCount(const QModelIndex& theParent) const
-{
- if (!theParent.isValid())
- return 2; // In case of groups using it has to be +1
-
- DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
- if (theParent.internalId() == ParamsFolder)
- return aRootDoc->size(ModelAPI_ResultParameter::group());
-
- if (theParent.internalId() == ConstructFolder)
- return aRootDoc->size(ModelAPI_ResultConstruction::group());
-
- //if (theParent.internalId() == GroupsFolder)
- // return aRootDoc->size(ModelAPI_ResultGroup::group());
-
- return 0;
-}
-
-int XGUI_TopDataModel::columnCount(const QModelIndex &parent) const
-{
- return 1;
-}
-
-QModelIndex XGUI_TopDataModel::index(int theRow, int theColumn, const QModelIndex& theParent) const
-{
- if (!theParent.isValid()) {
- switch (theRow) {
- case 0:
- return createIndex(theRow, theColumn, (qint32) ParamsFolder);
- case 1:
- return createIndex(theRow, theColumn, (qint32) ConstructFolder);
- //case 2:
- // return createIndex(theRow, theColumn, (qint32) GroupsFolder);
- }
- } else {
- if (theParent.internalId() == ParamsFolder)
- return createIndex(theRow, theColumn, (qint32) ParamObject);
-
- if (theParent.internalId() == ConstructFolder)
- return createIndex(theRow, theColumn, (qint32) ConstructObject);
-
- //if (theParent.internalId() == GroupsFolder)
- // return createIndex(theRow, theColumn, (qint32) GroupObject);
- }
- return QModelIndex();
-}
-
-QModelIndex XGUI_TopDataModel::parent(const QModelIndex& theIndex) const
-{
- int aId = (int) theIndex.internalId();
- switch (aId) {
- case ParamsFolder:
- case ConstructFolder:
- //case GroupsFolder:
- return QModelIndex();
- case ParamObject:
- return createIndex(0, 0, (qint32) ParamsFolder);
- case ConstructObject:
- return createIndex(1, 0, (qint32) ConstructFolder);
- //case GroupObject:
- // return createIndex(2, 0, (qint32) GroupsFolder);
- }
- return QModelIndex();
-}
-
-bool XGUI_TopDataModel::hasChildren(const QModelIndex& theParent) const
-{
- return rowCount(theParent) > 0;
-}
-
-ObjectPtr XGUI_TopDataModel::object(const QModelIndex& theIndex) const
-{
- switch (theIndex.internalId()) {
- case ParamsFolder:
- case ConstructFolder:
- return ObjectPtr();
- case ParamObject: {
- DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
- return aRootDoc->object(ModelAPI_ResultParameter::group(), theIndex.row());
- }
- case ConstructObject: {
- DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
- return aRootDoc->object(ModelAPI_ResultConstruction::group(), theIndex.row());
- }
- //case GroupObject: {
- // DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
- // return aRootDoc->object(ModelAPI_ResultGroup::group(), theIndex.row());
- //}
- }
- return ObjectPtr();
-}
-
-QModelIndex XGUI_TopDataModel::findParent(const ObjectPtr& theObject) const
-{
- return findGroup(theObject->groupName().c_str());
-}
-
-QModelIndex XGUI_TopDataModel::findGroup(const std::string& theGroup) const
-{
- if (theGroup == ModelAPI_ResultParameter::group())
- return createIndex(0, 0, (qint32) ParamsFolder);
- if (theGroup == ModelAPI_ResultConstruction::group())
- return createIndex(1, 0, (qint32) ConstructFolder);
- //if (theGroup == ModelAPI_ResultGroup::group())
- // return createIndex(2, 0, (qint32) ConstructFolder);
- return QModelIndex();
-}
-
-QModelIndex XGUI_TopDataModel::objectIndex(const ObjectPtr& theObject) const
-{
- QModelIndex aIndex;
- if (theObject) {
- DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
- std::string aGroup = theObject->groupName();
- int aNb = aRootDoc->size(aGroup);
- int aRow = -1;
- for (int i = 0; i < aNb; i++) {
- if (aRootDoc->object(aGroup, i) == theObject) {
- aRow = i;
- break;
- }
- }
- if (aRow != -1) {
- if (aGroup == ModelAPI_ResultParameter::group())
- return createIndex(aRow, 0, (qint32) ParamObject);
- if (aGroup == ModelAPI_ResultConstruction::group())
- return createIndex(aRow, 0, (qint32) ConstructObject);
- //if (aGroup == ModelAPI_ResultGroup::group())
- // return createIndex(aRow, 0, (qint32) GroupObject);
- }
- }
- return aIndex;
-}
-
-//******************************************************************
-//******************************************************************
-//******************************************************************
-XGUI_PartDataModel::XGUI_PartDataModel(QObject* theParent)
- : XGUI_PartModel(theParent)
-{
-}
-
-XGUI_PartDataModel::~XGUI_PartDataModel()
-{
-}
-
-QVariant XGUI_PartDataModel::data(const QModelIndex& theIndex, int theRole) const
-{
- switch (theRole) {
- case Qt::DisplayRole:
- // return a name
- switch (theIndex.internalId()) {
- case MyRoot: {
- DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
- ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), myId);
- if (aObject)
- return std::dynamic_pointer_cast<ModelAPI_Object>(aObject)->data()->name().c_str();
- }
- case ParamsFolder:
- return tr("Parameters") + QString(" (%1)").arg(rowCount(theIndex));
- case ConstructFolder:
- return tr("Constructions") + QString(" (%1)").arg(rowCount(theIndex));
- case BodiesFolder:
- return tr("Bodies") + QString(" (%1)").arg(rowCount(theIndex));
- case GroupsFolder:
- return tr("Groups") + QString(" (%1)").arg(rowCount(theIndex));
- case ParamObject: {
- ObjectPtr aObject = partDocument()->object(ModelAPI_ResultParameter::group(),
- theIndex.row());
- if (aObject) {
- ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObject);
- AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
- QString aVal = QString::number(aValueAttribute->value());
- QString aTitle = QString(aObject->data()->name().c_str());
- return aTitle + " = " + aVal;
- }
- }
- break;
- case ConstructObject: {
- ObjectPtr aObject = partDocument()->object(ModelAPI_ResultConstruction::group(),
- theIndex.row());
- if (aObject)
- return std::dynamic_pointer_cast<ModelAPI_Object>(aObject)->data()->name().c_str();
- }
- break;
- case BodiesObject: {
- ObjectPtr aObject = partDocument()->object(ModelAPI_ResultBody::group(), theIndex.row());
- if (aObject)
- return aObject->data()->name().c_str();
- }
- break;
- case GroupObject: {
- ObjectPtr aObject = partDocument()->object(ModelAPI_ResultGroup::group(), theIndex.row());
- if (aObject)
- return aObject->data()->name().c_str();
- }
- case HistoryObject: {
- ObjectPtr aObject = partDocument()->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber());
- if (aObject)
- return aObject->data()->name().c_str();
- }
- }
- break;
- case Qt::DecorationRole:
- // return an Icon
- switch (theIndex.internalId()) {
- case MyRoot:
- return QIcon(":pictures/part_ico.png");
- case ParamsFolder:
- return QIcon(":pictures/params_folder.png");
- case ConstructFolder:
- case BodiesFolder:
- return QIcon(":pictures/constr_folder.png");
- case GroupsFolder:
- return QIcon(":pictures/constr_folder.png");
- case ConstructObject:
- case GroupObject:
- case BodiesObject: {
- 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()->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() - getRowsNumber());
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
- if (aFeature)
- return XGUI_Workshop::featureIcon(aFeature);
- }
- }
- break;
- case Qt::ToolTipRole:
- // return Tooltip
- break;
- case Qt::ForegroundRole:
- return QBrush(myItemsColor);
- break;
- }
- return QVariant();
-}
-
-QVariant XGUI_PartDataModel::headerData(int section, Qt::Orientation orientation, int role) const
-{
- return QVariant();
-}
-
-int XGUI_PartDataModel::rowCount(const QModelIndex& parent) const
-{
- if (!parent.isValid()) {
- DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
- if (aRootDoc->object(ModelAPI_ResultPart::group(), myId))
- return 1;
- else
- return 0;
- }
- switch (parent.internalId()) {
- case MyRoot:
- {
- DocumentPtr aDoc = partDocument();
- if (aDoc) {
- return getRowsNumber() + aDoc->size(ModelAPI_Feature::group());
- } else
- return 0;
- }
- case ParamsFolder:
- return partDocument()->size(ModelAPI_ResultParameter::group());
- case ConstructFolder:
- return partDocument()->size(ModelAPI_ResultConstruction::group());
- case BodiesFolder:
- return partDocument()->size(ModelAPI_ResultBody::group());
- case GroupsFolder:
- return partDocument()->size(ModelAPI_ResultGroup::group());
- }
- return 0;
-}
-
-int XGUI_PartDataModel::columnCount(const QModelIndex &parent) const
-{
- return 1;
-}
-
-QModelIndex XGUI_PartDataModel::index(int theRow, int theColumn, const QModelIndex &theParent) const
-{
- if (!theParent.isValid())
- return createIndex(theRow, 0, (qint32) MyRoot);
-
- int aId = (int) theParent.internalId();
- switch (aId) {
- case MyRoot:
- switch (theRow) {
- case 0:
- return createIndex(theRow, 0, (qint32) ParamsFolder);
- case 1:
- return createIndex(theRow, 0, (qint32) ConstructFolder);
- case 2:
- return createIndex(theRow, 0, (qint32) BodiesFolder);
- case 3:
- {
- 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);
- }
- case ParamsFolder:
- return createIndex(theRow, 0, (qint32) ParamObject);
- case ConstructFolder:
- return createIndex(theRow, 0, (qint32) ConstructObject);
- case BodiesFolder:
- return createIndex(theRow, 0, (qint32) BodiesObject);
- case GroupsFolder:
- return createIndex(theRow, 0, (qint32) GroupObject);
- }
- return QModelIndex();
-}
-
-QModelIndex XGUI_PartDataModel::parent(const QModelIndex& theIndex) const
-{
- switch (theIndex.internalId()) {
- case MyRoot:
- return QModelIndex();
- case ParamsFolder:
- case ConstructFolder:
- case BodiesFolder:
- case GroupsFolder:
- case HistoryObject:
- return createIndex(0, 0, (qint32) MyRoot);
-
- case ParamObject:
- return createIndex(0, 0, (qint32) ParamsFolder);
- case ConstructObject:
- return createIndex(1, 0, (qint32) ConstructFolder);
- case BodiesObject:
- return createIndex(2, 0, (qint32) BodiesFolder);
- case GroupObject:
- return createIndex(3, 0, (qint32) GroupsFolder);
- }
- return QModelIndex();
-}
-
-bool XGUI_PartDataModel::hasChildren(const QModelIndex& theParent) const
-{
- return rowCount(theParent) > 0;
-}
-
-DocumentPtr XGUI_PartDataModel::partDocument() const
-{
- DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
- ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), myId);
- ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);
- if (aPart)
- return aPart->partDoc();
- return DocumentPtr(); // null if not found
-}
-
-ObjectPtr XGUI_PartDataModel::object(const QModelIndex& theIndex) const
-{
- switch (theIndex.internalId()) {
- case MyRoot: {
- DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
- return aRootDoc->object(ModelAPI_ResultPart::group(), myId);
- }
- case ParamsFolder:
- case ConstructFolder:
- case BodiesFolder:
- case GroupsFolder:
- return ObjectPtr();
-
- case ParamObject:
- return partDocument()->object(ModelAPI_ResultParameter::group(), theIndex.row());
- case ConstructObject:
- return partDocument()->object(ModelAPI_ResultConstruction::group(), theIndex.row());
- case BodiesObject:
- return partDocument()->object(ModelAPI_ResultBody::group(), theIndex.row());
- case GroupObject:
- return partDocument()->object(ModelAPI_ResultGroup::group(), theIndex.row());
- case HistoryObject:
- return partDocument()->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber());
- }
- return ObjectPtr();
-}
-
-bool XGUI_PartDataModel::hasDocument(const DocumentPtr& theDoc) const
-{
- return (partDocument() == theDoc);
-}
-
-QModelIndex XGUI_PartDataModel::findParent(const ObjectPtr& theObject) const
-{
- return findGroup(theObject->groupName().c_str());
-}
-
-QModelIndex XGUI_PartDataModel::findGroup(const std::string& theGroup) const
-{
- if (theGroup == ModelAPI_ResultParameter::group())
- return createIndex(0, 0, (qint32) ParamsFolder);
- if (theGroup == ModelAPI_ResultConstruction::group())
- return createIndex(1, 0, (qint32) ConstructFolder);
- if (theGroup == ModelAPI_ResultBody::group())
- return createIndex(2, 0, (qint32) BodiesFolder);
- if (theGroup == ModelAPI_ResultGroup::group())
- return createIndex(3, 0, (qint32) GroupsFolder);
- return QModelIndex();
-}
-
-ResultPartPtr XGUI_PartDataModel::part() const
-{
- DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
- ObjectPtr aObj = aRootDoc->object(ModelAPI_ResultPart::group(), myId);
- return std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
-}
-
-QModelIndex XGUI_PartDataModel::objectIndex(const ObjectPtr& theObject) const
-{
- QModelIndex aIndex;
- if (theObject) {
- if (part() == theObject)
- return aIndex;
-
- std::string aGroup = theObject->groupName();
- DocumentPtr aDoc = theObject->document();
- int aNb = aDoc->size(aGroup);
- int aRow = -1;
- for (int i = 0; i < aNb; i++) {
- if (aDoc->object(aGroup, i) == theObject) {
- aRow = i;
- break;
- }
- }
- if (aRow == -1)
- return aIndex;
- if (aGroup == ModelAPI_ResultParameter::group())
- return createIndex(aRow, 0, (qint32) ParamObject);
- else if (aGroup == ModelAPI_ResultConstruction::group())
- return createIndex(aRow, 0, (qint32) ConstructObject);
- else if (aGroup == ModelAPI_ResultBody::group())
- return createIndex(aRow, 0, (qint32) BodiesObject);
- else if (aGroup == ModelAPI_ResultGroup::group())
- return createIndex(aRow, 0, (qint32) GroupObject);
- else
- 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
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
-
-#ifndef XGUI_PartDataModel_H
-#define XGUI_PartDataModel_H
-
-#include "XGUI.h"
-#include "XGUI_DataTreeModel.h"
-
-/**\class XGUI_TopDataModel
- * \ingroup GUI
- * \brief This is a data model for Object Browser (QTreeView).
- * It represents only upper part of data tree (non-parts tree items)
- */
-class XGUI_EXPORT XGUI_TopDataModel : public XGUI_FeaturesModel
-{
-Q_OBJECT
- public:
- /// Constructor
- /// \param theParent a parent object
- XGUI_TopDataModel(QObject* theParent);
- virtual ~XGUI_TopDataModel();
-
- // Reimpl from QAbstractItemModel
-
- /// Returns the data stored under the given role for the item referred to by the index.
- /// \param theIndex a model index
- /// \param theRole a data role (see Qt::ItemDataRole)
- virtual QVariant data(const QModelIndex& theIndex, int theRole) const;
-
- /// Returns the data for the given role and section in the header with the specified orientation.
- /// \param theSection a section
- /// \param theOrient an orientation
- /// \param theRole a data role (see Qt::ItemDataRole)
- virtual QVariant headerData(int theSection, Qt::Orientation theOrient,
- int theRole = Qt::DisplayRole) const;
-
- /// Returns the number of rows under the given parent. When the parent is valid it means that
- /// rowCount is returning the number of children of parent.
- /// \param theParent a parent model index
- virtual int rowCount(const QModelIndex &theParent = QModelIndex()) const;
-
- /// Returns the number of columns for the children of the given parent.
- /// It has a one column
- /// \param theParent a parent model index
- virtual int columnCount(const QModelIndex &theParent = QModelIndex()) const;
-
-
- /// Returns the index of the item in the model specified by the given row, column and parent index.
- /// \param theRow a row
- /// \param theColumn a column
- /// \param theParent a parent model index
- virtual QModelIndex index(int theRow, int theColumn, const QModelIndex& theParent =
- QModelIndex()) const;
-
- /// Returns the parent of the model item with the given index.
- /// If the item has no parent, an invalid QModelIndex is returned.
- /// \param theIndex a model index
- virtual QModelIndex parent(const QModelIndex& theIndex) const;
-
- /// Returns true if parent has any children; otherwise returns false.
- /// \param theParent a parent model index
- virtual bool hasChildren(const QModelIndex& theParent = QModelIndex()) const;
-
- //! Returns object by the given Model index.
- //! Returns 0 if the given index is not index of a object
- virtual ObjectPtr object(const QModelIndex& theIndex) const;
-
- //! Returns QModelIndex which corresponds to the given object
- //! If the object is not found then index is not valid
- virtual QModelIndex objectIndex(const ObjectPtr& theObject) const;
-
- //! Returns parent index of the given object
- virtual QModelIndex findParent(const ObjectPtr& theObject) const;
-
- //! Returns index corresponded to the group
- virtual QModelIndex findGroup(const std::string& theGroup) const;
-
- private:
- //! Types of QModelIndexes
- enum DataIds
- {
- ParamsFolder,
- ParamObject,
- ConstructFolder,
- ConstructObject
- //GroupsFolder,
- //GroupObject
- };
-
-};
-
-/**\class XGUI_PartDataModel
- * \ingroup GUI
- * \brief This is a data model for Object Browser (QTreeView).
- * It represents data tree only of a one part
- */
-class XGUI_PartDataModel : public XGUI_PartModel
-{
-Q_OBJECT
- public:
- /// Constructor
- /// \param theParent a parent object
- XGUI_PartDataModel(QObject* theParent);
- virtual ~XGUI_PartDataModel();
-
- // Reimpl from QAbstractItemModel
-
- /// Returns the data stored under the given role for the item referred to by the index.
- /// \param theIndex a model index
- /// \param theRole a data role (see Qt::ItemDataRole)
- virtual QVariant data(const QModelIndex& theIndex, int theRole) const;
-
- /// Returns the data for the given role and section in the header with the specified orientation.
- /// \param theSection a section
- /// \param theOrient an orientation
- /// \param theRole a data role (see Qt::ItemDataRole)
- virtual QVariant headerData(int theSection, Qt::Orientation theOrient,
- int theRole = Qt::DisplayRole) const;
-
- /// Returns the number of rows under the given parent. When the parent is valid it means that
- /// rowCount is returning the number of children of parent.
- /// \param theParent a parent model index
- virtual int rowCount(const QModelIndex &theParent = QModelIndex()) const;
-
- /// Returns the number of columns for the children of the given parent.
- /// It has a one column
- /// \param theParent a parent model index
- virtual int columnCount(const QModelIndex &theParent = QModelIndex()) const;
-
- /// Returns the index of the item in the model specified by the given row, column and parent index.
- /// \param theRow a row
- /// \param theColumn a column
- /// \param theParent a parent model index
- virtual QModelIndex index(int theRow, int theColumn, const QModelIndex& theParent =
- QModelIndex()) const;
-
- /// Returns the parent of the model item with the given index.
- /// If the item has no parent, an invalid QModelIndex is returned.
- /// \param theIndex a model index
- virtual QModelIndex parent(const QModelIndex& theIndex) const;
-
- /// Returns true if parent has any children; otherwise returns false.
- /// \param theParent a parent model index
- virtual bool hasChildren(const QModelIndex& theParent = QModelIndex()) const;
-
- //! Returns object by the given Model index.
- //! Returns 0 if the given index is not index of a object
- virtual ObjectPtr object(const QModelIndex& theIndex) const;
-
- //! Returns QModelIndex which corresponds to the given object
- //! If the object is not found then index is not valid
- virtual QModelIndex objectIndex(const ObjectPtr& theObject) const;
-
- //! Returns true if the given document is a sub-document of this tree
- virtual bool hasDocument(const DocumentPtr& theDoc) const;
-
- //! Returns parent index of the given object
- virtual QModelIndex findParent(const ObjectPtr& theObject) const;
-
- //! Returns index corresponded to the group
- virtual QModelIndex findGroup(const std::string& theGroup) const;
-
- //! Return a Part object
- virtual ResultPartPtr part() const;
-
- private:
-
- //! Returns document of the current part
- DocumentPtr partDocument() const;
-
- //! Returns defult number of rows
- int getRowsNumber() const;
-
- //! Types of QModelIndexes
- enum DataIds
- {
- MyRoot,
- ParamsFolder,
- ParamObject,
- ConstructFolder,
- ConstructObject,
- BodiesFolder,
- BodiesObject,
- GroupsFolder,
- GroupObject,
- HistoryObject
- };
-
-};
-
-#endif
virtual const QList<ModuleBase_ModelWidget*>& modelWidgets() const;
/// Removes all widgets in the widget area of the property panel
- void cleanContent();
+ virtual void cleanContent();
/// Returns currently active widget
virtual ModuleBase_ModelWidget* activeWidget() const { return myActiveWidget; }
void XGUI_SelectionMgr::onObjectBrowserSelection()
{
QObjectPtrList aObjects = myWorkshop->objectBrowser()->selectedObjects();
+ QList<ModuleBase_ViewerPrs> aSelectedPrs = ModuleBase_ISelection::getViewerPrs(aObjects);
+
XGUI_Displayer* aDisplayer = myWorkshop->displayer();
- aDisplayer->setSelected(aObjects);
+ aDisplayer->setSelected(aSelectedPrs);
emit selectionChanged();
}
bool aBlocked = myWorkshop->objectBrowser()->blockSignals(true);
myWorkshop->objectBrowser()->setObjectsSelected(aFeatures);
myWorkshop->objectBrowser()->blockSignals(aBlocked);
+ QList<ModuleBase_ViewerPrs> aSelectedPrs = ModuleBase_ISelection::getViewerPrs(aFeatures);
XGUI_Displayer* aDisplayer = myWorkshop->displayer();
- aDisplayer->setSelected(aFeatures);
+ aDisplayer->setSelected(aSelectedPrs);
emit selectionChanged();
}
}*/
-void checkObjects(const QObjectPtrList& theObjects, bool& hasResult, bool& hasFeature, bool& hasParameter)
-{
- hasResult = false;
- hasFeature = false;
- hasParameter = false;
- foreach(ObjectPtr aObj, theObjects) {
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
- ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
- ResultParameterPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aResult);
-
- hasResult = (aResult.get() != NULL);
- hasFeature = (aFeature.get() != NULL);
- hasParameter = (aConstruction.get() != NULL);
- if (hasFeature && hasResult && hasParameter)
- break;
- }
-}
-
}
#include <QRect>
#include <ModelAPI_Feature.h>
-#include <ModuleBase_Definitions.h>
#include <memory>
std::string XGUI_EXPORT featureInfo(FeaturePtr theFeature);
-/*!
-Check types of objects which are in the given list
-\param theObjects the list of objects
-\param hasResult will be set to true if list contains Result objects
-\param hasFeature will be set to true if list contains Feature objects
-\param hasParameter will be set to true if list contains Parameter objects
-*/
-void checkObjects(const QObjectPtrList& theObjects, bool& hasResult, bool& hasFeature, bool& hasParameter);
-
};
#endif
this, SIGNAL(keyRelease(ModuleBase_IViewWindow*, QKeyEvent*)));
connect(aViewer, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged()));
+
+ connect(aViewer, SIGNAL(viewTransformed(int)), this, SIGNAL(viewTransformed(int)));
+
connect(aViewer, SIGNAL(contextMenuRequested(QContextMenuEvent*)), this,
SIGNAL(contextMenuRequested(QContextMenuEvent*)));
-
- // TODO: Connect to ViewTransformation signal
} else {
AppElements_Viewer* aViewer = myWorkshop->mainWindow()->viewer();
}
}
+//***************************************
void XGUI_ViewerProxy::onViewTransformed(AppElements_ViewWindow::OperationType theType)
{
emit viewTransformed((int) theType);
-}
\ No newline at end of file
+}
+
#include "XGUI_SalomeConnector.h"
#include "XGUI_ActionsMgr.h"
#include "XGUI_ErrorDialog.h"
+#include "XGUI_ColorDialog.h"
#include "XGUI_ViewerProxy.h"
#include "XGUI_PropertyPanel.h"
#include "XGUI_ContextMenuMgr.h"
#include <QMenu>
#include <QToolButton>
#include <QAction>
-#include <QDialog>
-#include <QDialogButtonBox>
-#include <QHBoxLayout>
-#include <QtxColorButton.h>
#ifdef _DEBUG
#include <QDebug>
//#define DEBUG_FEATURE_CREATED
//#define DEBUG_FEATURE_REDISPLAY
-QMap<QString, QString> XGUI_Workshop::myIcons;
-
-
-QIcon XGUI_Workshop::featureIcon(const FeaturePtr& theFeature)
-{
- QIcon anIcon;
-
- std::string aKind = theFeature->getKind();
- QString aId(aKind.c_str());
- if (!myIcons.contains(aId))
- return anIcon;
-
- QString anIconString = myIcons[aId];
-
- ModelAPI_ExecState aState = theFeature->data()->execState();
- switch(aState) {
- case ModelAPI_StateDone:
- case ModelAPI_StateNothing: {
- anIcon = QIcon(anIconString);
- }
- break;
- case ModelAPI_StateMustBeUpdated: {
- anIcon = ModuleBase_Tools::lighter(anIconString);
- }
- break;
- case ModelAPI_StateExecFailed: {
- anIcon = ModuleBase_Tools::composite(":pictures/exec_state_failed.png", anIconString);
- }
- break;
- case ModelAPI_StateInvalidArgument: {
- anIcon = ModuleBase_Tools::composite(":pictures/exec_state_invalid_parameters.png",
- anIconString);
- }
- break;
- default: break;
- }
- return anIcon;
-}
XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
: QObject(),
aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
- aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
aLoop->registerListener(this, Events_LongOp::eventID());
aLoop->registerListener(this, Events_Loop::eventByName(EVENT_PLUGIN_LOADED));
- aLoop->registerListener(this, Events_Loop::eventByName(EVENT_DOCUMENT_CHANGED));
- aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TOSHOW));
- aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TOHIDE));
aLoop->registerListener(this, Events_Loop::eventByName(EVENT_SELFILTER_LOADED));
aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED));
std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
onFeatureUpdatedMsg(anUpdateMsg);
- } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
- std::shared_ptr<ModelAPI_ObjectDeletedMessage> aDelMsg =
- std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
- onObjectDeletedMsg(aDelMsg);
} else if (theMessage->eventID() == Events_LongOp::eventID()) {
if (Events_LongOp::isPerformed()) {
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
} else {
QApplication::restoreOverrideCursor();
}
- } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TOSHOW)) {
- std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
- std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
- const std::set<ObjectPtr>& aObjList = anUpdateMsg->objects();
- QObjectPtrList aList;
- std::set<ObjectPtr>::const_iterator aIt;
- for (aIt = aObjList.cbegin(); aIt != aObjList.cend(); ++aIt)
- aList.append(*aIt);
- showObjects(aList, true);
- } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TOHIDE)) {
- std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
- std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
- const std::set<ObjectPtr>& aObjList = anUpdateMsg->objects();
- QObjectPtrList aList;
- std::set<ObjectPtr>::const_iterator aIt;
- for (aIt = aObjList.cbegin(); aIt != aObjList.cend(); ++aIt)
- aList.append(*aIt);
- showObjects(aList, false);
}
//An operation passed by message. Start it, process and commit.
else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OPERATION_LAUNCHED)) {
updateCommandStatus();
}
}
- } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) {
- myActionsMgr->update();
- // Find and Activate active part
- if (myPartActivating)
- return;
- SessionPtr aMgr = ModelAPI_Session::get();
- DocumentPtr aActiveDoc = aMgr->activeDocument();
- DocumentPtr aDoc = aMgr->moduleDocument();
- if (aActiveDoc == aDoc) {
- activatePart(ResultPartPtr());
- return;
- }
- std::string aGrpName = ModelAPI_ResultPart::group();
- for (int i = 0; i < aDoc->size(aGrpName); i++) {
- ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aDoc->object(aGrpName, i));
- if (aPart->partDoc() == aActiveDoc) {
- activatePart(aPart); // Activate a part which corresponds to active Doc
- return;
- }
- }
- // If not found then activate global document
- activatePart(ResultPartPtr());
-
- }
+ }
else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_SELFILTER_LOADED)) {
std::shared_ptr<Config_SelectionFilterMessage> aMsg =
std::dynamic_pointer_cast<Config_SelectionFilterMessage>(theMessage);
}
}
myOperationMgr->onValidateOperation();
- if (myObjectBrowser)
- myObjectBrowser->processEvent(theMsg);
+ //if (myObjectBrowser)
+ // myObjectBrowser->processEvent(theMsg);
}
//******************************************************
ObjectPtr aObj = (*aIt);
// Hide the object if it is invalid or concealed one
- bool aHide = !aObj->data() || !aObj->data()->isValid();
+ bool aHide = !aObj->data() || !aObj->data()->isValid() ||
+ aObj->isDisabled() || (!aObj->isDisplayed());
if (!aHide) { // check that this is not hidden result
ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
aHide = aRes && aRes->isConcealed();
myDisplayer->deactivate(aObj);
}
} else { // display object if the current operation has it
- ModuleBase_Operation* aOperation = myOperationMgr->currentOperation();
- if (aOperation && aOperation->hasObject(aObj)) {
+ if (displayObject(aObj)) {
ModuleBase_Operation* aOperation = myOperationMgr->currentOperation();
- #ifdef DEBUG_FEATURE_REDISPLAY
- QString anObjInfo = ModuleBase_Tools::objectInfo((aObj));
- qDebug(QString(" display object = %1").arg(anObjInfo).toStdString().c_str());
- #endif
- if (displayObject(aObj)) {
+ if (aOperation && aOperation->hasObject(aObj)) {
+ ModuleBase_Operation* aOperation = myOperationMgr->currentOperation();
+ #ifdef DEBUG_FEATURE_REDISPLAY
+ QString anObjInfo = ModuleBase_Tools::objectInfo((aObj));
+ qDebug(QString(" display object = %1").arg(anObjInfo).toStdString().c_str());
+ #endif
// Deactivate object of current operation from selection
if (myDisplayer->isActive(aObj))
myDisplayer->deactivate(aObj);
isDisplayed = displayObject(*aIt);
//}
}
- if (myObjectBrowser)
- myObjectBrowser->processEvent(theMsg);
+ //if (myObjectBrowser)
+ // myObjectBrowser->processEvent(theMsg);
if (isDisplayed)
myDisplayer->updateViewer();
//if (aHasPart) { // TODO: Avoid activate last part on loading of document
//}
}
-//******************************************************
-void XGUI_Workshop::onObjectDeletedMsg(const std::shared_ptr<ModelAPI_ObjectDeletedMessage>& theMsg)
-{
- if (myObjectBrowser)
- myObjectBrowser->processEvent(theMsg);
- //std::set<ObjectPtr> aFeatures = theMsg->objects();
-}
-
//******************************************************
void XGUI_Workshop::onOperationStarted(ModuleBase_Operation* theOperation)
{
//myDisplayer->activateObjects(aModes);
myModule->operationStopped(theOperation);
- if (myOperationMgr->operationsCount() == 0) {
+ // if the operation is nested, do not deactivate objects
+ //if (myOperationMgr->operationsCount() == 0) {
// Activate selection mode for all objects
- QIntList aModes;
- myDisplayer->activateObjects(aModes);
- }
+ QIntList aModes;
+ // TODO: check on OCC_6.9.0
+ // the module current active modes should not be deactivated in order to save the objects selected
+ // the deactivate object in the mode of selection leads to the object is deselected in the viewer.
+ // But, in OCC_6.8.0 this deselection does not happened automatically. It is necessary to call
+ // ClearOutdatedSelection, but this method has an error in the realization, which should be fixed in
+ // the OCC_6.9.0 release. Moreother, it is possible that ClearOutdatedSelection will be called inside
+ // Deactivate method of AIS_InteractiveContext. In this case, we need not call it.
+ module()->activeSelectionModes(aModes);
+ myDisplayer->activateObjects(aModes);
+ //}
}
}
ActionInfo aFeatureInfo;
aFeatureInfo.initFrom(theMessage);
- // Remember features icons
- myIcons[QString::fromStdString(theMessage->id())] = aFeatureInfo.iconFile;
QString aWchName = QString::fromStdString(theMessage->workbenchId());
QStringList aNestedFeatures =
} else if (anAnswer == QMessageBox::Cancel) {
return;
}
- aSession->closeAll();
myCurrentDir = "";
}
}
QApplication::setOverrideCursor(Qt::WaitCursor);
myIsLoadingData = true;
+ aSession->closeAll();
aSession->load(myCurrentDir.toLatin1().constData());
myObjectBrowser->rebuildDataTree();
displayAllResults();
aObjDock->setStyleSheet(
"::title { position: relative; padding-left: 5px; text-align: left center }");
myObjectBrowser = new XGUI_ObjectsBrowser(aObjDock);
- connect(myObjectBrowser, SIGNAL(activePartChanged(ObjectPtr)), this,
- SLOT(changeCurrentDocument(ObjectPtr)));
+ myObjectBrowser->setDataModel(myModule->dataModel());
+ myModule->customizeObjectBrowser(myObjectBrowser);
aObjDock->setWidget(myObjectBrowser);
myContextMenuMgr->connectObjectBrowser();
}
}
-//******************************************************
-void XGUI_Workshop::changeCurrentDocument(ObjectPtr theObj)
-{
- SessionPtr aMgr = ModelAPI_Session::get();
- if (theObj) {
- ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(theObj);
- if (aPart) {
- DocumentPtr aPartDoc = aPart->partDoc();
- if (aPartDoc) {
- aMgr->setActiveDocument(aPartDoc);
- return;
- }
- }
- }
- aMgr->setActiveDocument(aMgr->moduleDocument());
-}
-
//******************************************************
void XGUI_Workshop::salomeViewerSelectionChanged()
{
void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
{
QObjectPtrList aObjects = mySelector->selection()->selectedObjects();
- if ((theId == "ACTIVATE_PART_CMD") && (aObjects.size() > 0)) {
- ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObjects.first());
- activatePart(aPart);
- } else if (theId == "DEACTIVATE_PART_CMD")
- activatePart(ResultPartPtr());
- else if (theId == "DELETE_CMD")
+ if (theId == "DELETE_CMD")
deleteObjects();
else if (theId == "COLOR_CMD")
changeColor(aObjects);
setDisplayMode(aObjects, XGUI_Displayer::Shading);
else if (theId == "WIREFRAME_CMD")
setDisplayMode(aObjects, XGUI_Displayer::Wireframe);
- else if (theId == "HIDEALL_CMD")
- myDisplayer->eraseAll();
- else if (theId == "EDIT_CMD") {
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObjects.first());
- if (aFeature == NULL) {
- ResultParameterPtr aParam =
- std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObjects.first());
- if (aParam.get() != NULL) {
- aFeature = ModelAPI_Feature::feature(aParam);
- }
- }
- if (aFeature.get() != NULL)
- myModule->editFeature(aFeature);
+ else if (theId == "HIDEALL_CMD") {
+ QObjectPtrList aList = myDisplayer->displayedObjects();
+ foreach (ObjectPtr aObj, aList)
+ aObj->setDisplayed(false);
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
}
}
-//**************************************************************
-void XGUI_Workshop::activatePart(ResultPartPtr theFeature)
-{
- if (!myPartActivating) {
- myPartActivating = true;
- if (theFeature)
- theFeature->activate();
- changeCurrentDocument(theFeature);
- myObjectBrowser->activatePart(theFeature);
- myPartActivating = false;
- }
- updateCommandStatus();
-}
-
-//**************************************************************
-//void XGUI_Workshop::activateLastPart()
-//{
-// SessionPtr aMgr = ModelAPI_Session::get();
-// DocumentPtr aDoc = aMgr->moduleDocument();
-// std::string aGrpName = ModelAPI_ResultPart::group();
-// ObjectPtr aLastPart = aDoc->object(aGrpName, aDoc->size(aGrpName) - 1);
-// ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aLastPart);
-// if (aPart) {
-// activatePart(aPart);
-// }
-//}
-
//**************************************************************
void XGUI_Workshop::deleteObjects()
{
bool hasResult = false;
bool hasFeature = false;
bool hasParameter = false;
- XGUI_Tools::checkObjects(anObjects, hasResult, hasFeature, hasParameter);
+ ModuleBase_Tools::checkObjects(anObjects, hasResult, hasFeature, hasParameter);
if (!(hasFeature || hasParameter))
return;
aTypes.insert(ModelAPI_ResultGroup::group());
aTypes.insert(ModelAPI_ResultConstruction::group());
aTypes.insert(ModelAPI_ResultBody::group());
+ aTypes.insert(ModelAPI_ResultPart::group());
+
return hasResults(aObjects, aTypes);
}
+void setColor(ResultPtr theResult, std::vector<int>& theColor)
+{
+ if (!theResult.get())
+ return;
+
+ AttributeIntArrayPtr aColorAttr = theResult->data()->intArray(ModelAPI_Result::COLOR_ID());
+ if (aColorAttr.get() != NULL) {
+ if (!aColorAttr->size()) {
+ aColorAttr->setSize(3);
+ }
+ aColorAttr->setValue(0, theColor[0]);
+ aColorAttr->setValue(1, theColor[1]);
+ aColorAttr->setValue(2, theColor[2]);
+ }
+}
+
//**************************************************************
void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects)
{
+ AttributeIntArrayPtr aColorAttr;
+ // 1. find the current color of the object. This is a color of AIS presentation
+ // The objects are iterated until a first valid color is found
std::vector<int> aColor;
foreach(ObjectPtr anObject, theObjects) {
-
- AISObjectPtr anAISObj = myDisplayer->getAISObject(anObject);
- aColor.resize(3);
- anAISObj->getColor(aColor[0], aColor[1], aColor[2]);
+ if (anObject->groupName() == ModelAPI_ResultPart::group()) {
+ ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(anObject);
+ DocumentPtr aPartDoc = aPart->partDoc();
+ // the document should be checked on null, because in opened document if the part
+ // has not been activated yet, the part document is empty
+ if (!aPartDoc.get()) {
+ emit errorOccurred(QString::fromLatin1("Color can not be changed on a part with an empty document"));
+ }
+ else {
+ if (aPartDoc->size(ModelAPI_ResultBody::group()) > 0) {
+ ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultBody::group(), 0);
+ ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aObject);
+ if (aBody.get()) {
+ std::string aSection, aName, aDefault;
+ aBody->colorConfigInfo(aSection, aName, aDefault);
+ if (!aSection.empty() && !aName.empty()) {
+ aColor = Config_PropManager::color(aSection, aName, aDefault);
+ }
+ }
+ }
+ }
+ }
+ else {
+ AISObjectPtr anAISObj = myDisplayer->getAISObject(anObject);
+ if (anAISObj.get()) {
+ aColor.resize(3);
+ anAISObj->getColor(aColor[0], aColor[1], aColor[2]);
+ }
+ }
if (!aColor.empty())
break;
}
return;
// 2. show the dialog to change the value
- QDialog* aDlg = new QDialog();
- QVBoxLayout* aLay = new QVBoxLayout(aDlg);
-
- QtxColorButton* aColorBtn = new QtxColorButton(aDlg);
- aColorBtn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
-
- aLay->addWidget(aColorBtn);
- aColorBtn->setColor(QColor(aColor[0], aColor[1], aColor[2]));
-
- QDialogButtonBox* aButtons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
- Qt::Horizontal, aDlg);
- connect(aButtons, SIGNAL(accepted()), aDlg, SLOT(accept()));
- connect(aButtons, SIGNAL(rejected()), aDlg, SLOT(reject()));
- aLay->addWidget(aButtons);
-
+ XGUI_ColorDialog* aDlg = new XGUI_ColorDialog(mainWindow());
+ aDlg->setColor(aColor);
aDlg->move(QCursor::pos());
bool isDone = aDlg->exec() == QDialog::Accepted;
if (!isDone)
return;
- QColor aColorResult = aColorBtn->color();
- int aRedResult = aColorResult.red(),
- aGreenResult = aColorResult.green(),
- aBlueResult = aColorResult.blue();
-
- if (aRedResult == aColor[0] && aGreenResult == aColor[1] && aBlueResult == aColor[2])
- return;
+ bool isRandomColor = aDlg->isRandomColor();
// 3. abort the previous operation and start a new one
SessionPtr aMgr = ModelAPI_Session::get();
bool aWasOperation = aMgr->isOperation(); // keep this value
if (!aWasOperation) {
- QString aDescription = contextMenuMgr()->action("DELETE_CMD")->text();
+ QString aDescription = contextMenuMgr()->action("COLOR_CMD")->text();
aMgr->startOperation(aDescription.toStdString());
}
// 4. set the value to all results
- AttributeIntArrayPtr aColorAttr;
foreach(ObjectPtr anObj, theObjects) {
ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObj);
if (aResult.get() != NULL) {
- aColorAttr = aResult->data()->intArray(ModelAPI_Result::COLOR_ID());
- if (aColorAttr.get() != NULL) {
- if (!aColorAttr->size()) {
- aColorAttr->setSize(3);
+ if (aResult->groupName() == ModelAPI_ResultPart::group()) {
+ ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aResult);
+ DocumentPtr aPartDoc = aPart->partDoc();
+ // the document should be checked on null, because in opened document if the part
+ // has not been activated yet, the part document is empty
+ if (aPartDoc.get()) {
+ for (int i = 0; i < aPartDoc->size(ModelAPI_ResultBody::group()); i++) {
+ ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultBody::group(), i);
+ ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aObject);
+ std::vector<int> aColorResult = aDlg->getColor();
+ setColor(aBody, aColorResult);
+ }
}
- aColorAttr->setValue(0, aRedResult);
- aColorAttr->setValue(1, aGreenResult);
- aColorAttr->setValue(2, aBlueResult);
+ }
+ else {
+ std::vector<int> aColorResult = aDlg->getColor();
+ setColor(aResult, aColorResult);
}
}
}
//**************************************************************
void XGUI_Workshop::showObjects(const QObjectPtrList& theList, bool isVisible)
{
- foreach (ObjectPtr aObj, theList)
- {
+ foreach (ObjectPtr aObj, theList) {
if (isVisible) {
- displayObject(aObj);
+ aObj->setDisplayed(true);
+ //displayObject(aObj);
} else {
- myDisplayer->erase(aObj, false);
+ aObj->setDisplayed(false);
+ //myDisplayer->erase(aObj, false);
}
}
- myDisplayer->updateViewer();
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+ //myDisplayer->updateViewer();
}
//**************************************************************
void XGUI_Workshop::showOnlyObjects(const QObjectPtrList& theList)
{
- myDisplayer->showOnly(theList);
+ QObjectPtrList aList = myDisplayer->displayedObjects();
+ foreach (ObjectPtr aObj, aList)
+ aObj->setDisplayed(false);
+ foreach (ObjectPtr aObj, theList)
+ aObj->setDisplayed(true);
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+
}
//**************************************************************
void XGUI_Workshop::displayGroupResults(DocumentPtr theDoc, std::string theGroup)
{
- for (int i = 0; i < theDoc->size(theGroup); i++)
- displayObject(theDoc->object(theGroup, i));
+ for (int i = 0; i < theDoc->size(theGroup); i++)
+ theDoc->object(theGroup, i)->setDisplayed(true);
+ //displayObject(theDoc->object(theGroup, i));
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
}
//**************************************************************
/// \return a desktop instance
QMainWindow* desktop() const;
- //! Returns icon name according to feature
- static QIcon featureIcon(const FeaturePtr& theFeature);
-
- //! Activates or deactivates a part
- //! If PartPtr is Null pointer then PartSet will be activated
- void activatePart(std::shared_ptr<ModelAPI_ResultPart> theFeature);
-
//! Delete features
void deleteObjects();
/// Reaction on command call
void onFeatureTriggered();
- /// Change active document
- /// \param theObj a part object. If it is NULL then active document is a main document
- void changeCurrentDocument(ObjectPtr theObj);
-
- //void activateLastPart();
-
/// Close document
void closeDocument();
/// Process feature redisplay message
void onFeatureRedisplayMsg(const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& );
- /// Process feature delete message
- void onObjectDeletedMsg(const std::shared_ptr<ModelAPI_ObjectDeletedMessage>& );
-
/// Display all results
void displayAllResults();
XGUI_ModuleConnector* myModuleConnector;
QString myCurrentDir;
- static QMap<QString, QString> myIcons;
bool myUpdatePrefs;
<file>pictures/button_help.png</file>
<file>pictures/button_ok.png</file>
- <file>pictures/edit.png</file>
- <file>pictures/exec_state_failed.png</file>
- <file>pictures/exec_state_invalid_parameters.png</file>
<file>pictures/assembly.png</file>
- <file>pictures/activate.png</file>
<file>pictures/delete.png</file>
<file>pictures/rename_edit.png</file>
<file>pictures/eye_pencil.png</file>
<file>pictures/shading.png</file>
<file>pictures/wireframe.png</file>
<file>pictures/expression.png</file>
+ <file>pictures/arrow.png</file>
</qresource>
</RCC>