From 7b40e745dd80b0af027783d1d064ba84f44e97bb Mon Sep 17 00:00:00 2001 From: nds Date: Tue, 31 Mar 2015 12:35:06 +0300 Subject: [PATCH] 1. The incorrect behaviour fixed: Create a sketch(two circles), create an extrusion(use sketch in OB), edit sketch(create a new circle). The result is the extrusion is not redisplayed for the last circle. 2. Hide of the features from the initialization plugin after creation. There is a blinking in OCC viewer. TODO: emit a signal about block/unblock the OCC viewer update to avoid this blinking. --- src/InitializationPlugin/CMakeLists.txt | 1 + .../InitializationPlugin_Plugin.cpp | 46 +++++++++-- .../InitializationPlugin_Plugin.h | 4 +- src/ModuleBase/ModuleBase_IModule.cpp | 3 +- src/ModuleBase/ModuleBase_IModule.h | 3 +- src/PartSet/PartSet_Module.cpp | 36 ++------- src/PartSet/PartSet_SketcherMgr.cpp | 62 ++++++++++----- src/PartSet/PartSet_SketcherMgr.h | 2 +- src/PartSet/PartSet_Validators.cpp | 12 ++- src/XGUI/XGUI_Workshop.cpp | 79 +++++++++++++++---- src/XGUI/XGUI_Workshop.h | 5 +- 11 files changed, 169 insertions(+), 84 deletions(-) diff --git a/src/InitializationPlugin/CMakeLists.txt b/src/InitializationPlugin/CMakeLists.txt index 717e200ab..9f18bb661 100644 --- a/src/InitializationPlugin/CMakeLists.txt +++ b/src/InitializationPlugin/CMakeLists.txt @@ -4,6 +4,7 @@ INCLUDE(Common) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/Events ${PROJECT_SOURCE_DIR}/src/Config ${PROJECT_SOURCE_DIR}/src/ModelAPI + ${PROJECT_SOURCE_DIR}/src/GeomAPI ) SET(PROJECT_HEADERS diff --git a/src/InitializationPlugin/InitializationPlugin_Plugin.cpp b/src/InitializationPlugin/InitializationPlugin_Plugin.cpp index 553d22608..ad7077675 100644 --- a/src/InitializationPlugin/InitializationPlugin_Plugin.cpp +++ b/src/InitializationPlugin/InitializationPlugin_Plugin.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -31,12 +32,29 @@ void InitializationPlugin_Plugin::processEvent(const std::shared_ptr aMessage = std::dynamic_pointer_cast< ModelAPI_DocumentCreatedMessage>(theMessage); DocumentPtr aDoc = aMessage->document(); - createPoint(aDoc); - createPlane(aDoc, 1., 0., 0.); - createPlane(aDoc, 0., 1., 0.); - createPlane(aDoc, 0., 0., 1.); + std::list aFeatures; + + aFeatures.push_back(createPoint(aDoc)); + aFeatures.push_back(createPlane(aDoc, 1., 0., 0.)); + aFeatures.push_back(createPlane(aDoc, 0., 1., 0.)); + aFeatures.push_back(createPlane(aDoc, 0., 0., 1.)); // for PartSet it is done outside of the transaction, so explicitly flush this creation Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED)); + + // 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::const_iterator aFIter = aFeatures.begin(); + for (; aFIter != aFeatures.cend(); aFIter++) { + FeaturePtr aPlane = *aFIter; + const std::list >& aResults = aPlane->results(); + std::list::const_iterator aRIter = aResults.begin(); + for (; aRIter != aResults.cend(); aRIter++) { + ModelAPI_EventCreator::get()->sendUpdated(*aRIter, HIDE_DISP); + } + } + Events_Loop::loop()->flush(HIDE_DISP); + } else if (theMessage.get()) { Events_Error::send( std::string("InitializationPlugin_Plugin::processEvent: unhandled message caught: ") @@ -44,10 +62,10 @@ void InitializationPlugin_Plugin::processEvent(const std::shared_ptr aPlane = theDoc->addFeature("Plane"); + FeaturePtr aPlane = theDoc->addFeature("Plane"); aPlane->string("CreationMethod")->setValue("PlaneByGeneralEquation"); aPlane->real("A")->setValue(theX); aPlane->real("B")->setValue(theY); @@ -62,9 +80,15 @@ void InitializationPlugin_Plugin::createPlane(DocumentPtr theDoc, double theX, d aPlane->data()->setName("X0Y"); } aPlane->setInHistory(aPlane, false); // don't show automatically created feature in the features history + + // the plane should be executed in order to build the feature result immediatelly + // the results are to be hidden in the plugin + aPlane->execute(); + + return aPlane; } -void InitializationPlugin_Plugin::createPoint(DocumentPtr theDoc) +FeaturePtr InitializationPlugin_Plugin::createPoint(DocumentPtr theDoc) { std::shared_ptr aPoint = theDoc->addFeature("Point"); aPoint->real("x")->setValue(0.); @@ -72,4 +96,10 @@ void InitializationPlugin_Plugin::createPoint(DocumentPtr theDoc) aPoint->real("z")->setValue(0.); aPoint->data()->setName("Origin"); aPoint->setInHistory(aPoint, false); // don't show automatically created feature in the features history + + // the point should be executed in order to build the feature result immediatelly + // the results are to be hidden in the plugin + aPoint->execute(); + + return aPoint; } diff --git a/src/InitializationPlugin/InitializationPlugin_Plugin.h b/src/InitializationPlugin/InitializationPlugin_Plugin.h index 4ddaf7609..42d157703 100644 --- a/src/InitializationPlugin/InitializationPlugin_Plugin.h +++ b/src/InitializationPlugin/InitializationPlugin_Plugin.h @@ -32,10 +32,10 @@ class INITIALIZATIONPLUGIN_EXPORT InitializationPlugin_Plugin : public Events_Li /// \param theX - determines if X is 0 or not /// \param theY - determines if Y is 0 or not /// \param theZ - determines if Z is 0 or not - void createPlane(DocumentPtr theDoc, double theX, double theY, double theZ); + FeaturePtr createPlane(DocumentPtr theDoc, double theX, double theY, double theZ); /// Creates the origin point in (0,0,0) /// \param theDoc - document to contain a "point" feature - void createPoint(DocumentPtr theDoc); + FeaturePtr createPoint(DocumentPtr theDoc); }; #endif diff --git a/src/ModuleBase/ModuleBase_IModule.cpp b/src/ModuleBase/ModuleBase_IModule.cpp index 315be9178..1f759feb5 100644 --- a/src/ModuleBase/ModuleBase_IModule.cpp +++ b/src/ModuleBase/ModuleBase_IModule.cpp @@ -113,8 +113,7 @@ void ModuleBase_IModule::actionCreated(QAction* theFeature) bool ModuleBase_IModule::canDisplayObject(const ObjectPtr& theObject) const { - ModuleBase_Operation* anOperation = myWorkshop->currentOperation(); - return anOperation && anOperation->hasObject(theObject); + return true; } bool ModuleBase_IModule::canUndo() const diff --git a/src/ModuleBase/ModuleBase_IModule.h b/src/ModuleBase/ModuleBase_IModule.h index b29b4e51d..c7cd377cc 100644 --- a/src/ModuleBase/ModuleBase_IModule.h +++ b/src/ModuleBase/ModuleBase_IModule.h @@ -109,8 +109,7 @@ class MODULEBASE_EXPORT ModuleBase_IModule : public QObject //! Returns True if there are available Redos and there is not an active operation virtual bool canRedo() const; - /// Returns whether the object can be displayed at the bounds of the active operation. - /// Display only current operation results + /// Returns whether the object can be displayed. The default realization returns true. /// \param theObject a model object virtual bool canDisplayObject(const ObjectPtr& theObject) const; diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index 20cd41101..da5860f6c 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -275,36 +275,12 @@ bool PartSet_Module::canRedo() const bool PartSet_Module::canDisplayObject(const ObjectPtr& theObject) const { - bool aCanDisplay = false; - if (!mySketchMgr->canDisplayObject()) - return aCanDisplay; - CompositeFeaturePtr aSketchFeature = mySketchMgr->activeSketch(); - if (aSketchFeature.get() != NULL) { - FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); - - // MPV: the second and third conditions to avoid crash on exit for application - if (aFeature.get() != NULL && aFeature->data().get() && aFeature->data()->isValid()) { - if (aFeature == aSketchFeature) { - aCanDisplay = false; - } - else if (aSketchFeature.get() && aSketchFeature->data().get() && - aSketchFeature->data()->isValid()) { - for (int i = 0; i < aSketchFeature->numberOfSubs() && !aCanDisplay; i++) { - FeaturePtr aSubFeature = aSketchFeature->subFeature(i); - std::list aResults = aSubFeature->results(); - std::list::const_iterator aIt; - for (aIt = aResults.begin(); aIt != aResults.end() && !aCanDisplay; ++aIt) { - if (theObject == (*aIt)) - aCanDisplay = true; - } - if (aSubFeature == theObject) - aCanDisplay = true; - } - } - } - } - else { - aCanDisplay = ModuleBase_IModule::canDisplayObject(theObject); + // the display should be possible almost always, with exception of some specific cases + + bool aCanDisplay = true; + + if (mySketchMgr->activeSketch()) { + aCanDisplay = mySketchMgr->canDisplayObject(theObject); } return aCanDisplay; } diff --git a/src/PartSet/PartSet_SketcherMgr.cpp b/src/PartSet/PartSet_SketcherMgr.cpp index 2747c4004..6a8c084db 100644 --- a/src/PartSet/PartSet_SketcherMgr.cpp +++ b/src/PartSet/PartSet_SketcherMgr.cpp @@ -195,7 +195,8 @@ void PartSet_SketcherMgr::onLeaveViewPort() myIsPropertyPanelValueChanged = false; // the feature is to be erased here, but it is correct to call canDisplayObject because // there can be additional check (e.g. editor widget in distance constraint) - visualizeFeature(aOperation, canDisplayObject()); + FeaturePtr aFeature = getCurrentOperation()->feature(); + visualizeFeature(aOperation, canDisplayObject(aFeature)); } void PartSet_SketcherMgr::onBeforeValuesChangedInPropertyPanel() @@ -239,7 +240,8 @@ void PartSet_SketcherMgr::onValuesChangedInPropertyPanel() ModuleBase_Operation* aOperation = getCurrentOperation(); // the feature is to be erased here, but it is correct to call canDisplayObject because // there can be additional check (e.g. editor widget in distance constraint) - visualizeFeature(aOperation, canDisplayObject()); + FeaturePtr aFeature = getCurrentOperation()->feature(); + visualizeFeature(aOperation, canDisplayObject(aFeature)); } void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) @@ -375,7 +377,8 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve } // the feature is to be erased here, but it is correct to call canDisplayObject because // there can be additional check (e.g. editor widget in distance constraint) - visualizeFeature(aOperation, canDisplayObject()); + FeaturePtr aFeature = getCurrentOperation()->feature(); + visualizeFeature(aOperation, canDisplayObject(aFeature)); } myClickedPoint.clear(); @@ -739,29 +742,46 @@ bool PartSet_SketcherMgr::canRedo() const return isNestedCreateOperation(getCurrentOperation()); } -bool PartSet_SketcherMgr::canDisplayObject() const +bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const { bool aCanDisplay = true; - if (!isNestedCreateOperation(getCurrentOperation())) - return aCanDisplay; - - ModuleBase_Operation* aOperation = getCurrentOperation(); - ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); - ModuleBase_ModelWidget* anActiveWdg = aPanel ? aPanel->activeWidget() : 0; - // the active widget editor should not influence here. The presentation should be visible always - // when this widget is active. - if (anActiveWdg) { - ModuleBase_WidgetEditor* anEditorWdg = dynamic_cast(anActiveWdg); - if (anEditorWdg) { + // 1. the sketch feature should not be displayed during the sketch active operation + // it is hidden by a sketch operation start and shown by a sketch stop, just the sketch + // nested features can be visualized + CompositeFeaturePtr aSketchFeature = activeSketch(); + if (aSketchFeature.get() != NULL) { + FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); + if (aFeature.get() != NULL && aFeature == aSketchFeature) + aCanDisplay = false; + } + // 2. For created nested feature operation do not display the created feature if + // the mouse curstor leaves the OCC window. + // The correction cases, which ignores this condition: + // a. the property panel values modification + // b. the popup menu activated + // c. widget editor control + if (aCanDisplay) { + if (!isNestedCreateOperation(getCurrentOperation())) return aCanDisplay; + + ModuleBase_Operation* aOperation = getCurrentOperation(); + ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); + ModuleBase_ModelWidget* anActiveWdg = aPanel ? aPanel->activeWidget() : 0; + // the active widget editor should not influence here. The presentation should be visible always + // when this widget is active. + if (anActiveWdg) { + ModuleBase_WidgetEditor* anEditorWdg = dynamic_cast(anActiveWdg); + if (anEditorWdg) { + return aCanDisplay; + } } - } - if (myIsPopupMenuActive) - return aCanDisplay; + if (myIsPopupMenuActive) + return aCanDisplay; - // during a nested create operation, the feature is redisplayed only if the mouse over view - // of there was a value modified in the property panel after the mouse left the view - aCanDisplay = myIsPropertyPanelValueChanged || myIsMouseOverWindow; + // during a nested create operation, the feature is redisplayed only if the mouse over view + // of there was a value modified in the property panel after the mouse left the view + aCanDisplay = myIsPropertyPanelValueChanged || myIsMouseOverWindow; + } return aCanDisplay; } diff --git a/src/PartSet/PartSet_SketcherMgr.h b/src/PartSet/PartSet_SketcherMgr.h index c5f7effe1..dc68f283a 100644 --- a/src/PartSet/PartSet_SketcherMgr.h +++ b/src/PartSet/PartSet_SketcherMgr.h @@ -135,7 +135,7 @@ public: /// Display only current operation results for usual operation and ask the sketcher manager /// if it is a sketch operation /// \param theObject a model object - bool canDisplayObject() const; + bool canDisplayObject(const ObjectPtr& theObject) const; /// Returns true if the current operation is sketch entity create operation /// \param theValue the current auxiliary value diff --git a/src/PartSet/PartSet_Validators.cpp b/src/PartSet/PartSet_Validators.cpp index 6d17784f7..04bcb3663 100644 --- a/src/PartSet/PartSet_Validators.cpp +++ b/src/PartSet/PartSet_Validators.cpp @@ -247,8 +247,16 @@ bool PartSet_SketchEntityValidator::isValid(const AttributePtr& theAttribute, for (int i = 0; i < aSelectionListAttr->size() && isSketchEntities; i++) { AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(i); ObjectPtr anObject = aSelectAttr->context(); - FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); - isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end(); + // a context of the selection attribute is a feature result. It can be a case when the result + // of the feature is null, e.g. the feature is modified and has not been executed yet. + // The validator returns an invalid result here. The case is an extrusion built on a sketch + // feature. A new sketch element creation leads to an empty result. + if (!anObject.get()) + isSketchEntities = false; + else { + FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); + isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end(); + } } } if (anAttributeType == ModelAPI_AttributeRefAttr::typeId()) { diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 2997907c0..3d7e3142e 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -92,6 +92,25 @@ #include #endif +//#define DEBUG_FEATURE_CREATED +//#define DEBUG_FEATURE_REDISPLAY + +QString objectInfo(ObjectPtr theObj) +{ + ResultPtr aRes = std::dynamic_pointer_cast(theObj); + FeaturePtr aFeature = std::dynamic_pointer_cast(theObj); + QString aFeatureStr = "feature"; + if(aRes.get()) { + aFeatureStr.append("(Result)"); + aFeature = ModelAPI_Feature::feature(aRes); + } + if (aFeature.get()) { + aFeatureStr.append(QString(": %1").arg(aFeature->getKind().c_str()).toStdString().c_str()); + } + return aFeatureStr; +} + + QMap XGUI_Workshop::myIcons; @@ -507,9 +526,20 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptr aObjects = theMsg->objects(); std::set::const_iterator aIt; + +#ifdef DEBUG_FEATURE_REDISPLAY + QStringList anInfo; + for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { + anInfo.append(objectInfo((*aIt))); + } + QString anInfoStr = anInfo.join(", "); + qDebug(QString("onFeatureRedisplayMsg: %1, %2").arg(aObjects.size()).arg(anInfoStr).toStdString().c_str()); +#endif + for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { ObjectPtr aObj = (*aIt); + // Hide the object if it is invalid or concealed one bool aHide = !aObj->data() || !aObj->data()->isValid(); if (!aHide) { // check that this is not hidden result ResultPtr aRes = std::dynamic_pointer_cast(aObj); @@ -518,7 +548,14 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptrerase(aObj, false); else { - if (myDisplayer->isVisible(aObj)) { + // Redisplay the visible object or the object of the current operation + bool isVisibleObject = myDisplayer->isVisible(aObj); + #ifdef DEBUG_FEATURE_REDISPLAY + QString anObjInfo = objectInfo((aObj)); + qDebug(QString("visible=%1 : display= %2").arg(isVisibleObject).arg(anObjInfo).toStdString().c_str()); + #endif + + if (isVisibleObject) { // redisplay visible object displayObject(aObj); // In order to update presentation if (myOperationMgr->hasOperation()) { ModuleBase_Operation* aOperation = myOperationMgr->currentOperation(); @@ -526,11 +563,11 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptrhasObject(aObj) && myDisplayer->isActive(aObj)) myDisplayer->deactivate(aObj); } - } else { - if (myOperationMgr->hasOperation()) { + } else { // display object if the current operation has it + ModuleBase_Operation* aOperation = myOperationMgr->currentOperation(); + if (aOperation && aOperation->hasObject(aObj)) { ModuleBase_Operation* aOperation = myOperationMgr->currentOperation(); - if (myModule->canDisplayObject(aObj)) { - displayObject(aObj); + if (displayObject(aObj)) { // Deactivate object of current operation from selection if (myDisplayer->isActive(aObj)) myDisplayer->deactivate(aObj); @@ -546,21 +583,28 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptr& theMsg) { std::set aObjects = theMsg->objects(); - std::set::const_iterator aIt; - bool aHasPart = false; +#ifdef DEBUG_FEATURE_CREATED + QStringList anInfo; + for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { + anInfo.append(objectInfo((*aIt))); + } + QString anInfoStr = anInfo.join(", "); + qDebug(QString("onFeatureCreatedMsg: %1, %2").arg(aObjects.size()).arg(anInfoStr).toStdString().c_str()); +#endif + + //bool aHasPart = false; bool isDisplayed = false; for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { - ResultPartPtr aPart = std::dynamic_pointer_cast(*aIt); - if (aPart) { - aHasPart = true; + //ResultPartPtr aPart = std::dynamic_pointer_cast(*aIt); + //if (aPart) { + //aHasPart = true; // If a feature is created from the aplication's python console // it doesn't stored in the operation mgr and doesn't displayed - } else if (myModule->canDisplayObject(*aIt)) { - displayObject(*aIt); - isDisplayed = true; - } + //} else { + isDisplayed = displayObject(*aIt); + //} } if (myObjectBrowser) myObjectBrowser->processEvent(theMsg); @@ -1573,8 +1617,11 @@ void XGUI_Workshop::closeDocument() } //************************************************************** -void XGUI_Workshop::displayObject(ObjectPtr theObj) +bool XGUI_Workshop::displayObject(ObjectPtr theObj) { + if (!myModule->canDisplayObject(theObj)) + return false; + ResultBodyPtr aBody = std::dynamic_pointer_cast(theObj); if (aBody.get() != NULL) { int aNb = myDisplayer->objectsCount(); @@ -1583,6 +1630,8 @@ void XGUI_Workshop::displayObject(ObjectPtr theObj) viewer()->fitAll(); } else myDisplayer->display(theObj, false); + + return true; } void XGUI_Workshop::addHistoryMenu(QObject* theObject, const char* theSignal, const char* theSlot) diff --git a/src/XGUI/XGUI_Workshop.h b/src/XGUI/XGUI_Workshop.h index c2b067741..baeff4448 100644 --- a/src/XGUI/XGUI_Workshop.h +++ b/src/XGUI/XGUI_Workshop.h @@ -391,7 +391,10 @@ signals: void createDockWidgets(); /// Displaus object and fit all viewer if the object is first (update viewer will not be called) - void displayObject(ObjectPtr theObj); + /// Asks the module whether the object can be displayed + /// \param theObj an object + /// \return true if the object is displayed + bool displayObject(ObjectPtr theObj); //! Extends undo/redo toolbutton's with history menu //! \param theObject - in the OpenParts it is a QToolButton by itself, -- 2.39.2