X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FXGUI%2FXGUI_Workshop.cpp;h=b4a48cd09d43ee5aa3d0b594f50e891b25acabbd;hb=0f9e6aed4b7f5b75eb13b39709dac59986fd3684;hp=facd2e4286158d34e5188b90cf52cc7e5b396f46;hpb=f0f8fbdcadad2d5d42c443e70afc6251faea1469;p=modules%2Fshaper.git diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp old mode 100644 new mode 100755 index facd2e428..b4a48cd09 --- 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" @@ -23,6 +24,7 @@ #include #include +#ifndef HAVE_SALOME #include #include #include @@ -30,6 +32,7 @@ #include #include #include +#endif #include #include @@ -63,6 +66,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -77,6 +84,7 @@ #include #include #include +#include #include #include #include @@ -100,7 +108,11 @@ #include #endif + +QString XGUI_Workshop::MOVE_TO_END_COMMAND = QObject::tr("Move to the end"); + //#define DEBUG_DELETE +//#define DEBUG_FEATURE_NAME XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) : QObject(), @@ -109,28 +121,29 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) mySalomeConnector(theConnector), myPropertyPanel(0), myObjectBrowser(0), - myDisplayer(0) + myDisplayer(0), + myViewerSelMode(TopAbs_FACE) { - myMainWindow = mySalomeConnector ? 0 : new AppElements_MainWindow(); - - if (myMainWindow) { - SUIT_ResourceMgr* aResMgr = ModuleBase_Preferences::resourceMgr(); - bool aCloc = aResMgr->booleanValue("language", "locale", true); - if (aCloc) - QLocale::setDefault( QLocale::c() ); - else - QLocale::setDefault( QLocale::system() ); - } +#ifndef HAVE_SALOME + myMainWindow = new AppElements_MainWindow(); + + SUIT_ResourceMgr* aResMgr = ModuleBase_Preferences::resourceMgr(); + bool aCloc = aResMgr->booleanValue("language", "locale", true); + if (aCloc) + QLocale::setDefault( QLocale::c() ); + else + QLocale::setDefault( QLocale::system() ); +#endif myDisplayer = new XGUI_Displayer(this); mySelector = new XGUI_SelectionMgr(this); - //connect(mySelector, SIGNAL(selectionChanged()), this, SLOT(updateModuleCommands())); + 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()); - myErrorMgr = new XGUI_ErrorMgr(this); myContextMenuMgr = new XGUI_ContextMenuMgr(this); connect(myContextMenuMgr, SIGNAL(actionTriggered(const QString&, bool)), this, SLOT(onContextMenuCommand(const QString&, bool))); @@ -144,6 +157,7 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) ModuleBase_IWorkshop* aWorkshop = moduleConnector(); myOperationMgr->setWorkshop(aWorkshop); + myErrorMgr = new XGUI_ErrorMgr(this, aWorkshop); myEventsListener = new XGUI_WorkshopListener(aWorkshop); connect(myOperationMgr, SIGNAL(operationStarted(ModuleBase_Operation*)), @@ -156,11 +170,12 @@ 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())); - if (myMainWindow) - connect(myMainWindow, SIGNAL(exitKeySequence()), SLOT(onExit())); +#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&))); @@ -176,6 +191,9 @@ 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); } //****************************************************** @@ -201,13 +219,18 @@ void XGUI_Workshop::startApplication() // by Config_PropManger to restore user-defined path to plugins ModuleBase_Preferences::loadCustomProps(); createModule(); - if (myMainWindow) { - myMainWindow->show(); - updateCommandStatus(); - } + +#ifndef HAVE_SALOME + myMainWindow->show(); + updateCommandStatus(); +#endif onNew(); + myViewerProxy->connectViewProxy(); + connect(myViewerProxy, SIGNAL(trihedronVisibilityChanged(bool)), + SLOT(onTrihedronVisibilityChanged(bool))); + emit applicationStarted(); } @@ -220,18 +243,32 @@ void XGUI_Workshop::activateModule() connect(myDisplayer, SIGNAL(beforeObjectErase(ObjectPtr, AISObjectPtr)), myModule, SLOT(onBeforeObjectErase(ObjectPtr, AISObjectPtr))); - myActionsMgr->update(); + updateCommandStatus(); + + // TODO: get default selection mode + // activate visualized objects in the viewer + activateObjectsSelection(displayer()->displayedObjects()); + myOperationMgr->activate(); } void XGUI_Workshop::deactivateModule() { myModule->deactivateSelectionFilters(); + // remove internal displayer filter + displayer()->deactivateSelectionFilters(); + disconnect(myDisplayer, SIGNAL(objectDisplayed(ObjectPtr, AISObjectPtr)), myModule, SLOT(onObjectDisplayed(ObjectPtr, AISObjectPtr))); disconnect(myDisplayer, SIGNAL(beforeObjectErase(ObjectPtr, AISObjectPtr)), myModule, SLOT(onBeforeObjectErase(ObjectPtr, AISObjectPtr))); + + XGUI_Displayer* aDisplayer = displayer(); + QObjectPtrList aDisplayed = aDisplayer->displayedObjects(); + aDisplayer->deactivateObjects(aDisplayed, true); + + myOperationMgr->deactivate(); } //****************************************************** @@ -239,48 +276,47 @@ void XGUI_Workshop::initMenu() { myContextMenuMgr->createActions(); - if (isSalomeMode()) { - // Create only Undo, Redo commands - QAction* aAction = salomeConnector()->addDesktopCommand("UNDO_CMD", tr("Undo"), - tr("Undo last command"), - QIcon(":pictures/undo.png"), - QKeySequence::Undo, false, "MEN_DESK_EDIT"); - QString aToolBarTitle = tr( "INF_DESK_TOOLBAR_STANDARD" ); - salomeConnector()->addActionInToolbar( aAction,aToolBarTitle ); - - connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onUndo())); - addHistoryMenu(aAction, SIGNAL(updateUndoHistory(const QList&)), SLOT(onUndo(int))); - - aAction = salomeConnector()->addDesktopCommand("REDO_CMD", tr("Redo"), tr("Redo last command"), - QIcon(":pictures/redo.png"), QKeySequence::Redo, - false, "MEN_DESK_EDIT"); - salomeConnector()->addActionInToolbar( aAction, aToolBarTitle ); - - connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onRedo())); - addHistoryMenu(aAction, SIGNAL(updateRedoHistory(const QList&)), SLOT(onRedo(int))); - - salomeConnector()->addDesktopMenuSeparator("MEN_DESK_EDIT"); - aAction = salomeConnector()->addDesktopCommand("REBUILD_CMD", tr("Rebuild"), tr("Rebuild data objects"), - QIcon(":pictures/rebuild.png"), QKeySequence(), - false, "MEN_DESK_EDIT"); - salomeConnector()->addActionInToolbar( aAction, aToolBarTitle ); - - 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"), - 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"), - QIcon(), QKeySequence(), - false, "MEN_DESK_FILE"); - connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onOpen())); - salomeConnector()->addDesktopMenuSeparator("MEN_DESK_FILE"); +#ifdef HAVE_SALOME + // Create only Undo, Redo commands + QAction* aAction = salomeConnector()->addDesktopCommand("UNDO_CMD", tr("Undo"), + tr("Undo last command"), + QIcon(":pictures/undo.png"), + QKeySequence::Undo, false, "MEN_DESK_EDIT"); + QString aToolBarTitle = tr( "INF_DESK_TOOLBAR_STANDARD" ); + salomeConnector()->addActionInToolbar( aAction,aToolBarTitle ); + + connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onUndo())); + addHistoryMenu(aAction, SIGNAL(updateUndoHistory(const QList&)), SLOT(onUndo(int))); + + aAction = salomeConnector()->addDesktopCommand("REDO_CMD", tr("Redo"), tr("Redo last command"), + QIcon(":pictures/redo.png"), QKeySequence::Redo, + false, "MEN_DESK_EDIT"); + salomeConnector()->addActionInToolbar( aAction, aToolBarTitle ); + + connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onRedo())); + addHistoryMenu(aAction, SIGNAL(updateRedoHistory(const QList&)), SLOT(onRedo(int))); + + salomeConnector()->addDesktopMenuSeparator("MEN_DESK_EDIT"); + //aAction = salomeConnector()->addDesktopCommand("REBUILD_CMD", tr("Rebuild"), tr("Rebuild data objects"), + // QIcon(":pictures/rebuild.png"), QKeySequence(), + // false, "MEN_DESK_EDIT"); + //salomeConnector()->addActionInToolbar( aAction, aToolBarTitle ); + + //connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onRebuild())); + //salomeConnector()->addDesktopMenuSeparator("MEN_DESK_EDIT"); + + 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 native..."), tr("Import native file"), + QIcon(), QKeySequence(), + false, "MEN_DESK_FILE"); + connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onOpen())); + salomeConnector()->addDesktopMenuSeparator("MEN_DESK_FILE"); - return; - } +#else // File commands group AppElements_MenuGroupPanel* aGroup = myMainWindow->menuObject()->generalPage(); @@ -291,6 +327,10 @@ void XGUI_Workshop::initMenu() aCommand->connectTo(this, SLOT(onSave())); //aCommand->disable(); + aCommand = aGroup->addFeature("SAVEAS_CMD", tr("Save as..."), tr("Save the document into a file"), + QIcon(":pictures/save.png"), QKeySequence()); + aCommand->connectTo(this, SLOT(onSaveAs())); + QString aUndoId = "UNDO_CMD"; aCommand = aGroup->addFeature(aUndoId, tr("Undo"), tr("Undo last command"), QIcon(":pictures/undo.png"), QKeySequence::Undo); @@ -309,23 +349,16 @@ void XGUI_Workshop::initMenu() SIGNAL(updateRedoHistory(const QList&)), SLOT(onRedo(int))); - aCommand = aGroup->addFeature("REBUILD_CMD", tr("Rebuild"), tr("Rebuild data objects"), - QIcon(":pictures/rebuild.png"), QKeySequence()); - aCommand->connectTo(this, SLOT(onRebuild())); + //aCommand = aGroup->addFeature("REBUILD_CMD", tr("Rebuild"), tr("Rebuild data objects"), + // QIcon(":pictures/rebuild.png"), QKeySequence()); + //aCommand->connectTo(this, SLOT(onRebuild())); - aCommand = aGroup->addFeature("SAVEAS_CMD", tr("Save as..."), tr("Save the document into a file"), - QIcon(":pictures/save.png"), QKeySequence()); - aCommand->connectTo(this, SLOT(onSaveAs())); //aCommand->disable(); aCommand = aGroup->addFeature("OPEN_CMD", tr("Open..."), tr("Open a new document"), QIcon(":pictures/open.png"), QKeySequence::Open); aCommand->connectTo(this, SLOT(onOpen())); - //aCommand = aGroup->addFeature("NEW_CMD", tr("New"), tr("Create a new document"), - // QIcon(":pictures/new.png"), QKeySequence::New); - //aCommand->connectTo(this, SLOT(onNew())); - aCommand = aGroup->addFeature("PREF_CMD", tr("Preferences"), tr("Edit preferences"), QIcon(":pictures/preferences.png"), QKeySequence::Preferences); aCommand->connectTo(this, SLOT(onPreferences())); @@ -333,25 +366,25 @@ void XGUI_Workshop::initMenu() aCommand = aGroup->addFeature("EXIT_CMD", tr("Exit"), tr("Exit application"), QIcon(":pictures/close.png"), QKeySequence::Close); aCommand->connectTo(this, SLOT(onExit())); - //FIXME: SBH's test action. Can be used for some GUI tests. -// #ifdef _DEBUG -// aCommand = aGroup->addFeature("TEST_CMD", "Test!", "Private debug button", -// QIcon(":pictures/close.png"), QKeySequence(), true); -// aCommand->connectTo(myMainWindow, SLOT(dockPythonConsole())); -// #endif +#endif } -//****************************************************** +#ifndef HAVE_SALOME AppElements_Workbench* XGUI_Workshop::addWorkbench(const QString& theName) { AppElements_MainMenu* aMenuBar = myMainWindow->menuObject(); return aMenuBar->addWorkbench(theName); } +#endif //****************************************************** QMainWindow* XGUI_Workshop::desktop() const { - return isSalomeMode() ? salomeConnector()->desktop() : myMainWindow; +#ifdef HAVE_SALOME + return salomeConnector()->desktop(); +#else + return myMainWindow; +#endif } //****************************************************** @@ -362,74 +395,182 @@ void XGUI_Workshop::onStartWaiting() } } +//****************************************************** +void XGUI_Workshop::onAcceptActionClicked() +{ + QAction* anAction = dynamic_cast(sender()); + XGUI_OperationMgr* anOperationMgr = operationMgr(); + if (anOperationMgr) { + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (anOperationMgr->currentOperation()); + if (aFOperation) { + //if (errorMgr()->canProcessClick(anAction, aFOperation->feature())) + myOperationMgr->onCommitOperation(); + } + } +} + +//****************************************************** +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) { if (!myModule->canActivateSelection(theObject)) { - if (myDisplayer->isActive(theObject)) - myDisplayer->deactivate(theObject, theUpdateViewer); + if (myDisplayer->isActive(theObject)) { + QObjectPtrList anObjects; + anObjects.append(theObject); + myDisplayer->deactivateObjects(anObjects, theUpdateViewer); + } } } //****************************************************** -void XGUI_Workshop::onOperationStarted(ModuleBase_Operation* theOperation) +bool XGUI_Workshop::isFeatureOfNested(const FeaturePtr& theFeature) { - setNestedFeatures(theOperation); + bool aHasNested = false; + std::string aFeatureKind = theFeature->getKind(); +#ifdef HAVE_SALOME + XGUI_SalomeConnector* aSalomeConnector = salomeConnector(); + if (aSalomeConnector->isFeatureOfNested(actionsMgr()->action(aFeatureKind.c_str()))) + aHasNested = true; +#else + AppElements_MainMenu* aMenuBar = mainWindow()->menuObject(); + AppElements_Command* aCommand = aMenuBar->feature(aFeatureKind.c_str()); + if (aCommand && aCommand->button()->additionalButtonWidget()) + aHasNested = true; +#endif + return aHasNested; +} - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (theOperation); +void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* 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 commited 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(); + foreach (ModuleBase_ModelWidget* aWidget, aWidgets) { + bool isStoreValue = !aFOperation->isEditOperation() && + !aWidget->getDefaultValue().empty() && + !aWidget->isComputedDefault(); + aWidget->setFeature(aFeature, isStoreValue); + aWidget->enableFocusProcessing(); + } - myModule->onOperationStarted(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())); + } + else { + disconnect(aWidget, SIGNAL(valueStateChanged(int)), this, SLOT(onWidgetStateChanged(int))); + disconnect(aWidget, SIGNAL(valuesChanged()), this, SLOT(onValuesChanged())); + } + } + } +} + +//****************************************************** +void XGUI_Workshop::onOperationStarted(ModuleBase_Operation* theOperation) +{ + setGrantedFeatures(theOperation); + myModule->operationStarted(theOperation); } //****************************************************** void XGUI_Workshop::onOperationResumed(ModuleBase_Operation* theOperation) { - setNestedFeatures(theOperation); + setGrantedFeatures(theOperation); if (theOperation->getDescription()->hasXmlRepresentation()) { //!< No need for property panel setPropertyPanel(theOperation); + connectToPropertyPanel(true); } updateCommandStatus(); - myModule->onOperationResumed(theOperation); + myModule->operationResumed(theOperation); } //****************************************************** void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation) { + updateCommandStatus(); + ModuleBase_OperationFeature* aFOperation = dynamic_cast (theOperation); if (!aFOperation) @@ -438,87 +579,67 @@ void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation) ModuleBase_ISelection* aSel = mySelector->selection(); QObjectPtrList aObj = aSel->selectedPresentations(); //!< No need for property panel - updateCommandStatus(); hidePropertyPanel(); myPropertyPanel->cleanContent(); - myModule->onOperationStopped(aFOperation); + connectToPropertyPanel(false); + myModule->operationStopped(aFOperation); // the deactivated objects of the current operation should be activated back. // They were deactivated on operation start or an object redisplay QObjectPtrList anObjects; FeaturePtr aFeature = aFOperation->feature(); - if (myDisplayer->isVisible(aFeature) && !myDisplayer->isActive(aFeature)) - anObjects.append(aFeature); - std::list aResults = aFeature->results(); - std::list::const_iterator aIt; - for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { - ResultPtr anObject = *aIt; - if (myDisplayer->isVisible(anObject) && !myDisplayer->isActive(anObject)) { - anObjects.append(anObject); + 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::const_iterator aIt; + for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { + ResultPtr anObject = *aIt; + if (myDisplayer->isVisible(anObject) && !myDisplayer->isActive(anObject)) { + anObjects.append(anObject); + } } } - QIntList aModes; - module()->activeSelectionModes(aModes); - myDisplayer->activateObjects(aModes, anObjects); + activateObjectsSelection(anObjects); } void XGUI_Workshop::onOperationCommitted(ModuleBase_Operation* theOperation) { - myModule->onOperationCommitted(theOperation); + myModule->operationCommitted(theOperation); } void XGUI_Workshop::onOperationAborted(ModuleBase_Operation* theOperation) { - myModule->onOperationAborted(theOperation); -} - -void XGUI_Workshop::setNestedFeatures(ModuleBase_Operation* theOperation) -{ - ModuleBase_OperationFeature* aFOperation = dynamic_cast(theOperation); - if (!aFOperation) - return; - - if (isSalomeMode()) - aFOperation->setGrantedOperationIds(mySalomeConnector->nestedActions(theOperation->id())); - else - aFOperation->setGrantedOperationIds(myActionsMgr->nestedCommands(theOperation->id())); + myModule->operationAborted(theOperation); } -void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* theOperation) +void XGUI_Workshop::setGrantedFeatures(ModuleBase_Operation* theOperation) { ModuleBase_OperationFeature* aFOperation = dynamic_cast(theOperation); if (!aFOperation) return; - showPropertyPanel(); - QString aXmlRepr = aFOperation->getDescription()->xmlRepresentation(); - ModuleBase_WidgetFactory aFactory = ModuleBase_WidgetFactory(aXmlRepr.toStdString(), - myModuleConnector); - - myPropertyPanel->cleanContent(); - aFactory.createWidget(myPropertyPanel->contentWidget()); - - QList aWidgets = aFactory.getModelWidgets(); - foreach (ModuleBase_ModelWidget* aWidget, aWidgets) { - bool isStoreValue = !aFOperation->isEditOperation() && - !aWidget->getDefaultValue().empty() && - !aWidget->isComputedDefault(); - aWidget->setFeature(aFOperation->feature(), isStoreValue); - aWidget->enableFocusProcessing(); + QStringList aGrantedIds; + if (isSalomeMode()) { + const std::shared_ptr& anInfo = + mySalomeConnector->featureInfo(theOperation->id()); + if (anInfo.get()) + aGrantedIds = QString::fromStdString(anInfo->nestedFeatures()) + .split(" ", QString::SkipEmptyParts); } - - myPropertyPanel->setModelWidgets(aWidgets); - aFOperation->setPropertyPanel(myPropertyPanel); - - myModule->propertyPanelDefined(theOperation); + else + aGrantedIds = myActionsMgr->nestedCommands(theOperation->id()); - myPropertyPanel->setWindowTitle(theOperation->getDescription()->description()); + ModuleBase_IModule* aModule = module(); + if (aModule) + aModule->grantedOperationIds(theOperation, aGrantedIds); - myErrorMgr->setPropertyPanel(myPropertyPanel); + aFOperation->setGrantedOperationIds(aGrantedIds); } + /* * Saves document with given name. */ @@ -530,29 +651,48 @@ void XGUI_Workshop::saveDocument(const QString& theName, std::list& QApplication::restoreOverrideCursor(); } -bool XGUI_Workshop::isActiveOperationAborted() +bool XGUI_Workshop::abortAllOperations() { return myOperationMgr->abortAllOperations(); } //****************************************************** -void XGUI_Workshop::onExit() +void XGUI_Workshop::onOpen() { - SessionPtr aMgr = ModelAPI_Session::get(); - if (aMgr->isModified()) { + if(!abortAllOperations()) + return; + //save current file before close if modified + SessionPtr aSession = ModelAPI_Session::get(); + if (aSession->isModified()) { + //TODO(sbh): re-launch the app? int anAnswer = QMessageBox::question( - myMainWindow, tr("Save current file"), tr("The document is modified, save before exit?"), + desktop(), tr("Save current file"), + tr("The document is modified, save before opening another?"), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel); if (anAnswer == QMessageBox::Save) { - bool saved = onSave(); - if (!saved) { - return; - } + onSave(); } else if (anAnswer == QMessageBox::Cancel) { return; } + myCurrentDir = ""; } - qApp->exit(); + + //show file dialog, check if readable and open + myCurrentDir = QFileDialog::getExistingDirectory(desktop(), tr("Select directory")); + 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); + aSession->closeAll(); + aSession->load(myCurrentDir.toLatin1().constData()); + myObjectBrowser->rebuildDataTree(); + updateCommandStatus(); + QApplication::restoreOverrideCursor(); } //****************************************************** @@ -565,60 +705,70 @@ void XGUI_Workshop::onNew() } myViewerProxy->connectToViewer(); showObjectBrowser(); - if (!isSalomeMode()) { - myMainWindow->showPythonConsole(); - QMdiSubWindow* aWnd = myMainWindow->viewer()->createView(); - aWnd->showMaximized(); - updateCommandStatus(); - } +#ifndef HAVE_SALOME + myMainWindow->showPythonConsole(); + QMdiSubWindow* aWnd = myMainWindow->viewer()->createView(); + aWnd->showMaximized(); + updateCommandStatus(); +#endif myContextMenuMgr->connectViewer(); QApplication::restoreOverrideCursor(); } +#ifndef HAVE_SALOME //****************************************************** -void XGUI_Workshop::onOpen() +void XGUI_Workshop::onExit() { - if(!isActiveOperationAborted()) - return; - //save current file before close if modified - SessionPtr aSession = ModelAPI_Session::get(); - if (aSession->isModified()) { - //TODO(sbh): re-launch the app? + SessionPtr aMgr = ModelAPI_Session::get(); + if (aMgr->isModified()) { int anAnswer = QMessageBox::question( - myMainWindow, tr("Save current file"), - tr("The document is modified, save before opening another?"), + myMainWindow, tr("Save current file"), tr("The document is modified, save before exit?"), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel); if (anAnswer == QMessageBox::Save) { - onSave(); + bool saved = onSave(); + if (!saved) { + return; + } } else if (anAnswer == QMessageBox::Cancel) { return; } - myCurrentDir = ""; } + qApp->exit(); +} - //show file dialog, check if readable and open - myCurrentDir = QFileDialog::getExistingDirectory(mainWindow(), tr("Select directory")); - if (myCurrentDir.isEmpty()) - return; - QFileInfo aFileInfo(myCurrentDir); - if (!aFileInfo.exists() || !aFileInfo.isReadable()) { - QMessageBox::critical(myMainWindow, tr("Warning"), tr("Unable to open the file.")); - myCurrentDir = ""; - return; +//****************************************************** +void XGUI_Workshop::onPreferences() +{ + ModuleBase_Prefs aModif; + ModuleBase_Preferences::editPreferences(aModif); + if (aModif.size() > 0) { + QString aSection; + foreach (ModuleBase_Pref aPref, aModif) + { + aSection = aPref.first; + if (aSection == ModuleBase_Preferences::VIEWER_SECTION) { + myMainWindow->viewer()->updateFromResources(); + } else if (aSection == ModuleBase_Preferences::MENU_SECTION) { + myMainWindow->menuObject()->updateFromResources(); + } + } + displayer()->redisplayObjects(); } - QApplication::setOverrideCursor(Qt::WaitCursor); - aSession->closeAll(); - aSession->load(myCurrentDir.toLatin1().constData()); - myObjectBrowser->rebuildDataTree(); - //displayAllResults(); - updateCommandStatus(); - QApplication::restoreOverrideCursor(); +} +#endif + +//****************************************************** +void XGUI_Workshop::onTrihedronVisibilityChanged(bool theState) +{ + XGUI_Displayer* aDisplayer = displayer(); + if (aDisplayer) + aDisplayer->displayTrihedron(theState); } //****************************************************** bool XGUI_Workshop::onSave() { - if(!isActiveOperationAborted()) + if(!abortAllOperations()) return false; if (myCurrentDir.isEmpty()) { return onSaveAs(); @@ -626,17 +776,18 @@ bool XGUI_Workshop::onSave() std::list aFiles; saveDocument(myCurrentDir, aFiles); updateCommandStatus(); - if (!isSalomeMode()) +#ifndef HAVE_SALOME myMainWindow->setModifiedState(false); +#endif return true; } //****************************************************** bool XGUI_Workshop::onSaveAs() { - if(!isActiveOperationAborted()) + if(!abortAllOperations()) return false; - QFileDialog dialog(mainWindow()); + QFileDialog dialog(desktop()); dialog.setWindowTitle(tr("Select directory to save files...")); dialog.setFileMode(QFileDialog::Directory); dialog.setFilter(tr("Directories (*)")); @@ -651,7 +802,7 @@ bool XGUI_Workshop::onSaveAs() QDir aDir(aTempDir); if (aDir.exists() && !aDir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).isEmpty()) { int answer = QMessageBox::question( - myMainWindow, + desktop(), //: Title of the dialog which asks user if he wants to save study in existing non-empty folder tr("Save"), tr("The directory already contains some files, save anyway?"), @@ -661,10 +812,10 @@ bool XGUI_Workshop::onSaveAs() } } myCurrentDir = aTempDir; - if (!isSalomeMode()) { +#ifndef HAVE_SALOME myMainWindow->setCurrentDir(myCurrentDir, false); myMainWindow->setModifiedState(false); - } +#endif return onSave(); } @@ -673,14 +824,18 @@ void XGUI_Workshop::onUndo(int theTimes) { objectBrowser()->treeView()->setCurrentIndex(QModelIndex()); SessionPtr aMgr = ModelAPI_Session::get(); + std::list aUndoList = aMgr->undoList(); if (aMgr->isOperation()) { - /// this is important for nested operrations - /// when sketch opeation is active, this condition is false and + /// this is important for nested operations + /// when sketch operation is active, this condition is false and /// the sketch operation is not aborted operationMgr()->onAbortOperation(); } - for (int i = 0; i < theTimes; ++i) { + std::list::const_iterator aIt = aUndoList.cbegin(); + for (int i = 0; (i < theTimes) && (aIt != aUndoList.cend()); ++i, ++aIt) { aMgr->undo(); + if (QString((*aIt).c_str()) == MOVE_TO_END_COMMAND) + myObjectBrowser->rebuildDataTree(); } operationMgr()->updateApplyOfOperations(); @@ -698,14 +853,18 @@ void XGUI_Workshop::onRedo(int theTimes) objectBrowser()->treeView()->setCurrentIndex(QModelIndex()); SessionPtr aMgr = ModelAPI_Session::get(); + std::list aRedoList = aMgr->redoList(); if (aMgr->isOperation()) { - /// this is important for nested operrations - /// when sketch opeation is active, this condition is false and + /// this is important for nested operations + /// when sketch operation is active, this condition is false and /// the sketch operation is not aborted operationMgr()->onAbortOperation(); } - for (int i = 0; i < theTimes; ++i) { + std::list::const_iterator aIt = aRedoList.cbegin(); + for (int i = 0; (i < theTimes) && (aIt != aRedoList.cend()); ++i, ++aIt) { aMgr->redo(); + if (QString((*aIt).c_str()) == MOVE_TO_END_COMMAND) + myObjectBrowser->rebuildDataTree(); } operationMgr()->updateApplyOfOperations(); updateCommandStatus(); @@ -716,44 +875,60 @@ void XGUI_Workshop::onRedo(int theTimes) } //****************************************************** -void XGUI_Workshop::onRebuild() +//void XGUI_Workshop::onRebuild() +//{ +// SessionPtr aMgr = ModelAPI_Session::get(); +// bool aWasOperation = aMgr->isOperation(); // keep this value +// if (!aWasOperation) { +// aMgr->startOperation("Rebuild"); +// } +// static const Events_ID aRebuildEvent = Events_Loop::loop()->eventByName("Rebuild"); +// Events_Loop::loop()->send(std::shared_ptr( +// new Events_Message(aRebuildEvent, this))); +// if (!aWasOperation) { +// aMgr->finishOperation(); +// } +// updateCommandStatus(); +//} + +//****************************************************** +void XGUI_Workshop::onWidgetStateChanged(int thePreviousState) { - SessionPtr aMgr = ModelAPI_Session::get(); - bool aWasOperation = aMgr->isOperation(); // keep this value - if (!aWasOperation) { - aMgr->startOperation("Rebuild"); + ModuleBase_ModelWidget* anActiveWidget = 0; + ModuleBase_Operation* anOperation = myOperationMgr->currentOperation(); + if (anOperation) { + ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel(); + if (aPanel) + anActiveWidget = aPanel->activeWidget(); } - static const Events_ID aRebuildEvent = Events_Loop::loop()->eventByName("Rebuild"); - Events_Loop::loop()->send(std::shared_ptr( - new Events_Message(aRebuildEvent, this))); - if (!aWasOperation) { - aMgr->finishOperation(); - } - updateCommandStatus(); + if (anActiveWidget) + operationMgr()->onValidateOperation(); + + myModule->widgetStateChanged(thePreviousState); } //****************************************************** -void XGUI_Workshop::onPreferences() +void XGUI_Workshop::onValuesChanged() { - ModuleBase_Prefs aModif; - ModuleBase_Preferences::editPreferences(aModif); - if (aModif.size() > 0) { - QString aSection; - foreach (ModuleBase_Pref aPref, aModif) - { - aSection = aPref.first; - if (aSection == ModuleBase_Preferences::VIEWER_SECTION) { - if (!isSalomeMode()) - myMainWindow->viewer()->updateFromResources(); - } else if (aSection == ModuleBase_Preferences::MENU_SECTION) { - if (!isSalomeMode()) - myMainWindow->menuObject()->updateFromResources(); - } - } + 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(); } } -//****************************************************** ModuleBase_IModule* XGUI_Workshop::loadModule(const QString& theModule) { QString libName = QString::fromStdString(library(theModule.toStdString())); @@ -803,7 +978,7 @@ ModuleBase_IModule* XGUI_Workshop::loadModule(const QString& theModule) ModuleBase_IModule* aModule = crtInst ? crtInst(myModuleConnector) : 0; if (!err.isEmpty()) { - if (mainWindow()) { + if (desktop()) { Events_Error::send(err.toStdString()); } else { qWarning(qPrintable(err)); @@ -827,6 +1002,7 @@ bool XGUI_Workshop::createModule() // myModule, SLOT(onBeforeObjectErase(ObjectPtr, AISObjectPtr))); myModule->createFeatures(); + salomeConnector()->createFeatureActions(); //myActionsMgr->update(); return true; } @@ -835,13 +1011,13 @@ bool XGUI_Workshop::createModule() void XGUI_Workshop::updateCommandStatus() { QList aCommands; - if (isSalomeMode()) { // update commands in SALOME mode +#ifdef HAVE_SALOME aCommands = salomeConnector()->commandList(); - } else { +#else AppElements_MainMenu* aMenuBar = myMainWindow->menuObject(); foreach (AppElements_Command* aCmd, aMenuBar->features()) aCommands.append(aCmd); - } +#endif SessionPtr aMgr = ModelAPI_Session::get(); if (aMgr->hasModuleDocument()) { foreach(QAction* aCmd, aCommands) { @@ -866,7 +1042,7 @@ void XGUI_Workshop::updateCommandStatus() aCmd->setEnabled(false); } } - myActionsMgr->update(); + myActionsMgr->updateCommandsStatus(); emit commandStatusUpdated(); } @@ -890,9 +1066,6 @@ QDockWidget* XGUI_Workshop::createObjectBrowser(QWidget* theParent) aObjDock->setStyleSheet( "::title { position: relative; padding-left: 5px; text-align: left center }"); myObjectBrowser = new XGUI_ObjectsBrowser(aObjDock); -#ifdef ModuleDataModel - myObjectBrowser->setDataModel(myModule->dataModel()); -#endif myModule->customizeObjectBrowser(myObjectBrowser); aObjDock->setWidget(myObjectBrowser); @@ -907,10 +1080,10 @@ QDockWidget* XGUI_Workshop::createObjectBrowser(QWidget* theParent) */ void XGUI_Workshop::createDockWidgets() { - QMainWindow* aDesktop = isSalomeMode() ? salomeConnector()->desktop() : myMainWindow; + QMainWindow* aDesktop = desktop(); QDockWidget* aObjDock = createObjectBrowser(aDesktop); aDesktop->addDockWidget(Qt::LeftDockWidgetArea, aObjDock); - myPropertyPanel = new XGUI_PropertyPanel(aDesktop); + myPropertyPanel = new XGUI_PropertyPanel(aDesktop, myOperationMgr); myPropertyPanel->setupActions(myActionsMgr); myPropertyPanel->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); aDesktop->addDockWidget(Qt::LeftDockWidgetArea, myPropertyPanel); @@ -920,14 +1093,18 @@ void XGUI_Workshop::createDockWidgets() myPropertyPanel->installEventFilter(myOperationMgr); QAction* aOkAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Accept); - connect(aOkAct, SIGNAL(triggered()), myOperationMgr, SLOT(onCommitOperation())); + connect(aOkAct, SIGNAL(triggered()), this, SLOT(onAcceptActionClicked())); + QAction* aCancelAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Abort); connect(aCancelAct, SIGNAL(triggered()), myOperationMgr, SLOT(onAbortOperation())); - connect(myPropertyPanel, SIGNAL(noMoreWidgets()), myModule, SLOT(onNoMoreWidgets())); - connect(myPropertyPanel, SIGNAL(keyReleased(QKeyEvent*)), - myOperationMgr, SLOT(onKeyReleased(QKeyEvent*))); - connect(myOperationMgr, SIGNAL(validationStateChanged(bool)), - aOkAct, SLOT(setEnabled(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*))); } //****************************************************** @@ -938,6 +1115,13 @@ void XGUI_Workshop::showPropertyPanel() aViewAct->setEnabled(true); myPropertyPanel->show(); myPropertyPanel->raise(); + + // The next code is necessary to made the property panel the active window + // 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) + ModuleBase_Tools::activateWindow(myPropertyPanel, "XGUI_Workshop::showPropertyPanel()"); + ModuleBase_Tools::setFocus(myPropertyPanel, "XGUI_Workshop::showPropertyPanel()"); } //****************************************************** @@ -947,18 +1131,31 @@ void XGUI_Workshop::hidePropertyPanel() ///setEnabled(false); myPropertyPanel->hide(); + + // the property panel is active window of the desktop, when it is + // hidden, it is undefined which window becomes active. By this reason + // it is defined to perform the desktop as the active window. + // 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 SHAPER package + QMainWindow* aDesktop = desktop(); + 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(); } //****************************************************** @@ -979,28 +1176,64 @@ 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 == "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") setDisplayMode(aObjects, XGUI_Displayer::Wireframe); else if (theId == "HIDEALL_CMD") { QObjectPtrList aList = myDisplayer->displayedObjects(); - foreach (ObjectPtr aObj, aList) - aObj->setDisplayed(false); + foreach (ObjectPtr aObj, aList) { + if (module()->canEraseObject(aObj)) + 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() { @@ -1011,67 +1244,169 @@ void XGUI_Workshop::deleteObjects() return; } - if (!isActiveOperationAborted()) - return; QObjectPtrList anObjects = mySelector->selection()->selectedObjects(); - // It is necessary to clear selection in order to avoid selection changed event during - // deleteion and negative consequences connected with processing of already deleted items - mySelector->clearSelection(); + if (!abortAllOperations()) + return; // check whether the object can be deleted. There should not be parts which are not loaded - if (!XGUI_Tools::canRemoveOrRename(myMainWindow, anObjects)) + 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()); + // 3. delete objects + std::set anIgnoredFeatures; + std::set aDirectRefFeatures, aIndirectRefFeatures; + findReferences(anObjects, aDirectRefFeatures, aIndirectRefFeatures); + + bool doDeleteReferences = true; + if (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()); } - aDescription = aDescription.arg(aObjectNames.join(", ")); +} - SessionPtr aMgr = ModelAPI_Session::get(); - aMgr->startOperation(aDescription.toStdString()); - // 2. close the documents of the removed parts if the result part is in a list of selected objects - // this is performed in the RemoveFeature of Part object. - /*foreach (ObjectPtr aObj, anObjects) - { - ResultPartPtr aPart = std::dynamic_pointer_cast(aObj); - if (aPart) { - DocumentPtr aDoc = aObj->document(); - if (aDoc == aMgr->activeDocument()) { - aDoc->close(); - } +//************************************************************** +void XGUI_Workshop::cleanHistory() +{ + if (!abortAllOperations()) + return; + + QObjectPtrList anObjects = mySelector->selection()->selectedObjects(); + 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, aFeatures, + aDirectRefFeatures, alreadyProcessed); + if (aDirectRefFeatures.empty() && !anUnusedObjects.contains(aFeature)) + anUnusedObjects.append(aFeature); + } + } + + // 2. warn about the references remove, break the delete operation if the user chose it + if (!anUnusedObjects.empty()) { + QStringList aNames; + foreach (const ObjectPtr& anObject, anUnusedObjects) { + FeaturePtr aFeature = std::dynamic_pointer_cast(anObject); + aNames.append(aFeature->name().c_str()); + } + QString anUnusedNames = aNames.join(", "); + + 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 = 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; + + // 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(); + + std::set anIgnoredFeatures; + if (removeFeatures(anUnusedObjects, anIgnoredFeatures, anActionId)) { + operationMgr()->commitOperation(); + } + else { + operationMgr()->abortOperation(operationMgr()->currentOperation()); } - }*/ - // 3. delete objects - QMainWindow* aDesktop = isSalomeMode() ? salomeConnector()->desktop() : myMainWindow; - std::set anIgnoredFeatures; - if (deleteFeatures(anObjects, anIgnoredFeatures, aDesktop, true)) { - myDisplayer->updateViewer(); - aMgr->finishOperation(); - operationMgr()->updateApplyOfOperations(); - updateCommandStatus(); } else { - aMgr->abortOperation(); + 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; } } //************************************************************** void XGUI_Workshop::moveObjects() { - if (!isActiveOperationAborted()) + if (!abortAllOperations()) return; SessionPtr aMgr = ModelAPI_Session::get(); @@ -1081,8 +1416,14 @@ void XGUI_Workshop::moveObjects() aMgr->startOperation(aDescription.toStdString()); QObjectPtrList anObjects = mySelector->selection()->selectedObjects(); - DocumentPtr anActiveDocument = aMgr->activeDocument(); + // 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)) @@ -1098,78 +1439,156 @@ void XGUI_Workshop::moveObjects() } //************************************************************** -bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList, - const std::set& theIgnoredFeatures, - QWidget* theParent, - const bool theAskAboutDeleteReferences) +void XGUI_Workshop::findReferences(const QObjectPtrList& theList, + std::set& aDirectRefFeatures, + std::set& aIndirectRefFeatures) { -#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) { - XGUI_Tools::refsToFeatureInAllDocuments(aDeletedObj, aDeletedObj, aDirectRefFeatures, aIndirectRefFeatures); + 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; } - // 2. warn about the references remove, break the delete operation if the user chose it - if (theAskAboutDeleteReferences && !aDirectRefFeatures.empty()) { +} + +bool XGUI_Workshop::isDeleteFeatureWithReferences(const QObjectPtrList& theList, + const std::set& aDirectRefFeatures, + const std::set& aIndirectRefFeatures, + QWidget* theParent, + bool& doDeleteReferences) +{ + doDeleteReferences = true; + + QString aDirectNames, aIndirectNames; + if (!aDirectRefFeatures.empty()) { QStringList aDirectRefNames; - foreach(const FeaturePtr& aFeature, aDirectRefFeatures) + foreach (const FeaturePtr& aFeature, aDirectRefFeatures) aDirectRefNames.append(aFeature->name().c_str()); - QString aDirectNames = aDirectRefNames.join(", "); + aDirectNames = aDirectRefNames.join(", "); QStringList aIndirectRefNames; - foreach(const FeaturePtr& aFeature, aIndirectRefFeatures) + foreach (const FeaturePtr& aFeature, aIndirectRefFeatures) aIndirectRefNames.append(aFeature->name().c_str()); - QString aIndirectNames = aIndirectRefNames.join(", "); - - QMessageBox::StandardButton aRes = QMessageBox::warning( - theParent, tr("Delete features"), - QString(tr("Selected features are used in the following features: %1.\ - These features will be deleted.\n%2Would you like to continue?")).arg(aDirectNames) - .arg(aIndirectNames.isEmpty() ? QString() : QString("Also these features will be deleted: %1.\n").arg(aIndirectNames)), - QMessageBox::No | QMessageBox::Yes, QMessageBox::No); - if (aRes != QMessageBox::Yes) + aIndirectNames = aIndirectRefNames.join(", "); + } + + bool aCanReplaceParameters = !aDirectRefFeatures.empty(); + QStringList aPartFeatureNames; + foreach (ObjectPtr aObj, theList) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aObj); + // invalid feature data means that the feature is already removed in model, + // we needn't process it. E.g. delete of feature from create operation. The operation abort + // will delete the operation + if (!aFeature->data()->isValid()) + continue; + ResultPtr aFirstResult = aFeature->firstResult(); + if (!aFirstResult.get()) + continue; + std::string aResultGroupName = aFirstResult->groupName(); + if (aResultGroupName == ModelAPI_ResultPart::group()) + aPartFeatureNames.append(aFeature->name().c_str()); + + if (aCanReplaceParameters && aResultGroupName != ModelAPI_ResultParameter::group()) + aCanReplaceParameters = false; + } + QString aPartNames = aPartFeatureNames.join(", "); + + 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 (!aDirectNames.isEmpty() || !aIndirectNames.isEmpty()) { + if (aCanReplaceParameters) { + aText = QString(tr("Selected parameters are used in the following features: %1.\nThese features will be deleted.\nOr parameters could be replaced by their values.\n") + .arg(aDirectNames)); + if (!aIndirectNames.isEmpty()) + aText += 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")).arg(aDirectNames); + if (!aIndirectNames.isEmpty()) + aText += QString(tr("(Also these features will be deleted: %1)\n")).arg(aIndirectNames); + } + } + if (!aPartNames.isEmpty()) + aText += QString(tr("The following parts will be deleted: %1.\n")).arg(aPartNames); + + if (!aText.isEmpty()) { + aText += "Would you like to continue?"; + 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; + } } + return true; +} - // 3. remove referenced features - std::set aFeaturesToDelete = aDirectRefFeatures; - aFeaturesToDelete.insert(aIndirectRefFeatures.begin(), aIndirectRefFeatures.end()); - std::set::const_iterator anIt = aFeaturesToDelete.begin(), - aLast = aFeaturesToDelete.end(); +bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theFeatures, + const std::set& theIgnoredFeatures) +{ + std::set aDirectRefFeatures, aIndirectRefFeatures; + findReferences(theFeatures, aDirectRefFeatures, aIndirectRefFeatures); + return deleteFeaturesInternal(theFeatures, aDirectRefFeatures, aIndirectRefFeatures, + theIgnoredFeatures); +} + +bool XGUI_Workshop::deleteFeaturesInternal(const QObjectPtrList& theList, + const std::set& aDirectRefFeatures, + const std::set& aIndirectRefFeatures, + const std::set& theIgnoredFeatures, + const bool doDeleteReferences) +{ + 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; + QStringList anInfo; #endif - for (; anIt != aLast; anIt++) { - FeaturePtr aFeature = (*anIt); - DocumentPtr aDoc = aFeature->document(); - if (theIgnoredFeatures.find(aFeature) == theIgnoredFeatures.end()) { - aDoc->removeFeature(aFeature); + 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()); + 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(); + qDebug(QString("remove references:%1").arg(anInfo.join("; ")).toStdString().c_str()); + anInfo.clear(); #endif + } QString anActionId = "DELETE_CMD"; - QString anId = QString::fromStdString(anActionId.toStdString().c_str()); + return removeFeatures(theList, theIgnoredFeatures, anActionId); +} + +//************************************************************** +bool XGUI_Workshop::removeFeatures(const QObjectPtrList& theList, + const std::set& theIgnoredFeatures, + const QString& theActionId) +{ + bool isDone = false; + + QString anId = QString::fromStdString(theActionId.toStdString().c_str()); QStringList anObjectGroups = contextMenuMgr()->actionObjectGroups(anId); // 4. remove the parameter features foreach (ObjectPtr aObj, theList) { @@ -1179,9 +1598,6 @@ bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList, if (!anObjectGroups.contains(aGroupName.c_str())) continue; - if (!myModule->canApplyAction(aObj, 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 @@ -1197,6 +1613,7 @@ bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList, qDebug(QString("remove feature :%1").arg(anInfoStr).toStdString().c_str()); #endif aDoc->removeFeature(aFeature); + isDone = true; } } } @@ -1222,6 +1639,32 @@ bool hasResults(QObjectPtrList theObjects, const std::set& theTypes return isFoundResultType; } +//************************************************************** +// Returns the list of all features for theDocument and all features of +// all nested parts. +std::list allFeatures(const DocumentPtr& theDocument) +{ + std::list aResultList; + std::list anAllFeatures = theDocument->allFeatures(); + foreach (const FeaturePtr& aFeature, anAllFeatures) { + // 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()) { + ResultPartPtr aResultPart = + std::dynamic_pointer_cast(aResult); + if (aResultPart.get() && aResultPart->partDoc().get()) { + // Recursion + std::list anAllFeatures = allFeatures(aResultPart->partDoc()); + aResultList.insert(aResultList.end(), anAllFeatures.begin(), anAllFeatures.end()); + } + } + + aResultList.push_back(aFeature); + } + return aResultList; +} + //************************************************************** // Returns the list of features placed between theObject and the current feature // in the same document. Excludes theObject, includes the current feature. @@ -1229,14 +1672,14 @@ std::list toCurrentFeatures(const ObjectPtr& theObject) { std::list aResult; DocumentPtr aDocument = theObject->document(); - std::list anAllFeatures = aDocument->allFeatures(); + std::list anAllFeatures = allFeatures(aDocument); // find the object iterator std::list::iterator aObjectIt = std::find(anAllFeatures.begin(), anAllFeatures.end(), theObject); - if (aObjectIt == anAllFeatures.end()) + if (aObjectIt == anAllFeatures.end()) return aResult; // find the current feature iterator std::list::iterator aCurrentIt = std::find(anAllFeatures.begin(), anAllFeatures.end(), aDocument->currentFeature(true)); - if (aCurrentIt == anAllFeatures.end()) + if (aCurrentIt == anAllFeatures.end()) return aResult; // check the right order if (std::distance(aObjectIt, anAllFeatures.end()) <= std::distance(aCurrentIt, anAllFeatures.end())) @@ -1255,8 +1698,12 @@ bool XGUI_Workshop::canMoveFeature() QObjectPtrList aObjects = mySelector->selection()->selectedObjects(); QObjectPtrList aValidatedObjects; foreach (ObjectPtr aObject, aObjects) { - if (myModule->canApplyAction(aObject, anActionId)) - aValidatedObjects.append(aObject); + if (!myModule->canApplyAction(aObject, anActionId)) + continue; + // To be moved feature should be in active document + if (aObject->document() != ModelAPI_Session::get()->activeDocument()) + continue; + aValidatedObjects.append(aObject); } if (aValidatedObjects.size() != aObjects.size()) aObjects = aValidatedObjects; @@ -1285,7 +1732,7 @@ bool XGUI_Workshop::canMoveFeature() std::set_intersection(aRefFeatures.begin(), aRefFeatures.end(), aPlacedFeatures.begin(), aPlacedFeatures.end(), std::inserter(aIntersectionFeatures, aIntersectionFeatures.begin())); - // 4. Return false if any reference feature is placed before curent feature + // 4. Return false if any reference feature is placed before current feature if (!aIntersectionFeatures.empty()) aCanMove = false; } @@ -1323,7 +1770,7 @@ bool XGUI_Workshop::canChangeColor() const return hasResults(aObjects, aTypes); } -void setColor(ResultPtr theResult, std::vector& theColor) +void setColor(ResultPtr theResult, const std::vector& theColor) { if (!theResult.get()) return; @@ -1342,6 +1789,7 @@ void setColor(ResultPtr theResult, std::vector& theColor) //************************************************************** void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects) { + AttributeIntArrayPtr aColorAttr; // 1. find the current color of the object. This is a color of AIS presentation // The objects are iterated until a first valid color is found @@ -1368,8 +1816,10 @@ void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects) if (aColor.size() != 3) return; + if (!abortAllOperations()) + return; // 2. show the dialog to change the value - XGUI_ColorDialog* aDlg = new XGUI_ColorDialog(mainWindow()); + XGUI_ColorDialog* aDlg = new XGUI_ColorDialog(desktop()); aDlg->setColor(aColor); aDlg->move(QCursor::pos()); bool isDone = aDlg->exec() == QDialog::Accepted; @@ -1380,11 +1830,8 @@ void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects) // 3. abort the previous operation and start a new one SessionPtr aMgr = ModelAPI_Session::get(); - bool aWasOperation = aMgr->isOperation(); // keep this value - if (!aWasOperation) { - QString aDescription = contextMenuMgr()->action("COLOR_CMD")->text(); - aMgr->startOperation(aDescription.toStdString()); - } + QString aDescription = contextMenuMgr()->action("COLOR_CMD")->text(); + aMgr->startOperation(aDescription.toStdString()); // 4. set the value to all results std::vector aColorResult = aDlg->getColor(); @@ -1393,14 +1840,14 @@ void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects) 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++) - setColor(aCompsolidResult->subResult(i), aColorResult); + for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) { + setColor(aCompsolidResult->subResult(i), !isRandomColor ? aColorResult : aDlg->getRandomColor()); + } } - setColor(aResult, aColorResult); + setColor(aResult, !isRandomColor ? aColorResult : aDlg->getRandomColor()); } } - if (!aWasOperation) - aMgr->finishOperation(); + aMgr->finishOperation(); updateCommandStatus(); } @@ -1432,8 +1879,10 @@ void XGUI_Workshop::showOnlyObjects(const QObjectPtrList& theList) { // Hide all displayed objects QObjectPtrList aList = myDisplayer->displayedObjects(); - foreach (ObjectPtr aObj, aList) - aObj->setDisplayed(false); + foreach (ObjectPtr aObj, aList) { + if (module()->canEraseObject(aObj)) + aObj->setDisplayed(false); + } // Show only objects from the list foreach (ObjectPtr aObj, theList) { @@ -1461,20 +1910,6 @@ void XGUI_Workshop::registerValidators() const ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); } -//************************************************************** -/*void XGUI_Workshop::displayAllResults() -{ - SessionPtr aMgr = ModelAPI_Session::get(); - DocumentPtr aRootDoc = aMgr->moduleDocument(); - displayDocumentResults(aRootDoc); - for (int i = 0; i < aRootDoc->size(ModelAPI_ResultPart::group()); i++) { - ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), i); - ResultPartPtr aPart = std::dynamic_pointer_cast(aObject); - displayDocumentResults(aPart->partDoc()); - } - myDisplayer->updateViewer(); -}*/ - //************************************************************** void XGUI_Workshop::displayDocumentResults(DocumentPtr theDoc) { @@ -1523,6 +1958,8 @@ void XGUI_Workshop::closeDocument() myDisplayer->eraseAll(); objectBrowser()->clearContent(); + module()->closeDocument(); + SessionPtr aMgr = ModelAPI_Session::get(); aMgr->closeAll(); } @@ -1567,3 +2004,58 @@ QList XGUI_Workshop::processHistoryList(const std::list } return aResult; } + +void XGUI_Workshop::synchronizeViewer() +{ + SessionPtr aMgr = ModelAPI_Session::get(); + DocumentPtr aDoc = aMgr->activeDocument(); + + synchronizeGroupInViewer(aDoc, ModelAPI_ResultConstruction::group(), false); + synchronizeGroupInViewer(aDoc, ModelAPI_ResultBody::group(), false); + synchronizeGroupInViewer(aDoc, ModelAPI_ResultPart::group(), false); + synchronizeGroupInViewer(aDoc, ModelAPI_ResultGroup::group(), false); +} + +void XGUI_Workshop::synchronizeGroupInViewer(const DocumentPtr& theDoc, + const std::string& theGroup, + bool theUpdateViewer) +{ + ObjectPtr aObj; + int aSize = theDoc->size(theGroup); + for (int i = 0; i < aSize; i++) { + aObj = theDoc->object(theGroup, i); + 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); + } +}