X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FXGUI%2FXGUI_Workshop.cpp;h=6892cfc6e86a8b41ad2b5460b4e1009e173b06f7;hb=f3fa014cb639143f47a71e37bccae8870c5a285c;hp=f8a81b03f701a6753fbb71fbde764f8fbfa7109e;hpb=825f6bb93bb05174728f82025d3a959068b476fe;p=modules%2Fshaper.git diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index f8a81b03f..6892cfc6e 100755 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -4,7 +4,9 @@ #include "XGUI_Workshop.h" #include "XGUI_ActionsMgr.h" +#include "XGUI_MenuMgr.h" #include "XGUI_ColorDialog.h" +#include "XGUI_DeflectionDialog.h" #include "XGUI_ContextMenuMgr.h" #include "XGUI_Displayer.h" #include "XGUI_ErrorDialog.h" @@ -35,6 +37,7 @@ #include #include +#include #include #include #include @@ -51,7 +54,7 @@ //#include #include -#include +#include #include #include @@ -66,6 +69,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -73,6 +80,8 @@ #include #include #include +#include +#include #include @@ -104,10 +113,11 @@ #include #endif - QString XGUI_Workshop::MOVE_TO_END_COMMAND = QObject::tr("Move to the end"); //#define DEBUG_DELETE +//#define DEBUG_FEATURE_NAME +//#define DEBUG_CLEAN_HISTORY XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) : QObject(), @@ -117,7 +127,15 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) myPropertyPanel(0), myObjectBrowser(0), myDisplayer(0) + //myViewerSelMode(TopAbs_FACE) { + mySelector = new XGUI_SelectionMgr(this); + myModuleConnector = new XGUI_ModuleConnector(this); + myOperationMgr = new XGUI_OperationMgr(this, 0); + ModuleBase_IWorkshop* aWorkshop = moduleConnector(); + // Has to be defined first in order to get errors and messages from other components + myEventsListener = new XGUI_WorkshopListener(aWorkshop); + #ifndef HAVE_SALOME myMainWindow = new AppElements_MainWindow(); @@ -128,33 +146,39 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) else QLocale::setDefault( QLocale::system() ); #endif + QString aPath = Config_XMLReader::pluginConfigFile().c_str(); + QDir aDir(aPath); + + // Load translations + QStringList aFilters; + aFilters << "*_en.ts"; + QStringList aTsFiles = aDir.entryList(aFilters, QDir::Files); + foreach(QString aFileName, aTsFiles) { + Config_Translator::load(aFileName.toStdString()); + } + + myDataModelXMLReader = new Config_DataModelReader(); + //myDataModelXMLReader->readAll(); myDisplayer = new XGUI_Displayer(this); - mySelector = new XGUI_SelectionMgr(this); connect(mySelector, SIGNAL(selectionChanged()), this, SLOT(updateCommandStatus())); - 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())); - - myModuleConnector = new XGUI_ModuleConnector(this); + //connect(myViewerProxy, SIGNAL(selectionChanged()), + // myActionsMgr, SLOT(updateOnViewSelection())); - ModuleBase_IWorkshop* aWorkshop = moduleConnector(); myOperationMgr->setWorkshop(aWorkshop); myErrorMgr = new XGUI_ErrorMgr(this, aWorkshop); - myEventsListener = new XGUI_WorkshopListener(aWorkshop); - connect(myOperationMgr, SIGNAL(operationStarted(ModuleBase_Operation*)), - SLOT(onOperationStarted(ModuleBase_Operation*))); connect(myOperationMgr, SIGNAL(operationResumed(ModuleBase_Operation*)), SLOT(onOperationResumed(ModuleBase_Operation*))); connect(myOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)), @@ -163,21 +187,19 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) SLOT(onOperationCommitted(ModuleBase_Operation*))); connect(myOperationMgr, SIGNAL(operationAborted(ModuleBase_Operation*)), SLOT(onOperationAborted(ModuleBase_Operation*))); - //connect(myOperationMgr, SIGNAL(validationStateChanged(bool)), - // myErrorMgr, SLOT(onValidationStateChanged())); #ifndef HAVE_SALOME connect(myMainWindow, SIGNAL(exitKeySequence()), SLOT(onExit())); + onTrihedronVisibilityChanged(true); #endif - connect(this, SIGNAL(errorOccurred(const QString&)), myErrorDlg, SLOT(addError(const QString&))); - connect(myEventsListener, SIGNAL(errorOccurred(const QString&)), - myErrorDlg, SLOT(addError(const QString&))); + connect(myEventsListener, SIGNAL(errorOccurred(std::shared_ptr)), + myErrorDlg, SLOT(addError(std::shared_ptr))); //Config_PropManager::registerProp("Visualization", "object_default_color", "Object color", // Config_Prop::Color, "225,225,225"); - Config_PropManager::registerProp("Visualization", "result_body_color", "Body color", + Config_PropManager::registerProp("Visualization", "result_body_color", "Result color", Config_Prop::Color, ModelAPI_ResultBody::DEFAULT_COLOR()); Config_PropManager::registerProp("Visualization", "result_group_color", "Group color", Config_Prop::Color, ModelAPI_ResultGroup::DEFAULT_COLOR()); @@ -185,24 +207,50 @@ 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()); + + Config_PropManager::registerProp("Visualization", "body_deflection", "Body deflection coefficient", + Config_Prop::Double, ModelAPI_ResultBody::DEFAULT_DEFLECTION());//"0.001"); + + Config_PropManager::registerProp("Visualization", "construction_deflection", "Construction deflection coefficient", + Config_Prop::Double, ModelAPI_ResultConstruction::DEFAULT_DEFLECTION());//"0.0001"); + + if (ModuleBase_Preferences::resourceMgr()->booleanValue("Viewer", "face-selection", true)) + myViewerSelMode.append(TopAbs_FACE); + if (ModuleBase_Preferences::resourceMgr()->booleanValue("Viewer", "edge-selection", true)) + myViewerSelMode.append(TopAbs_EDGE); + if (ModuleBase_Preferences::resourceMgr()->booleanValue("Viewer", "vertex-selection", true)) + myViewerSelMode.append(TopAbs_VERTEX); + //IMP: an attempt to use result selection with other selection modes + myViewerSelMode.append(ModuleBase_ResultPrs::Sel_Result);//TopAbs_VERTEX); + myViewerSelMode.append(TopAbs_COMPSOLID); } //****************************************************** XGUI_Workshop::~XGUI_Workshop(void) { +#ifdef _DEBUG +#ifdef MISSED_TRANSLATION + // Save Missed translations + Config_Translator::saveMissedTranslations(); +#endif +#endif + delete myDisplayer; + delete myDataModelXMLReader; } //****************************************************** void XGUI_Workshop::startApplication() { + //Initialize event listening + myEventsListener->initializeEventListening(); + + myDataModelXMLReader->readAll(); initMenu(); Config_PropManager::registerProp("Plugins", "default_path", "Default Path", Config_Prop::Directory, ""); - //Initialize event listening - myEventsListener->initializeEventListening(); registerValidators(); @@ -218,6 +266,10 @@ void XGUI_Workshop::startApplication() onNew(); + myViewerProxy->connectViewProxy(); + connect(myViewerProxy, SIGNAL(trihedronVisibilityChanged(bool)), + SLOT(onTrihedronVisibilityChanged(bool))); + emit applicationStarted(); } @@ -232,12 +284,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() @@ -255,6 +306,8 @@ void XGUI_Workshop::deactivateModule() XGUI_Displayer* aDisplayer = displayer(); QObjectPtrList aDisplayed = aDisplayer->displayedObjects(); aDisplayer->deactivateObjects(aDisplayed, true); + + myOperationMgr->deactivate(); } //****************************************************** @@ -291,12 +344,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())); @@ -397,19 +450,19 @@ void XGUI_Workshop::onAcceptActionClicked() } //****************************************************** -/*void XGUI_Workshop::onValidationStateChanged(bool theEnabled) +void XGUI_Workshop::onPreviewActionClicked() { - XGUI_OperationMgr* anOperationMgr = operationMgr(); - if (anOperationMgr) { - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (anOperationMgr->currentOperation()); - if (aFOperation) { - QAction* anAction = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Accept); - myErrorMgr->updateActionState(anAction, aFOperation->feature(), theEnabled); + 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) @@ -441,46 +494,99 @@ bool XGUI_Workshop::isFeatureOfNested(const FeaturePtr& theFeature) return aHasNested; } -//****************************************************** -void XGUI_Workshop::onOperationStarted(ModuleBase_Operation* theOperation) +void XGUI_Workshop::fillPropertyPanel(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 '%1' has no attribute '%2' used by widget '%3'."; + Events_InfoMessage("XGUI_Workshop", anErrorMsg) + .arg(aFeatureKind).arg(aWidget->attributeID()).arg(aWidget->metaObject()->className()).send(); + 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); + + // 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); - connectToPropertyPanel(true); - myModule->operationStarted(aFOperation); + myModule->propertyPanelDefined(theOperation); - // 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(); +#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())); + } + } + } } //****************************************************** @@ -489,7 +595,7 @@ void XGUI_Workshop::onOperationResumed(ModuleBase_Operation* theOperation) setGrantedFeatures(theOperation); if (theOperation->getDescription()->hasXmlRepresentation()) { //!< No need for property panel - setPropertyPanel(theOperation); + fillPropertyPanel(theOperation); connectToPropertyPanel(true); } updateCommandStatus(); @@ -524,7 +630,8 @@ void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation) if (aFeature.get()) { // feature may be not created (plugin load fail) if (myDisplayer->isVisible(aFeature) && !myDisplayer->isActive(aFeature)) anObjects.append(aFeature); - std::list aResults = aFeature->results(); + std::list aResults; + ModelAPI_Tools::allResults(aFeature, aResults); std::list::const_iterator aIt; for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { ResultPtr anObject = *aIt; @@ -533,9 +640,7 @@ void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation) } } } - QIntList aModes; - module()->activeSelectionModes(aModes); - myDisplayer->activateObjects(aModes, anObjects); + activateObjectsSelection(anObjects); } @@ -556,8 +661,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()); @@ -568,72 +678,7 @@ 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); - - myPropertyPanel->setWindowTitle(theOperation->getDescription()->description()); - - 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. - */ +//****************************************************** void XGUI_Workshop::saveDocument(const QString& theName, std::list& theFileNames) { QApplication::restoreOverrideCursor(); @@ -642,11 +687,24 @@ void XGUI_Workshop::saveDocument(const QString& theName, std::list& QApplication::restoreOverrideCursor(); } +//****************************************************** bool XGUI_Workshop::abortAllOperations() { return myOperationMgr->abortAllOperations(); } +//****************************************************** +void XGUI_Workshop::operationStarted(ModuleBase_Operation* theOperation) +{ + setGrantedFeatures(theOperation); + if (!theOperation->getDescription()->hasXmlRepresentation()) { //!< No need for property panel + updateCommandStatus(); + } + else { + myModule->operationStarted(theOperation); + } +} + //****************************************************** void XGUI_Workshop::onOpen() { @@ -669,20 +727,33 @@ void XGUI_Workshop::onOpen() } //show file dialog, check if readable and open - myCurrentDir = QFileDialog::getExistingDirectory(desktop(), tr("Select directory")); + QString aDirectory = QFileDialog::getExistingDirectory(desktop(), tr("Select directory")); + openDirectory(aDirectory); +} + +//****************************************************** +void XGUI_Workshop::openDirectory(const QString& theDirectory) +{ + myCurrentDir = theDirectory; if (myCurrentDir.isEmpty()) return; + QFileInfo aFileInfo(myCurrentDir); if (!aFileInfo.exists() || !aFileInfo.isReadable()) { QMessageBox::critical(desktop(), tr("Warning"), tr("Unable to open the file.")); myCurrentDir = ""; return; } + QApplication::setOverrideCursor(Qt::WaitCursor); + SessionPtr aSession = ModelAPI_Session::get(); aSession->closeAll(); aSession->load(myCurrentDir.toLatin1().constData()); myObjectBrowser->rebuildDataTree(); updateCommandStatus(); +#ifndef HAVE_SALOME + myMainWindow->setCurrentDir(myCurrentDir, true); +#endif QApplication::restoreOverrideCursor(); } @@ -748,6 +819,14 @@ void XGUI_Workshop::onPreferences() } #endif +//****************************************************** +void XGUI_Workshop::onTrihedronVisibilityChanged(bool theState) +{ + XGUI_Displayer* aDisplayer = displayer(); + if (aDisplayer) + aDisplayer->displayTrihedron(theState); +} + //****************************************************** bool XGUI_Workshop::onSave() { @@ -890,6 +969,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())); @@ -940,7 +1046,7 @@ ModuleBase_IModule* XGUI_Workshop::loadModule(const QString& theModule) if (!err.isEmpty()) { if (desktop()) { - Events_Error::send(err.toStdString()); + Events_InfoMessage("XGUI_Workshop", err.toStdString()).send(); } else { qWarning(qPrintable(err)); } @@ -963,6 +1069,9 @@ bool XGUI_Workshop::createModule() // myModule, SLOT(onBeforeObjectErase(ObjectPtr, AISObjectPtr))); myModule->createFeatures(); +#ifdef HAVE_SALOME + salomeConnector()->createFeatureActions(); +#endif //myActionsMgr->update(); return true; } @@ -1026,6 +1135,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); @@ -1057,13 +1167,14 @@ void XGUI_Workshop::createDockWidgets() QAction* aCancelAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Abort); connect(aCancelAct, SIGNAL(triggered()), myOperationMgr, SLOT(onAbortOperation())); - connect(myPropertyPanel, SIGNAL(keyReleased(QKeyEvent*)), - myOperationMgr, SLOT(onKeyReleased(QKeyEvent*))); - connect(myPropertyPanel, SIGNAL(enterClicked()), - myOperationMgr, SLOT(onProcessEnter())); - //connect(myOperationMgr, SIGNAL(validationStateChanged(bool)), - // this, SLOT(onValidationStateChanged(bool))); + 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(QObject*)), + myOperationMgr, SLOT(onProcessEnter(QObject*))); } //****************************************************** @@ -1079,8 +1190,8 @@ void XGUI_Workshop::showPropertyPanel() // in order to operation manager could process key events of the panel. // otherwise they are ignored. It happens only if the same(activateWindow) is // not happened by property panel activation(e.g. resume operation of Sketch) - myPropertyPanel->activateWindow(); - myPropertyPanel->setFocus(); + ModuleBase_Tools::activateWindow(myPropertyPanel, "XGUI_Workshop::showPropertyPanel()"); + ModuleBase_Tools::setFocus(myPropertyPanel, "XGUI_Workshop::showPropertyPanel()"); } //****************************************************** @@ -1097,22 +1208,24 @@ 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(); - aDesktop->activateWindow(); - aDesktop->setFocus(); + ModuleBase_Tools::activateWindow(aDesktop, "XGUI_Workshop::hidePropertyPanel()"); + ModuleBase_Tools::setFocus(aDesktop, "XGUI_Workshop::showPropertyPanel()"); } //****************************************************** void XGUI_Workshop::showObjectBrowser() { - myObjectBrowser->parentWidget()->show(); + if (!isSalomeMode()) + myObjectBrowser->parentWidget()->show(); } //****************************************************** void XGUI_Workshop::hideObjectBrowser() { - myObjectBrowser->parentWidget()->hide(); + if (!isSalomeMode()) + myObjectBrowser->parentWidget()->hide(); } //****************************************************** @@ -1133,16 +1246,24 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked) QObjectPtrList aObjects = mySelector->selection()->selectedObjects(); if (theId == "DELETE_CMD") deleteObjects(); + else if (theId == "CLEAN_HISTORY_CMD") + cleanHistory(); else if (theId == "MOVE_CMD") moveObjects(); else if (theId == "COLOR_CMD") changeColor(aObjects); - else if (theId == "SHOW_CMD") + else if (theId == "DEFLECTION_CMD") + changeDeflection(aObjects); + else if (theId == "SHOW_CMD") { showObjects(aObjects, true); + mySelector->updateSelectionBy(ModuleBase_ISelection::Browser); + } else if (theId == "HIDE_CMD") showObjects(aObjects, false); - else if (theId == "SHOW_ONLY_CMD") + else if (theId == "SHOW_ONLY_CMD") { showOnlyObjects(aObjects); + mySelector->updateSelectionBy(ModuleBase_ISelection::Browser); + } else if (theId == "SHADING_CMD") setDisplayMode(aObjects, XGUI_Displayer::Shading); else if (theId == "WIREFRAME_CMD") @@ -1154,14 +1275,53 @@ 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); + //IMP: an attempt to use result selection with other selection modes + setViewerSelectionMode(ModuleBase_ResultPrs::Sel_Result); + setViewerSelectionMode(TopAbs_COMPSOLID); + } else if (theId == "SHOW_RESULTS_CMD") { + highlightResults(aObjects); + } else if (theId == "SHOW_FEATURE_CMD") { + highlightFeature(aObjects); + } +} + +//************************************************************** +void XGUI_Workshop::setViewerSelectionMode(int theMode) +{ + if (theMode == -1) + myViewerSelMode.clear(); + else { + if (myViewerSelMode.contains(theMode)) + myViewerSelMode.removeAll(theMode); + else + myViewerSelMode.append(theMode); } + activateObjectsSelection(myDisplayer->displayedObjects()); +} + +//************************************************************** +void XGUI_Workshop::activateObjectsSelection(const QObjectPtrList& theList) +{ + QIntList aModes; + module()->activeSelectionModes(aModes); + if (aModes.isEmpty() && (myViewerSelMode.length() > 0)) + aModes.append(myViewerSelMode); + myDisplayer->activateObjects(aModes, theList); } //************************************************************** void XGUI_Workshop::deleteObjects() { ModuleBase_IModule* aModule = module(); - // 1. allow the module to delete objects, do nothing if it has succeed + // allow the module to delete objects, do nothing if it has succeed if (aModule->deleteObjects()) { updateCommandStatus(); return; @@ -1170,221 +1330,231 @@ 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; 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 += tr(" %1"); - QStringList aObjectNames; - foreach (ObjectPtr aObj, anObjects) { - if (!aObj->data()->isValid()) - continue; - aObjectNames << QString::fromStdString(aObj->data()->name()); - } - aDescription = aDescription.arg(aObjectNames.join(", ")); + // delete objects + std::map > aReferences; + std::set aFeatures; + ModuleBase_Tools::convertToFeatures(anObjects, aFeatures); + ModelAPI_Tools::findAllReferences(aFeatures, aReferences); + + bool aDone = false; + QString aDescription = contextMenuMgr()->action("DELETE_CMD")->text() + " %1"; + 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(); + + std::set aFeatureRefsToDelete; + if (ModuleBase_Tools::askToDelete(aFeatures, aReferences, desktop(), aFeatureRefsToDelete)) { + // 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(); + + if (!aFeatureRefsToDelete.empty()) + aFeatures.insert(aFeatureRefsToDelete.begin(), aFeatureRefsToDelete.end()); + aDone = ModelAPI_Tools::removeFeatures(aFeatures, false); } - else { + if (aDone) + operationMgr()->commitOperation(); + else operationMgr()->abortOperation(operationMgr()->currentOperation()); +} + +//************************************************************** +void addRefsToFeature(const FeaturePtr& theFeature, + const std::map >& theMainList, + std::set& theReferences) +{ + //if (theReferences.find(theFeature) != theReferences.end()) + // return; + if (theMainList.find(theFeature) == theMainList.end()) + return; // this feature is not in the selection list, so exists without references to it + std::set aMainReferences = theMainList.at(theFeature); + + std::set::const_iterator anIt = aMainReferences.begin(), + aLast = aMainReferences.end(); + for (; anIt != aLast; anIt++) { + FeaturePtr aRefFeature = *anIt; + if (theReferences.find(aRefFeature) == theReferences.end()) + theReferences.insert(aRefFeature); + addRefsToFeature(aRefFeature, theMainList, theReferences); } } //************************************************************** -void XGUI_Workshop::moveObjects() +void XGUI_Workshop::cleanHistory() { if (!abortAllOperations()) return; - SessionPtr aMgr = ModelAPI_Session::get(); - - QString anActionId = "MOVE_CMD"; - QString aDescription = contextMenuMgr()->action(anActionId)->text(); - aMgr->startOperation(aDescription.toStdString()); - QObjectPtrList anObjects = mySelector->selection()->selectedObjects(); - // It is necessary to clear selection in order to avoid selection changed event during - // moving and negative consequences connected with processing of already moved items - mySelector->clearSelection(); - // check whether the object can be moved. There should not be parts which are not loaded - if (!XGUI_Tools::canRemoveOrRename(desktop(), anObjects)) - return; - - DocumentPtr anActiveDocument = aMgr->activeDocument(); - FeaturePtr aCurrentFeature = anActiveDocument->currentFeature(true); - foreach (ObjectPtr aObject, anObjects) { - if (!myModule->canApplyAction(aObject, anActionId)) - continue; + std::set aFeatures; + ModuleBase_Tools::convertToFeatures(anObjects, aFeatures); + +#ifdef DEBUG_CLEAN_HISTORY + QStringList anInfo; + std::set::const_iterator aFIt; + for (aFIt = aFeatures.begin(); aFIt != aFeatures.end(); ++aFIt) { + FeaturePtr aFeature = ModelAPI_Feature::feature(*aFIt); + anInfo.append(aFeature->name().c_str()); + } + QString anInfoStr = anInfo.join(";\t"); + qDebug(QString("cleanHistory for: [%1] - %2").arg(aFeatures.size()).arg(anInfoStr).toStdString().c_str()); +#endif - FeaturePtr aFeature = std::dynamic_pointer_cast(aObject); - if (aFeature.get()) { - anActiveDocument->moveFeature(aFeature, aCurrentFeature); - aCurrentFeature = anActiveDocument->currentFeature(true); + std::map > aReferences; + ModelAPI_Tools::findAllReferences(aFeatures, aReferences, true, false); + // find for each object whether all reference values are in the map as key, that means that there is + // no other reference in the model to this object, so it might be removed by cleaning history + // sk_1(ext_1, vertex_1) + (sk_3, bool_1) - cann't be deleted, dependency to bool_1 + // ext_1(bool_1, sk_3) - cann't be deleted, dependency to bool_1 + // vertex_1() + // sk_2(ext_2) + (bool_1) - cann't be deleted, dependency to bool_1 + // ext_2(bool_1) - cann't be deleted, dependency to bool_1 + // sk_3() + // Information: bool_1 is not selected + std::set anUnusedObjects; + std::map >::const_iterator aMainIt = aReferences.begin(), + aMainLast = aReferences.end(); + for (; aMainIt != aMainLast; aMainIt++) { + FeaturePtr aMainListFeature = aMainIt->first; + std::set aMainRefList = aMainIt->second; + std::set::const_iterator aRefIt = aMainRefList.begin(), aRefLast = aMainRefList.end(); + bool aFeatureOutOfTheList = false; + for (; aRefIt != aRefLast && !aFeatureOutOfTheList; aRefIt++) { + FeaturePtr aRefFeature = *aRefIt; + aFeatureOutOfTheList = aReferences.find(aRefFeature) == aReferences.end(); } + if (!aFeatureOutOfTheList) + anUnusedObjects.insert(aMainListFeature); } - aMgr->finishOperation(); -} -//************************************************************** -bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList, - const std::set& theIgnoredFeatures, - QWidget* theParent, - const bool theAskAboutDeleteReferences) -{ -#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()); +#ifdef DEBUG_CLEAN_HISTORY + anInfo.clear(); + for (aFIt = anUnusedObjects.begin(); aFIt != anUnusedObjects.end(); ++aFIt) { + FeaturePtr aFeature = *aFIt; + anInfo.append(aFeature->name().c_str()); + } + qDebug(QString("unused objects: [%1] - %2").arg(anInfo.size()).arg(anInfo.join(";\t")).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, 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; - } + // warn about the references remove, break the delete operation if the user chose it + if (!anUnusedObjects.empty()) { + QStringList aNames; + foreach (const FeaturePtr& aFeature, anUnusedObjects) { + aNames.append(aFeature->name().c_str()); } + aNames.sort(); + QString anUnusedNames = aNames.join(", "); - QMessageBox aMessageBox(theParent); - aMessageBox.setWindowTitle(tr("Delete features")); + 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; - 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)); - } + QString aText = QString(tr("Unused features are the following: %1.\nThese features will be deleted.\nWould you like to continue?") + .arg(anUnusedNames)); aMessageBox.setText(aText); - aMessageBox.exec(); - QMessageBox::ButtonRole aButtonRole = aMessageBox.buttonRole(aMessageBox.clickedButton()); + if (aMessageBox.exec() == QMessageBox::No) + return; - if (aButtonRole == QMessageBox::NoRole) - return false; + // 1. start operation + aDescription += "by deleting of " + 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(); - if (aButtonRole == QMessageBox::ActionRole) { - foreach (ObjectPtr aObj, theList) - ModelAPI_ReplaceParameterMessage::send(aObj, this); - doDeleteReferences = false; + std::set anIgnoredFeatures; + if (ModelAPI_Tools::removeFeatures(anUnusedObjects, true)) { + operationMgr()->commitOperation(); + } + else { + operationMgr()->abortOperation(operationMgr()->currentOperation()); } } + else { + QString anActionId = "CLEAN_HISTORY_CMD"; + QString aDescription = contextMenuMgr()->action(anActionId)->text(); - // 3. remove referenced features - if (doDeleteReferences) { - std::set aFeaturesToDelete = aDirectRefFeatures; - aFeaturesToDelete.insert(aIndirectRefFeatures.begin(), aIndirectRefFeatures.end()); - std::set::const_iterator anIt = aFeaturesToDelete.begin(), - aLast = aFeaturesToDelete.end(); -#ifdef DEBUG_DELETE - QStringList anInfo; -#endif - for (; anIt != aLast; anIt++) { - FeaturePtr aFeature = (*anIt); - DocumentPtr aDoc = aFeature->document(); - if (theIgnoredFeatures.find(aFeature) == theIgnoredFeatures.end()) { - aDoc->removeFeature(aFeature); -#ifdef DEBUG_DELETE - anInfo.append(ModuleBase_Tools::objectInfo(aFeature).toStdString().c_str()); -#endif - } - } -#ifdef DEBUG_DELETE - qDebug(QString("remove references:%1").arg(anInfo.join("; ")).toStdString().c_str()); - anInfo.clear(); -#endif + 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; } +} - QString anActionId = "DELETE_CMD"; - QString anId = QString::fromStdString(anActionId.toStdString().c_str()); - QStringList anObjectGroups = contextMenuMgr()->actionObjectGroups(anId); - // 4. remove the parameter features - foreach (ObjectPtr aObj, theList) { - // features and parameters can be removed here, - // the results are removed only by a corresponded feature remove - std::string aGroupName = aObj->groupName(); - if (!anObjectGroups.contains(aGroupName.c_str())) - continue; +//************************************************************** +void XGUI_Workshop::moveObjects() +{ + if (!abortAllOperations()) + return; + + SessionPtr aMgr = ModelAPI_Session::get(); + + QString anActionId = "MOVE_CMD"; + QString aDescription = contextMenuMgr()->action(anActionId)->text(); + aMgr->startOperation(aDescription.toStdString()); - if (!myModule->canApplyAction(aObj, anActionId)) + QObjectPtrList anObjects = mySelector->selection()->selectedObjects(); + // It is necessary to clear selection in order to avoid selection changed event during + // moving and negative consequences connected with processing of already moved items + mySelector->clearSelection(); + // check whether the object can be moved. There should not be parts which are not loaded + std::set aFeatures; + ModuleBase_Tools::convertToFeatures(anObjects, aFeatures); + if (!XGUI_Tools::canRemoveOrRename(desktop(), aFeatures)) + return; + + DocumentPtr anActiveDocument = aMgr->activeDocument(); + FeaturePtr aCurrentFeature = anActiveDocument->currentFeature(true); + std::set::const_iterator anIt = aFeatures.begin(), aLast = aFeatures.end(); + for (; anIt != aLast; anIt++) { + FeaturePtr aFeature = *anIt; + if (!aFeature.get() || !myModule->canApplyAction(aFeature, anActionId)) continue; - FeaturePtr aFeature = ModelAPI_Feature::feature(aObj); - if (aFeature) { - /*// TODO: to learn the workshop to delegate the Part object deletion to the PartSet module - // part features are removed in the PartSet module. This condition should be moved there - if (aFeature->getKind() == "Part") - continue; - */ - DocumentPtr aDoc = aObj->document(); - if (theIgnoredFeatures.find(aFeature) == theIgnoredFeatures.end()) { -#ifdef DEBUG_DELETE - QString anInfoStr = ModuleBase_Tools::objectInfo(aFeature); - anInfo.append(anInfoStr); - qDebug(QString("remove feature :%1").arg(anInfoStr).toStdString().c_str()); -#endif - aDoc->removeFeature(aFeature); - } - } + anActiveDocument->moveFeature(aFeature, aCurrentFeature); + aCurrentFeature = anActiveDocument->currentFeature(true); } -#ifdef DEBUG_DELETE - qDebug(QString("remove features:%1").arg(anInfo.join("; ")).toStdString().c_str()); -#endif - return true; + aMgr->finishOperation(); +} + +//************************************************************** +bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theObjects) +{ + std::map > aReferences; + std::set aFeatures; + ModuleBase_Tools::convertToFeatures(theObjects, aFeatures); + + return ModelAPI_Tools::removeFeaturesAndReferences(aFeatures); } bool hasResults(QObjectPtrList theObjects, const std::set& theTypes) @@ -1414,7 +1584,9 @@ std::list allFeatures(const DocumentPtr& theDocument) // The order of appending features of the part and the part itself is important // Append features from a part feature - foreach (const ResultPtr& aResult, aFeature->results()) { + std::list aResults; + ModelAPI_Tools::allResults(aFeature, aResults); + foreach (const ResultPtr& aResult, aResults) { ResultPartPtr aResultPart = std::dynamic_pointer_cast(aResult); if (aResultPart.get() && aResultPart->partDoc().get()) { @@ -1486,7 +1658,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; @@ -1615,6 +1787,92 @@ void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects) updateCommandStatus(); } +//************************************************************** +bool XGUI_Workshop::canChangeDeflection() const +{ + QObjectPtrList aObjects = mySelector->selection()->selectedObjects(); + + std::set aTypes; + 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 setDeflection(ResultPtr theResult, const double theDeflection) +{ + if (!theResult.get()) + return; + + AttributeDoublePtr aDeflectionAttr = theResult->data()->real(ModelAPI_Result::DEFLECTION_ID()); + if (aDeflectionAttr.get() != NULL) + aDeflectionAttr->setValue(theDeflection); +} + + +//************************************************************** +void XGUI_Workshop::changeDeflection(const QObjectPtrList& theObjects) +{ + AttributeDoublePtr aDoubleAttr; + // 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 + double aDeflection = -1; + foreach(ObjectPtr anObject, theObjects) { + ResultPtr aResult = std::dynamic_pointer_cast(anObject); + if (aResult.get()) { + aDeflection = XGUI_CustomPrs::getResultDeflection(aResult); + } + else { + // TODO: remove the obtaining a color from the AIS object + // this does not happen never because: + // 1. The color can be changed only on results + // 2. The result can be not visualized in the viewer(e.g. Origin Construction) + AISObjectPtr anAISObj = myDisplayer->getAISObject(anObject); + if (anAISObj.get()) { + aDeflection = anAISObj->getDeflection(); + } + } + if (aDeflection > 0) + break; + } + if (aDeflection < 0) + return; + + if (!abortAllOperations()) + return; + // 2. show the dialog to change the value + XGUI_DeflectionDialog* aDlg = new XGUI_DeflectionDialog(desktop()); + aDlg->setDeflection(aDeflection); + aDlg->move(QCursor::pos()); + bool isDone = aDlg->exec() == QDialog::Accepted; + if (!isDone) + return; + + // 3. abort the previous operation and start a new one + SessionPtr aMgr = ModelAPI_Session::get(); + QString aDescription = contextMenuMgr()->action("DEFLECTION_CMD")->text(); + aMgr->startOperation(aDescription.toStdString()); + + // 4. set the value to all results + aDeflection = aDlg->getDeflection(); + foreach(ObjectPtr anObj, theObjects) { + ResultPtr aResult = std::dynamic_pointer_cast(anObj); + if (aResult.get() != NULL) { + ResultCompSolidPtr aCompsolidResult = std::dynamic_pointer_cast(aResult); + if (aCompsolidResult.get() != NULL) { // change colors for all sub-solids + for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) { + setDeflection(aCompsolidResult->subResult(i), aDeflection); + } + } + setDeflection(aResult, aDeflection); + } + } + aMgr->finishOperation(); + updateCommandStatus(); +} + //************************************************************** #define SET_DISPLAY_GROUP(aGroupName, aDisplay) \ for (int i = 0; i < aDoc->size(aGroupName); i++) { \ @@ -1769,6 +2027,15 @@ QList XGUI_Workshop::processHistoryList(const std::list return aResult; } +void XGUI_Workshop::setStatusBarMessage(const QString& theMessage) +{ +#ifdef HAVE_SALOME + salomeConnector()->putInfo(theMessage, -1); +#else + myMainWindow->putInfo(theMessage, -1); +#endif +} + void XGUI_Workshop::synchronizeViewer() { SessionPtr aMgr = ModelAPI_Session::get(); @@ -1788,9 +2055,66 @@ 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; + bool aHasHidden = false; + foreach(ObjectPtr aObj, theObjects) { + aFeature = std::dynamic_pointer_cast(aObj); + if (aFeature.get()) { + std::list aResults; + ModelAPI_Tools::allResults(aFeature, aResults); + std::list >::const_iterator aIt; + for(aIt = aResList.cbegin(); aIt != aResList.cend(); aIt++) { + aHasHidden |= (*aIt)->isConcealed(); + aSelList.append(*aIt); + } + } + } + if (aSelList.count() > theObjects.count()) { + // if something was found + bool aBlocked = objectBrowser()->blockSignals(true); + objectBrowser()->setObjectsSelected(aSelList); + objectBrowser()->blockSignals(aBlocked); + } + if (aHasHidden) + QMessageBox::information(desktop(), tr("Find results"), + tr("Results not found"), QMessageBox::Ok); +} + +void XGUI_Workshop::highlightFeature(const QObjectPtrList& theObjects) +{ + ResultPtr aResult; + QObjectPtrList aSelList = theObjects; + FeaturePtr aFeature; + foreach(ObjectPtr aObj, theObjects) { + aResult = std::dynamic_pointer_cast(aObj); + if (aResult.get()) { + aFeature = ModelAPI_Feature::feature(aResult); + if (aFeature.get()) { + aSelList.append(aFeature); + } + } + } + if (aSelList.count() > theObjects.count()) { + // if something was found + bool aBlocked = objectBrowser()->blockSignals(true); + objectBrowser()->setObjectsSelected(aSelList); + objectBrowser()->blockSignals(aBlocked); + } +}