X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FXGUI%2FXGUI_Workshop.cpp;h=fbdb6379b393f11fddb917661ea703cfa44ac69f;hb=3a60523c3fa0af9d8daf760fcf13f7f2c45836de;hp=7f432db6b281a32cb3650905b2079edf57217472;hpb=4049559747c32c5ec443cf3d60501bc64a17e58a;p=modules%2Fshaper.git diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 7f432db6b..fbdb6379b 100755 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -4,6 +4,7 @@ #include "XGUI_Workshop.h" #include "XGUI_ActionsMgr.h" +#include "XGUI_MenuMgr.h" #include "XGUI_ColorDialog.h" #include "XGUI_ContextMenuMgr.h" #include "XGUI_Displayer.h" @@ -66,6 +67,9 @@ #include #include #include +#include +#include +#include #include #include @@ -73,6 +77,7 @@ #include #include #include +#include #include @@ -117,7 +122,8 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) mySalomeConnector(theConnector), myPropertyPanel(0), myObjectBrowser(0), - myDisplayer(0) + myDisplayer(0), + myViewerSelMode(TopAbs_FACE) { #ifndef HAVE_SALOME myMainWindow = new AppElements_MainWindow(); @@ -130,6 +136,9 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) QLocale::setDefault( QLocale::system() ); #endif + myDataModelXMLReader = new Config_DataModelReader(); + myDataModelXMLReader->readAll(); + myDisplayer = new XGUI_Displayer(this); mySelector = new XGUI_SelectionMgr(this); @@ -137,14 +146,15 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) myOperationMgr = new XGUI_OperationMgr(this, 0); myActionsMgr = new XGUI_ActionsMgr(this); + myMenuMgr = new XGUI_MenuMgr(this); myErrorDlg = new XGUI_ErrorDialog(QApplication::desktop()); myContextMenuMgr = new XGUI_ContextMenuMgr(this); connect(myContextMenuMgr, SIGNAL(actionTriggered(const QString&, bool)), this, SLOT(onContextMenuCommand(const QString&, bool))); myViewerProxy = new XGUI_ViewerProxy(this); - connect(myViewerProxy, SIGNAL(selectionChanged()), - myActionsMgr, SLOT(updateOnViewSelection())); + //connect(myViewerProxy, SIGNAL(selectionChanged()), + // myActionsMgr, SLOT(updateOnViewSelection())); myModuleConnector = new XGUI_ModuleConnector(this); @@ -185,12 +195,16 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) Config_Prop::Color, ModelAPI_ResultConstruction::DEFAULT_COLOR()); Config_PropManager::registerProp("Visualization", "result_part_color", "Part color", Config_Prop::Color, ModelAPI_ResultPart::DEFAULT_COLOR()); + + myViewerSelMode = + ModuleBase_Preferences::resourceMgr()->integerValue("Viewer", "selection", TopAbs_FACE); } //****************************************************** XGUI_Workshop::~XGUI_Workshop(void) { delete myDisplayer; + delete myDataModelXMLReader; } //****************************************************** @@ -236,12 +250,11 @@ void XGUI_Workshop::activateModule() updateCommandStatus(); + // TODO: get default selection mode + // activate visualized objects in the viewer - XGUI_Displayer* aDisplayer = displayer(); - QObjectPtrList aDisplayed = aDisplayer->displayedObjects(); - QIntList aModes; - module()->activeSelectionModes(aModes); - aDisplayer->activateObjects(aModes, aDisplayed); + activateObjectsSelection(displayer()->displayedObjects()); + myOperationMgr->activate(); } void XGUI_Workshop::deactivateModule() @@ -259,6 +272,8 @@ void XGUI_Workshop::deactivateModule() XGUI_Displayer* aDisplayer = displayer(); QObjectPtrList aDisplayed = aDisplayer->displayedObjects(); aDisplayer->deactivateObjects(aDisplayed, true); + + myOperationMgr->deactivate(); } //****************************************************** @@ -295,12 +310,12 @@ void XGUI_Workshop::initMenu() //connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onRebuild())); //salomeConnector()->addDesktopMenuSeparator("MEN_DESK_EDIT"); - aAction = salomeConnector()->addDesktopCommand("SAVEAS_CMD", tr("Export NewGeom..."), tr("Export the current document into a NewGeom file"), + aAction = salomeConnector()->addDesktopCommand("SAVEAS_CMD", tr("Export native..."), tr("Export the current document into a native file"), QIcon(), QKeySequence(), false, "MEN_DESK_FILE"); connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onSaveAs())); - aAction = salomeConnector()->addDesktopCommand("OPEN_CMD", tr("Import NewGeom..."), tr("Import a NewGeom file"), + aAction = salomeConnector()->addDesktopCommand("OPEN_CMD", tr("Import native..."), tr("Import native file"), QIcon(), QKeySequence(), false, "MEN_DESK_FILE"); connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onOpen())); @@ -400,6 +415,21 @@ void XGUI_Workshop::onAcceptActionClicked() } } +//****************************************************** +void XGUI_Workshop::onPreviewActionClicked() +{ + ModuleBase_IPropertyPanel* aPanel = propertyPanel(); + if (aPanel) { + ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget(); + if (anActiveWidget && anActiveWidget->getValueState() == ModuleBase_ModelWidget::ModifiedInPP) { + anActiveWidget->storeValue(); + } + } + std::shared_ptr aMsg = std::shared_ptr( + new Events_Message(Events_Loop::eventByName(EVENT_PREVIEW_REQUESTED))); + Events_Loop::loop()->send(aMsg); +} + //****************************************************** void XGUI_Workshop::deactivateActiveObject(const ObjectPtr& theObject, const bool theUpdateViewer) { @@ -430,46 +460,107 @@ bool XGUI_Workshop::isFeatureOfNested(const FeaturePtr& theFeature) return aHasNested; } -//****************************************************** -void XGUI_Workshop::onOperationStarted(ModuleBase_Operation* theOperation) +void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* theOperation) { - setGrantedFeatures(theOperation); - - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (theOperation); + ModuleBase_OperationFeature* aFOperation = dynamic_cast(theOperation); if (!aFOperation) return; - if (aFOperation->getDescription()->hasXmlRepresentation()) { //!< No need for property panel - setPropertyPanel(aFOperation); - // filling the operation values by the current selection - // if the operation can be committed after the controls filling, the method perform should - // be stopped. Otherwise unnecessary presentations can be shown(e.g. operation prs in sketch) - if (!aFOperation->isEditOperation()) { - aFOperation->activateByPreselection(); - if (operationMgr()->currentOperation() != aFOperation) - return; + showPropertyPanel(); + myPropertyPanel->cleanContent(); + + QList aWidgets; + if (!module()->createWidgets(theOperation, aWidgets)) { + QString aXmlRepr = aFOperation->getDescription()->xmlRepresentation(); + ModuleBase_WidgetFactory aFactory(aXmlRepr.toStdString(), myModuleConnector); + aFactory.createWidget(myPropertyPanel->contentWidget()); + aWidgets = aFactory.getModelWidgets(); + } + + // check compatibility of feature and widgets + FeaturePtr aFeature = aFOperation->feature(); + std::string aFeatureKind = aFeature->getKind(); + foreach (ModuleBase_ModelWidget* aWidget, aWidgets) { + if (!aWidget->attributeID().empty() && !aFeature->attribute(aWidget->attributeID()).get()) { + std::string anErrorMsg = "The feature '" + aFeatureKind + "' has no attribute '" + + aWidget->attributeID() + "' used by widget '" + + aWidget->metaObject()->className() + "'."; + Events_Error::send(anErrorMsg); + myPropertyPanel->cleanContent(); + return; } } - updateCommandStatus(); + // for performance purpose, flush should be done after all controls are filled + bool isUpdateFlushed = false; + foreach (ModuleBase_ModelWidget* aWidget, aWidgets) { + bool isStoreValue = !aFOperation->isEditOperation() && + !aWidget->getDefaultValue().empty() && + !aWidget->isComputedDefault(); + aWidget->setFeature(aFeature, isStoreValue, isUpdateFlushed); + if (!isStoreValue) + aWidget->restoreValue(); + aWidget->enableFocusProcessing(); + } + ModuleBase_Tools::flushUpdated(aFeature); - connectToPropertyPanel(true); - myModule->operationStarted(aFOperation); + // update visible state of Preview button +#ifdef HAVE_SALOME + bool anIsAutoPreview = mySalomeConnector->featureInfo(aFeatureKind.c_str())->isAutoPreview(); +#else + AppElements_MainMenu* aMenuBar = mainWindow()->menuObject(); + AppElements_Command* aCommand = aMenuBar->feature(aFeatureKind.c_str()); + bool anIsAutoPreview = aCommand && aCommand->featureMessage()->isAutoPreview(); +#endif + if (!anIsAutoPreview) { + myPropertyPanel->findButton(PROP_PANEL_PREVIEW)->setVisible(true); + // send signal about preview should not be computed automatically, click on preview + // button should initiate it + std::shared_ptr aMsg = std::shared_ptr( + new Events_Message(Events_Loop::eventByName(EVENT_PREVIEW_BLOCKED))); + Events_Loop::loop()->send(aMsg); + } + myPropertyPanel->setModelWidgets(aWidgets); + aFOperation->setPropertyPanel(myPropertyPanel); - // the objects of the current operation should be deactivated - QObjectPtrList anObjects; - FeaturePtr aFeature = aFOperation->feature(); - anObjects.append(aFeature); - std::list aResults = aFeature->results(); - std::list::const_iterator aIt; - for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { - anObjects.append(*aIt); - } - QObjectPtrList::const_iterator anIt = anObjects.begin(), aLast = anObjects.end(); - for (; anIt != aLast; anIt++) - deactivateActiveObject(*anIt, false); - if (anObjects.size() > 0) - myDisplayer->updateViewer(); + myModule->propertyPanelDefined(theOperation); + +#ifndef DEBUG_FEATURE_NAME + myPropertyPanel->setWindowTitle(theOperation->getDescription()->description()); +#else + std::string aFeatureName = aFeature->name(); + myPropertyPanel->setWindowTitle(QString("%1: %2").arg(theOperation->getDescription()->description()) + .arg(aFeatureName.c_str())); +#endif + + myErrorMgr->setPropertyPanel(myPropertyPanel); +} + +void XGUI_Workshop::connectToPropertyPanel(const bool isToConnect) +{ + XGUI_PropertyPanel* aPropertyPanel = propertyPanel(); + if (aPropertyPanel) { + const QList& aWidgets = aPropertyPanel->modelWidgets(); + foreach (ModuleBase_ModelWidget* aWidget, aWidgets) { + myModule->connectToPropertyPanel(aWidget, isToConnect); + if (isToConnect) { + connect(aWidget, SIGNAL(valueStateChanged(int)), this, SLOT(onWidgetStateChanged(int))); + connect(aWidget, SIGNAL(valuesChanged()), this, SLOT(onValuesChanged())); + connect(aWidget, SIGNAL(objectUpdated()), this, SLOT(onWidgetObjectUpdated())); + } + else { + disconnect(aWidget, SIGNAL(valueStateChanged(int)), this, SLOT(onWidgetStateChanged(int))); + disconnect(aWidget, SIGNAL(valuesChanged()), this, SLOT(onValuesChanged())); + disconnect(aWidget, SIGNAL(objectUpdated()), this, SLOT(onWidgetObjectUpdated())); + } + } + } +} + +//****************************************************** +void XGUI_Workshop::onOperationStarted(ModuleBase_Operation* theOperation) +{ + setGrantedFeatures(theOperation); + myModule->operationStarted(theOperation); } //****************************************************** @@ -522,9 +613,7 @@ void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation) } } } - QIntList aModes; - module()->activeSelectionModes(aModes); - myDisplayer->activateObjects(aModes, anObjects); + activateObjectsSelection(anObjects); } @@ -545,8 +634,13 @@ void XGUI_Workshop::setGrantedFeatures(ModuleBase_Operation* theOperation) return; QStringList aGrantedIds; - if (isSalomeMode()) - aGrantedIds = mySalomeConnector->nestedActions(theOperation->id()); + if (isSalomeMode()) { + const std::shared_ptr& anInfo = + mySalomeConnector->featureInfo(theOperation->id()); + if (anInfo.get()) + aGrantedIds = QString::fromStdString(anInfo->nestedFeatures()) + .split(" ", QString::SkipEmptyParts); + } else aGrantedIds = myActionsMgr->nestedCommands(theOperation->id()); @@ -557,74 +651,6 @@ void XGUI_Workshop::setGrantedFeatures(ModuleBase_Operation* theOperation) aFOperation->setGrantedOperationIds(aGrantedIds); } -void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* theOperation) -{ - ModuleBase_OperationFeature* aFOperation = dynamic_cast(theOperation); - if (!aFOperation) - return; - - showPropertyPanel(); - QString aXmlRepr = aFOperation->getDescription()->xmlRepresentation(); - ModuleBase_WidgetFactory aFactory(aXmlRepr.toStdString(), myModuleConnector); - - myPropertyPanel->cleanContent(); - aFactory.createWidget(myPropertyPanel->contentWidget()); - - QList aWidgets = aFactory.getModelWidgets(); - - // check compatibility of feature and widgets - FeaturePtr aFeature = aFOperation->feature(); - foreach (ModuleBase_ModelWidget* aWidget, aWidgets) { - if (!aWidget->attributeID().empty() && !aFeature->attribute(aWidget->attributeID()).get()) { - std::string anErrorMsg = "The feature '" + aFeature->getKind() + "' has no attribute '" - + aWidget->attributeID() + "' used by widget '" - + aWidget->metaObject()->className() + "'."; - Events_Error::send(anErrorMsg); - myPropertyPanel->cleanContent(); - return; - } - } - - foreach (ModuleBase_ModelWidget* aWidget, aWidgets) { - bool isStoreValue = !aFOperation->isEditOperation() && - !aWidget->getDefaultValue().empty() && - !aWidget->isComputedDefault(); - aWidget->setFeature(aFOperation->feature(), isStoreValue); - aWidget->enableFocusProcessing(); - } - - myPropertyPanel->setModelWidgets(aWidgets); - aFOperation->setPropertyPanel(myPropertyPanel); - - myModule->propertyPanelDefined(theOperation); - -#ifndef DEBUG_FEATURE_NAME - myPropertyPanel->setWindowTitle(theOperation->getDescription()->description()); -#else - std::string aFeatureName = aFeature->name(); - myPropertyPanel->setWindowTitle(QString("%1: %2").arg(theOperation->getDescription()->description()) - .arg(aFeatureName.c_str())); -#endif - - myErrorMgr->setPropertyPanel(myPropertyPanel); -} - -void XGUI_Workshop::connectToPropertyPanel(const bool isToConnect) -{ - XGUI_PropertyPanel* aPropertyPanel = propertyPanel(); - if (aPropertyPanel) { - const QList& aWidgets = aPropertyPanel->modelWidgets(); - foreach (ModuleBase_ModelWidget* aWidget, aWidgets) { - myModule->connectToPropertyPanel(aWidget, isToConnect); - if (isToConnect) { - connect(aWidget, SIGNAL(valueStateChanged(int)), this, SLOT(onWidgetStateChanged(int))); - } - else { - disconnect(aWidget, SIGNAL(valueStateChanged(int)), this, SLOT(onWidgetStateChanged(int))); - } - } - } -} /* * Saves document with given name. @@ -893,6 +919,33 @@ void XGUI_Workshop::onWidgetStateChanged(int thePreviousState) myModule->widgetStateChanged(thePreviousState); } +//****************************************************** +void XGUI_Workshop::onValuesChanged() +{ + ModuleBase_ModelWidget* aSenderWidget = (ModuleBase_ModelWidget*)(sender()); + if (!aSenderWidget || aSenderWidget->canAcceptFocus()) + return; + + ModuleBase_ModelWidget* anActiveWidget = 0; + ModuleBase_Operation* anOperation = myOperationMgr->currentOperation(); + if (anOperation) { + ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel(); + if (aPanel) + anActiveWidget = aPanel->activeWidget(); + } + if (anActiveWidget) { + ModuleBase_WidgetValidated* aWidgetValidated = dynamic_cast + (anActiveWidget); + if (aWidgetValidated) + aWidgetValidated->clearValidatedCash(); + } +} + +void XGUI_Workshop::onWidgetObjectUpdated() +{ + operationMgr()->onValidateOperation(); +} + ModuleBase_IModule* XGUI_Workshop::loadModule(const QString& theModule) { QString libName = QString::fromStdString(library(theModule.toStdString())); @@ -966,6 +1019,9 @@ bool XGUI_Workshop::createModule() // myModule, SLOT(onBeforeObjectErase(ObjectPtr, AISObjectPtr))); myModule->createFeatures(); +#ifdef HAVE_SALOME + salomeConnector()->createFeatureActions(); +#endif //myActionsMgr->update(); return true; } @@ -1029,6 +1085,7 @@ QDockWidget* XGUI_Workshop::createObjectBrowser(QWidget* theParent) aObjDock->setStyleSheet( "::title { position: relative; padding-left: 5px; text-align: left center }"); myObjectBrowser = new XGUI_ObjectsBrowser(aObjDock); + myObjectBrowser->setXMLReader(myDataModelXMLReader); myModule->customizeObjectBrowser(myObjectBrowser); aObjDock->setWidget(myObjectBrowser); @@ -1060,11 +1117,14 @@ void XGUI_Workshop::createDockWidgets() QAction* aCancelAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Abort); connect(aCancelAct, SIGNAL(triggered()), myOperationMgr, SLOT(onAbortOperation())); + + QAction* aPreviewAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Preview); + connect(aPreviewAct, SIGNAL(triggered()), this, SLOT(onPreviewActionClicked())); + connect(myPropertyPanel, SIGNAL(keyReleased(QObject*, QKeyEvent*)), myOperationMgr, SLOT(onKeyReleased(QObject*, QKeyEvent*))); - - connect(myPropertyPanel, SIGNAL(enterClicked()), - myOperationMgr, SLOT(onProcessEnter())); + connect(myPropertyPanel, SIGNAL(enterClicked(QObject*)), + myOperationMgr, SLOT(onProcessEnter(QObject*))); } //****************************************************** @@ -1098,7 +1158,7 @@ void XGUI_Workshop::hidePropertyPanel() // in SALOME mode, workstack made the PyConsole the active window, // set the focus on it. As a result, shortcuts of the application, like // are processed by this console. For example Undo actions. - // It is possible that this code is to be moved to NewGeom package + // It is possible that this code is to be moved to SHAPER package QMainWindow* aDesktop = desktop(); ModuleBase_Tools::activateWindow(aDesktop, "XGUI_Workshop::hidePropertyPanel()"); ModuleBase_Tools::setFocus(aDesktop, "XGUI_Workshop::showPropertyPanel()"); @@ -1163,9 +1223,37 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked) aObj->setDisplayed(false); } Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); + } else if (theId == "SELECT_VERTEX_CMD") { + setViewerSelectionMode(TopAbs_VERTEX); + } else if (theId == "SELECT_EDGE_CMD") { + setViewerSelectionMode(TopAbs_EDGE); + } else if (theId == "SELECT_FACE_CMD") { + setViewerSelectionMode(TopAbs_FACE); + } else if (theId == "SELECT_RESULT_CMD") { + setViewerSelectionMode(-1); + } else if (theId == "SHOW_RESULTS_CMD") { + highlightResults(aObjects); } } +//************************************************************** +void XGUI_Workshop::setViewerSelectionMode(int theMode) +{ + myViewerSelMode = theMode; + activateObjectsSelection(myDisplayer->displayedObjects()); +} + +//************************************************************** +void XGUI_Workshop::activateObjectsSelection(const QObjectPtrList& theList) +{ + QIntList aModes; + module()->activeSelectionModes(aModes); + if (aModes.isEmpty() && (myViewerSelMode != -1)) + aModes.append(myViewerSelMode); + myDisplayer->activateObjects(aModes, theList); +} + + //************************************************************** void XGUI_Workshop::deleteObjects() { @@ -1179,9 +1267,6 @@ void XGUI_Workshop::deleteObjects() QObjectPtrList anObjects = mySelector->selection()->selectedObjects(); if (!abortAllOperations()) return; - // It is necessary to clear selection in order to avoid selection changed event during - // deletion and negative consequences connected with processing of already deleted items - mySelector->clearSelection(); // check whether the object can be deleted. There should not be parts which are not loaded if (!XGUI_Tools::canRemoveOrRename(desktop(), anObjects)) return; @@ -1189,24 +1274,36 @@ void XGUI_Workshop::deleteObjects() bool hasResult = false; bool hasFeature = false; bool hasParameter = false; - bool hasSubFeature = false; - ModuleBase_Tools::checkObjects(anObjects, hasResult, hasFeature, hasParameter, hasSubFeature); + bool hasCompositeOwner = false; + ModuleBase_Tools::checkObjects(anObjects, hasResult, hasFeature, hasParameter, hasCompositeOwner); if (!(hasFeature || hasParameter)) return; - // 1. start operation - QString aDescription = contextMenuMgr()->action("DELETE_CMD")->text(); - aDescription += " " + aDescription.arg(XGUI_Tools::unionOfObjectNames(anObjects, ", ")); - ModuleBase_OperationAction* anOpAction = new ModuleBase_OperationAction(aDescription, module()); - operationMgr()->startOperation(anOpAction); - // 3. delete objects std::set anIgnoredFeatures; - if (deleteFeatures(anObjects, anIgnoredFeatures, desktop(), true)) { - operationMgr()->commitOperation(); - } - else { - operationMgr()->abortOperation(operationMgr()->currentOperation()); + std::set aDirectRefFeatures, aIndirectRefFeatures; + ModuleBase_Tools::findReferences(anObjects, aDirectRefFeatures, aIndirectRefFeatures); + + bool doDeleteReferences = true; + if (ModuleBase_Tools::isDeleteFeatureWithReferences(anObjects, aDirectRefFeatures, + aIndirectRefFeatures, desktop(), doDeleteReferences)) { + // start operation + QString aDescription = contextMenuMgr()->action("DELETE_CMD")->text(); + aDescription += " " + aDescription.arg(XGUI_Tools::unionOfObjectNames(anObjects, ", ")); + ModuleBase_OperationAction* anOpAction = new ModuleBase_OperationAction(aDescription, module()); + operationMgr()->startOperation(anOpAction); + + // WORKAROUND, should be done before each object remove, if it presents in XGUI_DataModel tree + // It is necessary to clear selection in order to avoid selection changed event during + // deletion and negative consequences connected with processing of already deleted items + mySelector->clearSelection(); + + // delete and commit/abort operation in model + if (deleteFeaturesInternal(anObjects, aDirectRefFeatures, aIndirectRefFeatures, + anIgnoredFeatures, doDeleteReferences)) + operationMgr()->commitOperation(); + else + operationMgr()->abortOperation(operationMgr()->currentOperation()); } } @@ -1217,20 +1314,30 @@ void XGUI_Workshop::cleanHistory() return; QObjectPtrList anObjects = mySelector->selection()->selectedObjects(); - - // 1. find all referenced features - QList anUnusedObjects; - std::set aDirectRefFeatures; + QObjectPtrList aFeatures; foreach (ObjectPtr anObject, anObjects) { FeaturePtr aFeature = std::dynamic_pointer_cast(anObject); // for parameter result, use the corresponded reature to be removed if (!aFeature.get() && anObject->groupName() == ModelAPI_ResultParameter::group()) { aFeature = ModelAPI_Feature::feature(anObject); } + aFeatures.append(aFeature); + } + + // 1. find all referenced features + QList anUnusedObjects; + std::set aDirectRefFeatures; + //foreach (ObjectPtr anObject, anObjects) { + foreach (ObjectPtr anObject, aFeatures) { + FeaturePtr aFeature = std::dynamic_pointer_cast(anObject); + // for parameter result, use the corresponded reature to be removed + //if (!aFeature.get() && anObject->groupName() == ModelAPI_ResultParameter::group()) { + // aFeature = ModelAPI_Feature::feature(anObject); + //} if (aFeature.get()) { std::set alreadyProcessed; aDirectRefFeatures.clear(); - XGUI_Tools::refsDirectToFeatureInAllDocuments(aFeature, aFeature, anObjects, + ModuleBase_Tools::refsDirectToFeatureInAllDocuments(aFeature, aFeature, aFeatures, aDirectRefFeatures, alreadyProcessed); if (aDirectRefFeatures.empty() && !anUnusedObjects.contains(aFeature)) anUnusedObjects.append(aFeature); @@ -1257,6 +1364,21 @@ void XGUI_Workshop::cleanHistory() QString aText = QString(tr("Unused features are the following: %1.\nThese features will be deleted.\nWould you like to continue?") .arg(anUnusedNames)); + /*QString aText; + if (anUnusedNames.isEmpty()) { + aMessageBox.setStandardButtons(QMessageBox::Ok); + aMessageBox.setDefaultButton(QMessageBox::Ok); + + aText = QString(tr("All features are relevant, there is nothing to be deleted")); + } + else { + aMessageBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes); + aMessageBox.setDefaultButton(QMessageBox::No); + + aText = QString(tr("Unused features are the following: %1.\nThese features will be deleted.\nWould you like to continue?") + .arg(anUnusedNames)); + }*/ + aMessageBox.setText(aText); if (aMessageBox.exec() == QMessageBox::No) return; @@ -1266,14 +1388,39 @@ void XGUI_Workshop::cleanHistory() ModuleBase_OperationAction* anOpAction = new ModuleBase_OperationAction(aDescription, module()); operationMgr()->startOperation(anOpAction); + // WORKAROUND, should be done before each object remove, if it presents in XGUI_DataModel tree + // It is necessary to clear selection in order to avoid selection changed event during + // deletion and negative consequences connected with processing of already deleted items + mySelector->clearSelection(); + std::set anIgnoredFeatures; - if (removeFeatures(anUnusedObjects, anIgnoredFeatures, anActionId)) { + if (removeFeatures(anUnusedObjects, anIgnoredFeatures, anActionId, true)) { operationMgr()->commitOperation(); } else { operationMgr()->abortOperation(operationMgr()->currentOperation()); } } + else { + QString anActionId = "CLEAN_HISTORY_CMD"; + QString aDescription = contextMenuMgr()->action(anActionId)->text(); + + QMessageBox aMessageBox(desktop()); + aMessageBox.setWindowTitle(aDescription); + aMessageBox.setIcon(QMessageBox::Warning); + aMessageBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes); + aMessageBox.setDefaultButton(QMessageBox::No); + + QString aText; + aMessageBox.setStandardButtons(QMessageBox::Ok); + aMessageBox.setDefaultButton(QMessageBox::Ok); + + aText = QString(tr("All features are relevant, there is nothing to be deleted")); + aMessageBox.setText(aText); + + if (aMessageBox.exec() == QMessageBox::No) + return; + } } //************************************************************** @@ -1312,87 +1459,22 @@ void XGUI_Workshop::moveObjects() } //************************************************************** -bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList, - const std::set& theIgnoredFeatures, - QWidget* theParent, - const bool theAskAboutDeleteReferences) +bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theFeatures, + const std::set& theIgnoredFeatures) { -#ifdef DEBUG_DELETE - QStringList aDInfo; - QObjectPtrList::const_iterator aDIt = theList.begin(), aDLast = theList.end(); - for (; aDIt != aDLast; ++aDIt) { - aDInfo.append(ModuleBase_Tools::objectInfo((*aDIt))); - } - QString anInfoStr = aDInfo.join(", "); - qDebug(QString("deleteFeatures: %1, %2").arg(theList.size()).arg(anInfoStr).toStdString().c_str()); -#endif - - // 1. find all referenced features std::set aDirectRefFeatures, aIndirectRefFeatures; - foreach (ObjectPtr aDeletedObj, theList) { - std::set alreadyProcessed; - XGUI_Tools::refsToFeatureInAllDocuments(aDeletedObj, aDeletedObj, theList, aDirectRefFeatures, - aIndirectRefFeatures, alreadyProcessed); - std::set aDifference; - std::set_difference(aIndirectRefFeatures.begin(), aIndirectRefFeatures.end(), - aDirectRefFeatures.begin(), aDirectRefFeatures.end(), - std::inserter(aDifference, aDifference.begin())); - aIndirectRefFeatures = aDifference; - } - - bool doDeleteReferences = true; - - // 2. warn about the references remove, break the delete operation if the user chose it - if (theAskAboutDeleteReferences && !aDirectRefFeatures.empty()) { - QStringList aDirectRefNames; - foreach (const FeaturePtr& aFeature, aDirectRefFeatures) - aDirectRefNames.append(aFeature->name().c_str()); - QString aDirectNames = aDirectRefNames.join(", "); - - QStringList aIndirectRefNames; - foreach (const FeaturePtr& aFeature, aIndirectRefFeatures) - aIndirectRefNames.append(aFeature->name().c_str()); - QString aIndirectNames = aIndirectRefNames.join(", "); - - bool canReplaceParameters = true; - foreach (ObjectPtr aObj, theList) { - FeaturePtr aFeature = ModelAPI_Feature::feature(aObj); - if (!std::dynamic_pointer_cast(aFeature->firstResult()).get()) { // the feature is not a parameter - canReplaceParameters = false; - break; - } - } - - QMessageBox aMessageBox(theParent); - aMessageBox.setWindowTitle(tr("Delete features")); - aMessageBox.setIcon(QMessageBox::Warning); - aMessageBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes); - aMessageBox.setDefaultButton(QMessageBox::No); - - QString aText; - if (canReplaceParameters) { - aText = QString(tr("Selected parameters are used in the following features: %1.\nThese features will be deleted.\n%2Or parameters could be replaced by their values.\nWould you like to continue?")) - .arg(aDirectNames).arg(aIndirectNames.isEmpty() ? QString() : QString(tr("(Also these features will be deleted: %1)\n")).arg(aIndirectNames)); - QPushButton *aReplaceButton = aMessageBox.addButton(tr("Replace"), QMessageBox::ActionRole); - } else { - aText = QString(tr("Selected features are used in the following features: %1.\nThese features will be deleted.\n%2Would you like to continue?")) - .arg(aDirectNames).arg(aIndirectNames.isEmpty() ? QString() : QString(tr("Also these features will be deleted: %1.\n")).arg(aIndirectNames)); - } - aMessageBox.setText(aText); - aMessageBox.exec(); - QMessageBox::ButtonRole aButtonRole = aMessageBox.buttonRole(aMessageBox.clickedButton()); - - if (aButtonRole == QMessageBox::NoRole) - return false; - - if (aButtonRole == QMessageBox::ActionRole) { - foreach (ObjectPtr aObj, theList) - ModelAPI_ReplaceParameterMessage::send(aObj, this); - doDeleteReferences = false; - } - } + ModuleBase_Tools::findReferences(theFeatures, aDirectRefFeatures, aIndirectRefFeatures); + return deleteFeaturesInternal(theFeatures, aDirectRefFeatures, aIndirectRefFeatures, + theIgnoredFeatures); +} - // 3. remove referenced features +bool XGUI_Workshop::deleteFeaturesInternal(const QObjectPtrList& theList, + const std::set& aDirectRefFeatures, + const std::set& aIndirectRefFeatures, + const std::set& theIgnoredFeatures, + const bool doDeleteReferences) +{ + bool isDone = false; if (doDeleteReferences) { std::set aFeaturesToDelete = aDirectRefFeatures; aFeaturesToDelete.insert(aIndirectRefFeatures.begin(), aIndirectRefFeatures.end()); @@ -1405,7 +1487,9 @@ bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList, FeaturePtr aFeature = (*anIt); DocumentPtr aDoc = aFeature->document(); if (theIgnoredFeatures.find(aFeature) == theIgnoredFeatures.end()) { + // flush REDISPLAY signal after remove feature aDoc->removeFeature(aFeature); + isDone = true; #ifdef DEBUG_DELETE anInfo.append(ModuleBase_Tools::objectInfo(aFeature).toStdString().c_str()); #endif @@ -1418,13 +1502,21 @@ bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList, } QString anActionId = "DELETE_CMD"; - return removeFeatures(theList, theIgnoredFeatures, anActionId); + isDone = removeFeatures(theList, theIgnoredFeatures, anActionId, false) || isDone; + + if (isDone) { + // the redisplay signal should be flushed in order to erase the feature presentation in the viewer + // if should be done after removeFeature() of document + Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)); + } + return isDone; } //************************************************************** bool XGUI_Workshop::removeFeatures(const QObjectPtrList& theList, const std::set& theIgnoredFeatures, - const QString& theActionId) + const QString& theActionId, + const bool theFlushRedisplay) { bool isDone = false; @@ -1452,11 +1544,18 @@ bool XGUI_Workshop::removeFeatures(const QObjectPtrList& theList, anInfo.append(anInfoStr); qDebug(QString("remove feature :%1").arg(anInfoStr).toStdString().c_str()); #endif + // flush REDISPLAY signal after remove feature aDoc->removeFeature(aFeature); isDone = true; } } } + if (isDone && theFlushRedisplay) { + // the redisplay signal should be flushed in order to erase the feature presentation in the viewer + // if should be done after removeFeature() of document + Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)); + } + #ifdef DEBUG_DELETE qDebug(QString("remove features:%1").arg(anInfo.join("; ")).toStdString().c_str()); #endif @@ -1562,7 +1661,7 @@ bool XGUI_Workshop::canMoveFeature() std::set aPlacedFeatures(aFeaturesBetween.begin(), aFeaturesBetween.end()); // 2. Get all reference features to the selected object in the document std::set aRefFeatures; - XGUI_Tools::refsToFeatureInFeatureDocument(aObject, aRefFeatures); + ModuleBase_Tools::refsToFeatureInFeatureDocument(aObject, aRefFeatures); if (aRefFeatures.empty()) continue; @@ -1864,9 +1963,38 @@ void XGUI_Workshop::synchronizeGroupInViewer(const DocumentPtr& theDoc, int aSize = theDoc->size(theGroup); for (int i = 0; i < aSize; i++) { aObj = theDoc->object(theGroup, i); - if (aObj->isDisplayed()) + if (aObj->isDisplayed()) { + // Hide the presentation with an empty shape. But isDisplayed state of the object should not + // be changed to the object becomes visible when the shape becomes not empty + ResultPtr aRes = std::dynamic_pointer_cast(aObj); + if (aRes.get() && (!aRes->shape().get() || aRes->shape()->isNull())) + continue; myDisplayer->display(aObj, false); + } } if (theUpdateViewer) myDisplayer->updateViewer(); } + +void XGUI_Workshop::highlightResults(const QObjectPtrList& theObjects) +{ + FeaturePtr aFeature; + QObjectPtrList aSelList = theObjects; + std::list aResList; + foreach(ObjectPtr aObj, theObjects) { + aFeature = std::dynamic_pointer_cast(aObj); + if (aFeature.get()) { + aResList = aFeature->results(); + std::list >::const_iterator aIt; + for(aIt = aResList.cbegin(); aIt != aResList.cend(); aIt++) { + aSelList.append(*aIt); + } + } + } + if (aSelList.count() > theObjects.count()) { + // if something was found + bool aBlocked = objectBrowser()->blockSignals(true); + objectBrowser()->setObjectsSelected(aSelList); + objectBrowser()->blockSignals(aBlocked); + } +}