X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FXGUI%2FXGUI_Workshop.cpp;h=0a1b1570ca901a64d408103893edbf3050ec8f3b;hb=e65bf14e2ff3cf853884bf8998fadcece6e3b34c;hp=e7d8483fb5cdea7ed291aed4a822665b1deaba3f;hpb=6ffc65a82f0a74e7b844f8dd81a287f16ca1f28c;p=modules%2Fshaper.git diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index e7d8483fb..0a1b1570c 100755 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -1,20 +1,47 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> +// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or +// email : webmaster.salome@opencascade.com +// -//#include "XGUI_Constants.h" #include "XGUI_Workshop.h" #include "XGUI_ActionsMgr.h" +#include "XGUI_ActiveControlMgr.h" +#include "XGUI_ActiveControlSelector.h" +#include "XGUI_MenuMgr.h" #include "XGUI_ColorDialog.h" +#include "XGUI_DeflectionDialog.h" +#include "XGUI_TransparencyWidget.h" #include "XGUI_ContextMenuMgr.h" #include "XGUI_Displayer.h" #include "XGUI_ErrorDialog.h" #include "XGUI_ErrorMgr.h" +#include "XGUI_FacesPanel.h" +#include "XGUI_FacesPanelSelector.h" #include "XGUI_ModuleConnector.h" #include "XGUI_ObjectsBrowser.h" #include "XGUI_OperationMgr.h" #include "XGUI_PropertyPanel.h" +#include "XGUI_PropertyPanelSelector.h" +#include "XGUI_PropertyDialog.h" #include "XGUI_SalomeConnector.h" #include "XGUI_Selection.h" +#include "XGUI_SelectionActivate.h" #include "XGUI_SelectionMgr.h" #include "XGUI_Tools.h" #include "XGUI_ViewerProxy.h" @@ -22,6 +49,8 @@ #include #include #include +#include +#include #ifndef HAVE_SALOME #include @@ -33,28 +62,31 @@ #include #endif +#include + #include #include +#include #include #include #include #include #include +#include #include #include #include +#include #include #include -#include #include //#include #include -#include +#include #include -#include #include #include #include @@ -68,16 +100,28 @@ #include #include #include +#include +#include +#include #include #include #include #include #include -#include +#include +#include +#include +#include #include +#include +#ifdef BEFORE_TRIHEDRON_PATCH +#include +#include +#endif + #include #include #include @@ -95,6 +139,16 @@ #include +#ifdef TINSPECTOR +#include +#include +#include +#include +static TInspector_Communicator* MyTCommunicator; +static Handle(VInspector_CallBack) MyVCallBack; + +#endif + #ifdef _DEBUG #include #include @@ -106,66 +160,95 @@ #include #endif +//#define DEBUG_WITH_MESSAGE_REPORT 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(), myCurrentDir(QString()), myModule(NULL), mySalomeConnector(theConnector), myPropertyPanel(0), + myInspectionPanel(0), + myFacesPanel(0), myObjectBrowser(0), - myDisplayer(0), - myViewerSelMode(TopAbs_FACE) + 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); + mySelectionActivate = new XGUI_SelectionActivate(aWorkshop); + + SUIT_ResourceMgr* aResMgr = ModuleBase_Preferences::resourceMgr(); #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 + else QLocale::setDefault( QLocale::system() ); #endif + QString aPath = Config_XMLReader::pluginConfigFile().c_str(); + QDir aDir(aPath); + + // Load translations + QStringList aLangs; + aLangs << "*_en.ts"; // load by default eng translations + QString aCurrLang = aResMgr->stringValue("language", "language", "en"); + if(aCurrLang != "en") { + aLangs << "*_" + aCurrLang + ".ts"; // then replace with translated files + } + + foreach(QString aLang, aLangs) { + QStringList aFilters; + aFilters << aLang; + 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); + myActiveControlMgr = new XGUI_ActiveControlMgr(myModuleConnector); + 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*)), SLOT(onOperationStopped(ModuleBase_Operation*))); - connect(myOperationMgr, SIGNAL(operationCommitted(ModuleBase_Operation*)), + connect(myOperationMgr, SIGNAL(operationCommitted(ModuleBase_Operation*)), SLOT(onOperationCommitted(ModuleBase_Operation*))); - connect(myOperationMgr, SIGNAL(operationAborted(ModuleBase_Operation*)), + connect(myOperationMgr, SIGNAL(operationAborted(ModuleBase_Operation*)), SLOT(onOperationAborted(ModuleBase_Operation*))); #ifndef HAVE_SALOME @@ -173,43 +256,73 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) 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()); - Config_PropManager::registerProp("Visualization", "result_construction_color", "Construction color", - Config_Prop::Color, ModelAPI_ResultConstruction::DEFAULT_COLOR()); + Config_PropManager::registerProp("Visualization", "result_construction_color", + "Construction color", + 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); + Config_PropManager::registerProp("Visualization", "result_field_color", "Field color", + Config_Prop::Color, ModelAPI_ResultField::DEFAULT_COLOR()); + + 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(); + std::string aDir = Config_XMLReader::resourcesConfigFile(); + Config_PropManager::registerProp("Plugins", "import_initial_path", "Import initial directory", + Config_Prop::Directory, aDir); + +#ifdef _DEBUG + Config_PropManager::registerProp("Plugins", "create_part_by_start", "Create Part by Start", + Config_Prop::Boolean, "false"); + Config_PropManager::registerProp("Plugins", "show_hide_faces", "Show Hide Faces (on the right)", + Config_Prop::Boolean, "false"); +#endif registerValidators(); // Calling of loadCustomProps before activating module is required @@ -221,7 +334,7 @@ void XGUI_Workshop::startApplication() myMainWindow->show(); updateCommandStatus(); #endif - + onNew(); myViewerProxy->connectViewProxy(); @@ -229,11 +342,19 @@ void XGUI_Workshop::startApplication() SLOT(onTrihedronVisibilityChanged(bool))); emit applicationStarted(); + +#ifdef _DEBUG + bool aNewPart = Config_PropManager::boolean("Plugins", "create_part_by_start"); + if (aNewPart) { + module()->launchOperation("Part", false); // PartSetPlugin_Part::ID() + } +#endif } +//****************************************************** void XGUI_Workshop::activateModule() { - myModule->activateSelectionFilters(); + selectionActivate()->updateSelectionFilters(); connect(myDisplayer, SIGNAL(objectDisplayed(ObjectPtr, AISObjectPtr)), myModule, SLOT(onObjectDisplayed(ObjectPtr, AISObjectPtr))); @@ -249,12 +370,11 @@ void XGUI_Workshop::activateModule() myOperationMgr->activate(); } +//****************************************************** void XGUI_Workshop::deactivateModule() { - myModule->deactivateSelectionFilters(); - // remove internal displayer filter - displayer()->deactivateSelectionFilters(); + displayer()->deactivateSelectionFilters(false); disconnect(myDisplayer, SIGNAL(objectDisplayed(ObjectPtr, AISObjectPtr)), myModule, SLOT(onObjectDisplayed(ObjectPtr, AISObjectPtr))); @@ -264,6 +384,17 @@ void XGUI_Workshop::deactivateModule() XGUI_Displayer* aDisplayer = displayer(); QObjectPtrList aDisplayed = aDisplayer->displayedObjects(); aDisplayer->deactivateObjects(aDisplayed, true); + selectionActivate()->deactivateTrihedronInSelectionModes(); + +#ifdef BEFORE_TRIHEDRON_PATCH + //Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(aDisplayer->getTrihedron()); + /// Trihedron problem: objects stayed in the viewer, should be removed manually + /// otherwise in SALOME happens crash by HideAll in the viewer + aContext->Remove(aTrihedron->Position(), true); + aContext->Remove(aTrihedron->Axis(), true); + aContext->Remove(aTrihedron->XAxis(), true); + aContext->Remove(aTrihedron->YAxis(), true); +#endif myOperationMgr->deactivate(); } @@ -278,7 +409,8 @@ void XGUI_Workshop::initMenu() QAction* aAction = salomeConnector()->addDesktopCommand("UNDO_CMD", tr("Undo"), tr("Undo last command"), QIcon(":pictures/undo.png"), - QKeySequence::Undo, false, "MEN_DESK_EDIT"); + QKeySequence::Undo, false, + "MEN_DESK_EDIT"); QString aToolBarTitle = tr( "INF_DESK_TOOLBAR_STANDARD" ); salomeConnector()->addActionInToolbar( aAction,aToolBarTitle ); @@ -294,20 +426,15 @@ void XGUI_Workshop::initMenu() 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"), + 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"), + 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())); @@ -346,12 +473,6 @@ 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->disable(); - aCommand = aGroup->addFeature("OPEN_CMD", tr("Open..."), tr("Open a new document"), QIcon(":pictures/open.png"), QKeySequence::Open); aCommand->connectTo(this, SLOT(onOpen())); @@ -367,6 +488,7 @@ void XGUI_Workshop::initMenu() } #ifndef HAVE_SALOME +//****************************************************** AppElements_Workbench* XGUI_Workshop::addWorkbench(const QString& theName) { AppElements_MainMenu* aMenuBar = myMainWindow->menuObject(); @@ -402,14 +524,36 @@ void XGUI_Workshop::onAcceptActionClicked() (anOperationMgr->currentOperation()); if (aFOperation) { //if (errorMgr()->canProcessClick(anAction, aFOperation->feature())) - myOperationMgr->onCommitOperation(); + myOperationMgr->commitOperation(); + } + } +} + +//****************************************************** +void XGUI_Workshop::onAcceptPlusActionClicked() +{ + QAction* anAction = dynamic_cast(sender()); + XGUI_OperationMgr* anOperationMgr = operationMgr(); + if (anOperationMgr) { + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (anOperationMgr->currentOperation()); + if (aFOperation) { + if (myOperationMgr->commitOperation()) + module()->launchOperation(aFOperation->id(), false); } } } //****************************************************** -void XGUI_Workshop::onPreivewActionClicked() +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); @@ -419,7 +563,7 @@ void XGUI_Workshop::onPreivewActionClicked() void XGUI_Workshop::deactivateActiveObject(const ObjectPtr& theObject, const bool theUpdateViewer) { if (!myModule->canActivateSelection(theObject)) { - if (myDisplayer->isActive(theObject)) { + if (selectionActivate()->isActive(theObject)) { QObjectPtrList anObjects; anObjects.append(theObject); myDisplayer->deactivateObjects(anObjects, theUpdateViewer); @@ -436,7 +580,7 @@ bool XGUI_Workshop::isFeatureOfNested(const FeaturePtr& theFeature) XGUI_SalomeConnector* aSalomeConnector = salomeConnector(); if (aSalomeConnector->isFeatureOfNested(actionsMgr()->action(aFeatureKind.c_str()))) aHasNested = true; -#else +#else AppElements_MainMenu* aMenuBar = mainWindow()->menuObject(); AppElements_Command* aCommand = aMenuBar->feature(aFeatureKind.c_str()); if (aCommand && aCommand->button()->additionalButtonWidget()) @@ -445,13 +589,15 @@ bool XGUI_Workshop::isFeatureOfNested(const FeaturePtr& theFeature) return aHasNested; } -void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* theOperation) +//****************************************************** +void XGUI_Workshop::fillPropertyPanel(ModuleBase_Operation* theOperation) { - ModuleBase_OperationFeature* aFOperation = dynamic_cast(theOperation); + ModuleBase_OperationFeature* aFOperation = + dynamic_cast(theOperation); if (!aFOperation) return; - showPropertyPanel(); + showPanel(myPropertyPanel); myPropertyPanel->cleanContent(); QList aWidgets; @@ -466,31 +612,48 @@ void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* theOperation) 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; + if (aWidget->usesAttribute()) { + 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; + } } } + // 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); + aWidget->setFeature(aFeature, isStoreValue, isUpdateFlushed); + if (!isStoreValue) + aWidget->restoreValue(); aWidget->enableFocusProcessing(); } - // update visible state of Preview button + std::shared_ptr aFeatureInfo; #ifdef HAVE_SALOME - bool anIsAutoPreview = mySalomeConnector->featureInfo(aFeatureKind.c_str())->isAutoPreview(); + aFeatureInfo = mySalomeConnector->featureInfo(aFeatureKind.c_str()); #else AppElements_MainMenu* aMenuBar = mainWindow()->menuObject(); AppElements_Command* aCommand = aMenuBar->feature(aFeatureKind.c_str()); - bool anIsAutoPreview = aCommand && aCommand->featureMessage()->isAutoPreview(); + if (aCommand) + aFeatureInfo = aCommand->featureMessage(); #endif + bool anIsAutoPreview = true; + if (aFeatureInfo.get()) + anIsAutoPreview = aFeatureInfo->isAutoPreview(); + else { + std::string aXmlCfg, aDescription; + module()->getXMLRepresentation(aFeatureKind, aXmlCfg, aDescription); + ModuleBase_WidgetFactory aFactory(aXmlCfg, moduleConnector()); + anIsAutoPreview = aFactory.widgetAPI()->getBooleanAttribute(FEATURE_AUTO_PREVIEW, true); + } + if (!anIsAutoPreview) { myPropertyPanel->findButton(PROP_PANEL_PREVIEW)->setVisible(true); // send signal about preview should not be computed automatically, click on preview @@ -499,6 +662,10 @@ void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* theOperation) new Events_Message(Events_Loop::eventByName(EVENT_PREVIEW_BLOCKED))); Events_Loop::loop()->send(aMsg); } + // if update happens after preview is blocked, it does nothing when blocked + // it improves performance for valid objects on feature start + ModuleBase_Tools::flushUpdated(aFeature); + myPropertyPanel->setModelWidgets(aWidgets); aFOperation->setPropertyPanel(myPropertyPanel); @@ -508,13 +675,15 @@ void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* theOperation) myPropertyPanel->setWindowTitle(theOperation->getDescription()->description()); #else std::string aFeatureName = aFeature->name(); - myPropertyPanel->setWindowTitle(QString("%1: %2").arg(theOperation->getDescription()->description()) - .arg(aFeatureName.c_str())); + 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(); @@ -525,29 +694,24 @@ void XGUI_Workshop::connectToPropertyPanel(const bool isToConnect) if (isToConnect) { connect(aWidget, SIGNAL(valueStateChanged(int)), this, SLOT(onWidgetStateChanged(int))); connect(aWidget, SIGNAL(valuesChanged()), this, SLOT(onValuesChanged())); - } + connect(aWidget, SIGNAL(objectUpdated()), this, SLOT(onWidgetObjectUpdated())); + } else { disconnect(aWidget, SIGNAL(valueStateChanged(int)), this, SLOT(onWidgetStateChanged(int))); disconnect(aWidget, SIGNAL(valuesChanged()), this, SLOT(onValuesChanged())); + disconnect(aWidget, SIGNAL(objectUpdated()), this, SLOT(onWidgetObjectUpdated())); } } } } -//****************************************************** -void XGUI_Workshop::onOperationStarted(ModuleBase_Operation* theOperation) -{ - setGrantedFeatures(theOperation); - myModule->operationStarted(theOperation); -} - //****************************************************** 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(); @@ -555,7 +719,6 @@ void XGUI_Workshop::onOperationResumed(ModuleBase_Operation* theOperation) myModule->operationResumed(theOperation); } - //****************************************************** void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation) { @@ -569,7 +732,7 @@ void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation) ModuleBase_ISelection* aSel = mySelector->selection(); QObjectPtrList aObj = aSel->selectedPresentations(); //!< No need for property panel - hidePropertyPanel(); + hidePanel(myPropertyPanel); myPropertyPanel->cleanContent(); connectToPropertyPanel(false); @@ -580,13 +743,14 @@ void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation) QObjectPtrList anObjects; FeaturePtr aFeature = aFOperation->feature(); if (aFeature.get()) { // feature may be not created (plugin load fail) - if (myDisplayer->isVisible(aFeature) && !myDisplayer->isActive(aFeature)) + if (myDisplayer->isVisible(aFeature) && !selectionActivate()->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; - if (myDisplayer->isVisible(anObject) && !myDisplayer->isActive(anObject)) { + if (myDisplayer->isVisible(anObject) && !selectionActivate()->isActive(anObject)) { anObjects.append(anObject); } } @@ -594,20 +758,23 @@ void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation) activateObjectsSelection(anObjects); } - +//****************************************************** void XGUI_Workshop::onOperationCommitted(ModuleBase_Operation* theOperation) { myModule->operationCommitted(theOperation); } +//****************************************************** void XGUI_Workshop::onOperationAborted(ModuleBase_Operation* theOperation) { myModule->operationAborted(theOperation); } +//****************************************************** void XGUI_Workshop::setGrantedFeatures(ModuleBase_Operation* theOperation) { - ModuleBase_OperationFeature* aFOperation = dynamic_cast(theOperation); + ModuleBase_OperationFeature* aFOperation = + dynamic_cast(theOperation); if (!aFOperation) return; @@ -629,23 +796,42 @@ void XGUI_Workshop::setGrantedFeatures(ModuleBase_Operation* theOperation) aFOperation->setGrantedOperationIds(aGrantedIds); } - -/* - * Saves document with given name. - */ +//****************************************************** void XGUI_Workshop::saveDocument(const QString& theName, std::list& theFileNames) { QApplication::restoreOverrideCursor(); SessionPtr aMgr = ModelAPI_Session::get(); + + std::list aDocList = aMgr->allOpenedDocuments(); + std::list::const_iterator aIt; + for (aIt = aDocList.cbegin(); aIt != aDocList.cend(); aIt++) { + std::list aState = myObjectBrowser->getStateForDoc(*aIt); + (*aIt)->storeNodesState(aState); + } + aMgr->save(theName.toLatin1().constData(), theFileNames); + 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() { @@ -668,20 +854,57 @@ 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); + module()->closeDocument(); + SessionPtr aSession = ModelAPI_Session::get(); aSession->closeAll(); aSession->load(myCurrentDir.toLatin1().constData()); myObjectBrowser->rebuildDataTree(); + + // Open first level of data tree + DocumentPtr aRootDoc = aSession->moduleDocument(); + std::list aStates; + aRootDoc->restoreNodesState(aStates); + myObjectBrowser->setStateForDoc(aRootDoc, aStates); + updateCommandStatus(); +#ifndef HAVE_SALOME + myMainWindow->setCurrentDir(myCurrentDir, true); +#endif + +#ifdef _DEBUG + bool aNewPart = Config_PropManager::boolean("Plugins", "create_part_by_start"); + if (aNewPart) { + + DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument(); + int aSize = aRootDoc->size(ModelAPI_ResultPart::group()); + if (aSize > 0 ) { + ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), 0); + ResultPartPtr aPart = std::dynamic_pointer_cast(aObject); + if (aPart.get()) + aPart->activate(); + } + } +#endif + QApplication::restoreOverrideCursor(); } @@ -758,7 +981,7 @@ void XGUI_Workshop::onTrihedronVisibilityChanged(bool theState) //****************************************************** bool XGUI_Workshop::onSave() { - if(!abortAllOperations()) + if(!myOperationMgr->abortAllOperations(XGUI_OperationMgr::XGUI_InformationMessage)) return false; if (myCurrentDir.isEmpty()) { return onSaveAs(); @@ -775,12 +998,12 @@ bool XGUI_Workshop::onSave() //****************************************************** bool XGUI_Workshop::onSaveAs() { - if(!abortAllOperations()) + if(!myOperationMgr->abortAllOperations(XGUI_OperationMgr::XGUI_InformationMessage)) return false; QFileDialog dialog(desktop()); dialog.setWindowTitle(tr("Select directory to save files...")); dialog.setFileMode(QFileDialog::Directory); - dialog.setFilter(tr("Directories (*)")); + dialog.setFilter(QDir::AllDirs); dialog.setOptions(QFileDialog::HideNameFilterDetails | QFileDialog::ShowDirsOnly); dialog.setViewMode(QFileDialog::Detail); @@ -793,7 +1016,8 @@ bool XGUI_Workshop::onSaveAs() if (aDir.exists() && !aDir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).isEmpty()) { int answer = QMessageBox::question( desktop(), - //: Title of the dialog which asks user if he wants to save study in existing non-empty folder + // 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?"), QMessageBox::Save | QMessageBox::Cancel); @@ -812,85 +1036,80 @@ bool XGUI_Workshop::onSaveAs() //****************************************************** 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 operations - /// when sketch operation is active, this condition is false and - /// the sketch operation is not aborted - operationMgr()->onAbortOperation(); - } - 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(); - updateCommandStatus(); + processUndoRedo(ActionUndo, theTimes); + myObjectBrowser->updateAllIndexes(1); } //****************************************************** void XGUI_Workshop::onRedo(int theTimes) { + processUndoRedo(ActionRedo, theTimes); + myObjectBrowser->updateAllIndexes(1); +} + +//****************************************************** +void XGUI_Workshop::processUndoRedo(const ModuleBase_ActionType theActionType, int theTimes) +{ + ModuleBase_ModelWidget* anActiveWidget = myOperationMgr->activeWidget(); + if (anActiveWidget) { + ActionIntParamPtr aParam(new ModuleBase_ActionIntParameter(theTimes)); + if (anActiveWidget->processAction(theActionType, aParam)) + return; + } // the viewer update should be blocked in order to avoid the features blinking. For the created // feature a results are created, the flush of the created signal caused the viewer redisplay for - // each created result. After a redisplay signal is flushed. So, the viewer update is blocked until - // redo of all possible objects happens + // each created result. After a redisplay signal is flushed. So, the viewer update is blocked + // until redo of all possible objects happens bool isUpdateEnabled = myDisplayer->enableUpdateViewer(false); - objectBrowser()->treeView()->setCurrentIndex(QModelIndex()); SessionPtr aMgr = ModelAPI_Session::get(); - std::list aRedoList = aMgr->redoList(); if (aMgr->isOperation()) { + XGUI_OperationMgr* aOpMgr = operationMgr(); /// this is important for nested operations /// when sketch operation is active, this condition is false and /// the sketch operation is not aborted - operationMgr()->onAbortOperation(); + if (aOpMgr->canStopOperation(aOpMgr->currentOperation())) + aOpMgr->abortOperation(aOpMgr->currentOperation()); + else + { + myDisplayer->enableUpdateViewer(isUpdateEnabled); + return; + } } - std::list::const_iterator aIt = aRedoList.cbegin(); - for (int i = 0; (i < theTimes) && (aIt != aRedoList.cend()); ++i, ++aIt) { - aMgr->redo(); + objectBrowser()->treeView()->setCurrentIndex(QModelIndex()); + std::list anActionList = theActionType == ActionUndo ? aMgr->undoList() + : aMgr->redoList(); + std::list::const_iterator aIt = anActionList.cbegin(); + for (int i = 0; (i < theTimes) && (aIt != anActionList.cend()); ++i, ++aIt) { + if (theActionType == ActionUndo) + aMgr->undo(); + else + aMgr->redo(); + if (QString((*aIt).c_str()) == MOVE_TO_END_COMMAND) myObjectBrowser->rebuildDataTree(); } operationMgr()->updateApplyOfOperations(); + facesPanel()->reset(true); updateCommandStatus(); // unblock the viewer update functionality and make update on purpose myDisplayer->enableUpdateViewer(isUpdateEnabled); myDisplayer->updateViewer(); + // Clear messages in status bar from previous operations if exists + setStatusBarMessage(""); } -//****************************************************** -//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) { - ModuleBase_ModelWidget* anActiveWidget = 0; - ModuleBase_Operation* anOperation = myOperationMgr->currentOperation(); - if (anOperation) { - ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel(); - if (aPanel) - anActiveWidget = aPanel->activeWidget(); - } + ModuleBase_ModelWidget* anActiveWidget = myOperationMgr->activeWidget(); + //ModuleBase_Operation* anOperation = myOperationMgr->currentOperation(); + //if (anOperation) { + // ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel(); + // if (aPanel) + // anActiveWidget = aPanel->activeWidget(); + //} if (anActiveWidget) operationMgr()->onValidateOperation(); @@ -919,6 +1138,13 @@ void XGUI_Workshop::onValuesChanged() } } +//****************************************************** +void XGUI_Workshop::onWidgetObjectUpdated() +{ + operationMgr()->onValidateOperation(); +} + +//****************************************************** ModuleBase_IModule* XGUI_Workshop::loadModule(const QString& theModule) { QString libName = QString::fromStdString(library(theModule.toStdString())); @@ -969,7 +1195,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)); } @@ -992,6 +1218,9 @@ bool XGUI_Workshop::createModule() // myModule, SLOT(onBeforeObjectErase(ObjectPtr, AISObjectPtr))); myModule->createFeatures(); +#ifdef HAVE_SALOME + salomeConnector()->createFeatureActions(); +#endif //myActionsMgr->update(); return true; } @@ -1011,10 +1240,24 @@ void XGUI_Workshop::updateCommandStatus() if (aMgr->hasModuleDocument()) { foreach(QAction* aCmd, aCommands) { QString aId = aCmd->data().toString(); - if (aId == "UNDO_CMD") - aCmd->setEnabled(myModule->canUndo()); - else if (aId == "REDO_CMD") - aCmd->setEnabled(myModule->canRedo()); + if (aId == "UNDO_CMD") { + bool isActionEnabled = false; + // if ultimate is true -> using result of operation only, or using OR combination + ModuleBase_ModelWidget* anActiveWidget = myOperationMgr->activeWidget(); + if (anActiveWidget && anActiveWidget->canProcessAction(ActionUndo, isActionEnabled)) + aCmd->setEnabled(isActionEnabled); + else + aCmd->setEnabled(myModule->canUndo()); + } + else if (aId == "REDO_CMD") { + bool isActionEnabled = false; + // if ultimate is true -> using result of operation only, or using OR combination + ModuleBase_ModelWidget* anActiveWidget = myOperationMgr->activeWidget(); + if (anActiveWidget && anActiveWidget->canProcessAction(ActionRedo, isActionEnabled)) + aCmd->setEnabled(isActionEnabled); + else + aCmd->setEnabled(myModule->canRedo()); + } else // Enable all commands aCmd->setEnabled(true); @@ -1035,14 +1278,24 @@ void XGUI_Workshop::updateCommandStatus() emit commandStatusUpdated(); } +//****************************************************** void XGUI_Workshop::updateHistory() { - std::list aUndoList = ModelAPI_Session::get()->undoList(); - QList aUndoRes = processHistoryList(aUndoList); - emit updateUndoHistory(aUndoRes); + bool isActionEnabled = false; + ModuleBase_ModelWidget* anActiveWidget = myOperationMgr->activeWidget(); + QList aUndoRes; + QList aRedoRes; + if (anActiveWidget && anActiveWidget->canProcessAction(ActionUndo, isActionEnabled)) { + aUndoRes = anActiveWidget->actionsList(ActionUndo); + aRedoRes = anActiveWidget->actionsList(ActionRedo); + } else { + std::list aUndoList = ModelAPI_Session::get()->undoList(); + aUndoRes = processHistoryList(aUndoList); - std::list aRedoList = ModelAPI_Session::get()->redoList(); - QList aRedoRes = processHistoryList(aRedoList); + std::list aRedoList = ModelAPI_Session::get()->redoList(); + aRedoRes = processHistoryList(aRedoList); + } + emit updateUndoHistory(aUndoRes); emit updateRedoHistory(aRedoRes); } @@ -1050,11 +1303,14 @@ void XGUI_Workshop::updateHistory() QDockWidget* XGUI_Workshop::createObjectBrowser(QWidget* theParent) { QDockWidget* aObjDock = new QDockWidget(theParent); - aObjDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); + aObjDock->setAllowedAreas(Qt::LeftDockWidgetArea | + Qt::RightDockWidgetArea | + Qt::BottomDockWidgetArea); aObjDock->setWindowTitle(tr("Object browser")); aObjDock->setStyleSheet( "::title { position: relative; padding-left: 5px; text-align: left center }"); - myObjectBrowser = new XGUI_ObjectsBrowser(aObjDock); + myObjectBrowser = new XGUI_ObjectsBrowser(aObjDock, this); + myObjectBrowser->setXMLReader(myDataModelXMLReader); myModule->customizeObjectBrowser(myObjectBrowser); aObjDock->setWidget(myObjectBrowser); @@ -1073,22 +1329,71 @@ void XGUI_Workshop::createDockWidgets() QDockWidget* aObjDock = createObjectBrowser(aDesktop); aDesktop->addDockWidget(Qt::LeftDockWidgetArea, aObjDock); myPropertyPanel = new XGUI_PropertyPanel(aDesktop, myOperationMgr); + myActiveControlMgr->addSelector(new XGUI_PropertyPanelSelector(myPropertyPanel)); + myPropertyPanel->setupActions(myActionsMgr); - myPropertyPanel->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); + myPropertyPanel->setAllowedAreas(Qt::LeftDockWidgetArea | + Qt::RightDockWidgetArea | + Qt::BottomDockWidgetArea); aDesktop->addDockWidget(Qt::LeftDockWidgetArea, myPropertyPanel); - hidePropertyPanel(); ///addSelector(new XGUI_FacesPanelSelector(myFacesPanel)); + myFacesPanel->setAllowedAreas(Qt::LeftDockWidgetArea | + Qt::RightDockWidgetArea | + Qt::BottomDockWidgetArea); + connect(myFacesPanel, SIGNAL(closed()), myFacesPanel, SLOT(onClosed())); + + myInspectionPanel = new XGUI_InspectionPanel(aDesktop, mySelector); + myInspectionPanel->setAllowedAreas(Qt::LeftDockWidgetArea | + Qt::RightDockWidgetArea); + aDesktop->addDockWidget(Qt::RightDockWidgetArea, myInspectionPanel); + + aDesktop->addDockWidget( +#ifdef HAVE_SALOME + Qt::RightDockWidgetArea, +#else + Qt::LeftDockWidgetArea, +#endif + myFacesPanel); + hidePanel(myFacesPanel); ///addDockWidget(Qt::RightDockWidgetArea, myFacesPanel); + showPanel(myFacesPanel); + } +#endif hideObjectBrowser(); + +#ifndef HAVE_SALOME +#ifdef _DEBUG + if (!aShowOnTheRight) + { +#endif // _DEBUG + aDesktop->tabifyDockWidget(myFacesPanel, aObjDock); +#ifdef _DEBUG + } +#endif // _DEBUG + +#endif // HAVE_SALOME + aDesktop->tabifyDockWidget(aObjDock, myPropertyPanel); myPropertyPanel->installEventFilter(myOperationMgr); QAction* aOkAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Accept); connect(aOkAct, SIGNAL(triggered()), this, SLOT(onAcceptActionClicked())); + QAction* aOkContAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptPlus); + connect(aOkContAct, SIGNAL(triggered()), this, SLOT(onAcceptPlusActionClicked())); + QAction* aCancelAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Abort); connect(aCancelAct, SIGNAL(triggered()), myOperationMgr, SLOT(onAbortOperation())); QAction* aPreviewAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Preview); - connect(aPreviewAct, SIGNAL(triggered()), this, SLOT(onPreivewActionClicked())); + connect(aPreviewAct, SIGNAL(triggered()), this, SLOT(onPreviewActionClicked())); connect(myPropertyPanel, SIGNAL(keyReleased(QObject*, QKeyEvent*)), myOperationMgr, SLOT(onKeyReleased(QObject*, QKeyEvent*))); @@ -1097,29 +1402,32 @@ void XGUI_Workshop::createDockWidgets() } //****************************************************** -void XGUI_Workshop::showPropertyPanel() +void XGUI_Workshop::showPanel(QDockWidget* theDockWidget) { - QAction* aViewAct = myPropertyPanel->toggleViewAction(); - ///setEnabled(true); - myPropertyPanel->show(); - myPropertyPanel->raise(); + if (theDockWidget == myPropertyPanel) { + QAction* aViewAct = myPropertyPanel->toggleViewAction(); + ///setEnabled(true); + } + theDockWidget->show(); + theDockWidget->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()"); + ModuleBase_Tools::setFocus(theDockWidget, "XGUI_Workshop::showPanel()"); } //****************************************************** -void XGUI_Workshop::hidePropertyPanel() +void XGUI_Workshop::hidePanel(QDockWidget* theDockWidget) { - QAction* aViewAct = myPropertyPanel->toggleViewAction(); - ///setEnabled(false); - myPropertyPanel->hide(); + if (theDockWidget && theDockWidget == myPropertyPanel) { + QAction* aViewAct = theDockWidget->toggleViewAction(); + ///setEnabled(false); + } + theDockWidget->hide(); // the property panel is active window of the desktop, when it is // hidden, it is undefined which window becomes active. By this reason @@ -1129,8 +1437,7 @@ void XGUI_Workshop::hidePropertyPanel() // 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()"); + ModuleBase_Tools::setFocus(aDesktop, "XGUI_Workshop::hidePanel()"); } //****************************************************** @@ -1171,15 +1478,25 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked) moveObjects(); else if (theId == "COLOR_CMD") changeColor(aObjects); + else if (theId == "DEFLECTION_CMD") + changeDeflection(aObjects); +#ifdef USE_TRANSPARENCY + else if (theId == "TRANSPARENCY_CMD") + changeTransparency(aObjects); +#endif else if (theId == "SHOW_CMD") { showObjects(aObjects, true); mySelector->updateSelectionBy(ModuleBase_ISelection::Browser); + updateCommandStatus(); } - else if (theId == "HIDE_CMD") + else if (theId == "HIDE_CMD") { showObjects(aObjects, false); + updateCommandStatus(); + } else if (theId == "SHOW_ONLY_CMD") { showOnlyObjects(aObjects); mySelector->updateSelectionBy(ModuleBase_ISelection::Browser); + updateCommandStatus(); } else if (theId == "SHADING_CMD") setDisplayMode(aObjects, XGUI_Displayer::Shading); @@ -1192,24 +1509,109 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked) aObj->setDisplayed(false); } Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); +#ifdef HAVE_SALOME + //issue #2159 Hide all incomplete behavior + viewer()->eraseAll(); +#endif + updateCommandStatus(); + // Necessary for update icons in ObjectBrowser on Linux + myObjectBrowser->updateAllIndexes(); } 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 == "INSERT_FOLDER_CMD") { + insertFeatureFolder(); + } else if (theId == "ADD_TO_FOLDER_BEFORE_CMD") { + insertToFolder(true); + } else if (theId == "ADD_TO_FOLDER_AFTER_CMD") { + insertToFolder(false); + } else if (theId == "ADD_OUT_FOLDER_BEFORE_CMD") { + moveOutFolder(true); + } else if (theId == "ADD_OUT_FOLDER_AFTER_CMD") { + moveOutFolder(false); } else if (theId == "SELECT_RESULT_CMD") { - setViewerSelectionMode(-1); + //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); + } +#ifdef TINSPECTOR + else if (theId == "TINSPECTOR_VIEW") { + Handle(CDF_Application) anApplication = CDF_Session::CurrentSession()->CurrentApplication(); + if (!anApplication.IsNull()) + { + if (!MyTCommunicator) + { + MyTCommunicator = new TInspector_Communicator(); + + NCollection_List aParameters; + aParameters.Append(anApplication); + Handle(AIS_InteractiveContext) aContext = viewer()->AISContext(); + if (!aContext.IsNull()) + aParameters.Append(aContext); + +#ifdef DEBUG_WITH_MESSAGE_REPORT + Handle(Message_Report) aContextReport = aContext->GetReport(); + aContext->SetReportActive (Standard_True); + aContextReport->SetLimit (1000); + if (!aContextReport.IsNull()) + aParameters.Append(aContextReport); +#endif + MyVCallBack = new VInspector_CallBack(); + myDisplayer->setCallBack(MyVCallBack); + #ifndef HAVE_SALOME + AppElements_Viewer* aViewer = mainWindow()->viewer(); + if (aViewer) + aViewer->setCallBack(MyVCallBack); + #endif + aParameters.Append(MyVCallBack); + + MyTCommunicator->RegisterPlugin("TKDFBrowser"); + MyTCommunicator->RegisterPlugin("TKShapeView"); + MyTCommunicator->RegisterPlugin("TKVInspector"); +#ifdef DEBUG_WITH_MESSAGE_REPORT + MyTCommunicator->RegisterPlugin("TKMessageView"); +#endif + MyTCommunicator->RegisterPlugin("SMBrowser"); // custom plugin to view ModelAPI + //MyTCommunicator->RegisterPlugin("TKSMBrowser"); // custom plugin to view ModelAPI + + MyTCommunicator->Init(aParameters); + MyTCommunicator->Activate("TKSMBrowser"); // to have button in TInspector +#ifndef DEBUG_WITH_MESSAGE_REPORT + MyTCommunicator->Activate("TKVInspector"); // to have filled callback by model +#endif + MyTCommunicator->Activate("TKDFBrowser"); + +#ifdef DEBUG_WITH_MESSAGE_REPORT + MyTCommunicator->Activate("TKMessageView"); // temporary + MyTCommunicator->Activate("TKVInspector"); // to have filled callback by model +#endif + } + MyTCommunicator->SetVisible(true); + } } +#endif } //************************************************************** void XGUI_Workshop::setViewerSelectionMode(int theMode) { - myViewerSelMode = theMode; - activateObjectsSelection(myDisplayer->displayedObjects()); + if (theMode == -1) + myViewerSelMode.clear(); + else { + if (myViewerSelMode.contains(theMode)) + myViewerSelMode.removeAll(theMode); + else + myViewerSelMode.append(theMode); + } + selectionActivate()->updateSelectionModes(); } //************************************************************** @@ -1217,17 +1619,68 @@ void XGUI_Workshop::activateObjectsSelection(const QObjectPtrList& theList) { QIntList aModes; module()->activeSelectionModes(aModes); - if (aModes.isEmpty() && (myViewerSelMode != -1)) + if (aModes.isEmpty() && (myViewerSelMode.length() > 0)) aModes.append(myViewerSelMode); - myDisplayer->activateObjects(aModes, theList); + selectionActivate()->activateObjects(aModes, theList); } +//************************************************************** +bool XGUI_Workshop::prepareForDisplay(const std::set& theObjects) const +{ + if (facesPanel()->isEmpty()) + return true; + + // generate container of objects taking into account sub elments of compsolid + std::set anAllProcessedObjects; + for (std::set::const_iterator anObjectsIt = theObjects.begin(); + anObjectsIt != theObjects.end(); anObjectsIt++) { + ObjectPtr anObject = *anObjectsIt; + ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast(anObject); + if (aCompRes.get()) { + if (aCompRes->numberOfSubs(true) == 0) + anAllProcessedObjects.insert(anObject); + else { + for (int i = 0; i < aCompRes->numberOfSubs(true); i++) { + ResultPtr aSubRes = aCompRes->subResult(i, true); + anAllProcessedObjects.insert(aCompRes->subResult(i, true)); + } + } + } + else + anAllProcessedObjects.insert(anObject); + } + + // find hidden objects in faces panel + std::set aHiddenObjects; + QStringList aHiddenObjectNames; + for (std::set::const_iterator anObjectsIt = anAllProcessedObjects.begin(); + anObjectsIt != anAllProcessedObjects.end(); anObjectsIt++) { + if (!facesPanel()->isObjectHiddenByPanel(*anObjectsIt)) + continue; + aHiddenObjects.insert(*anObjectsIt); + aHiddenObjectNames.append((*anObjectsIt)->data()->name().c_str()); + } + if (aHiddenObjects.empty()) // in parameter objects there are no hidden objects in hide face + return true; + + int anAnswer = QMessageBox::question( + desktop(), tr("Show object"), + tr("'%1'\n are hidden by %2:\nRemove objects from the panel to be displayed?") + .arg(aHiddenObjectNames.join(", ")).arg(facesPanel()->windowTitle()), + QMessageBox::Yes | QMessageBox::No, QMessageBox::No); + + bool aToBeDisplayed = anAnswer == QMessageBox::Yes; + if (aToBeDisplayed) + facesPanel()->restoreObjects(aHiddenObjects); + + return aToBeDisplayed; +} //************************************************************** 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; @@ -1236,90 +1689,151 @@ void XGUI_Workshop::deleteObjects() QObjectPtrList anObjects = mySelector->selection()->selectedObjects(); if (!abortAllOperations()) return; - // 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 hasCompositeOwner = false; - ModuleBase_Tools::checkObjects(anObjects, hasResult, hasFeature, hasParameter, hasCompositeOwner); - if (!(hasFeature || hasParameter)) + bool hasResultInHistory = false; + bool hasFolder = false; + ModuleBase_Tools::checkObjects(anObjects, hasResult, hasFeature, hasParameter, hasCompositeOwner, + hasResultInHistory, hasFolder); + if (!(hasFeature || hasParameter || hasFolder)) return; - // 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); + // delete objects + std::map > aReferences; + std::set aFeatures; + ModuleBase_Tools::convertToFeatures(anObjects, aFeatures); + ModelAPI_Tools::findAllReferences(aFeatures, aReferences); + std::set aFolders; + ModuleBase_Tools::convertToFolders(anObjects, aFolders); + + 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); + + 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(); - // delete and commit/abort operation in model - if (deleteFeaturesInternal(anObjects, aDirectRefFeatures, aIndirectRefFeatures, - anIgnoredFeatures, doDeleteReferences)) - operationMgr()->commitOperation(); - else - operationMgr()->abortOperation(operationMgr()->currentOperation()); + if (!aFeatureRefsToDelete.empty()) + aFeatures.insert(aFeatureRefsToDelete.begin(), aFeatureRefsToDelete.end()); + aDone = ModelAPI_Tools::removeFeatures(aFeatures, false); + } + if (aFolders.size() > 0) { + std::set::const_iterator anIt = aFolders.begin(), + aLast = aFolders.end(); + for (; anIt != aLast; anIt++) { + FolderPtr aFolder = *anIt; + if (aFolder.get()) { + DocumentPtr aDoc = aFolder->document(); + aDoc->removeFolder(aFolder); + } + } } + + if (aDone) + operationMgr()->commitOperation(); + else + operationMgr()->abortOperation(operationMgr()->currentOperation()); } //************************************************************** -void XGUI_Workshop::cleanHistory() +void addRefsToFeature(const FeaturePtr& theFeature, + const std::map >& theMainList, + std::set& theReferences) { - if (!abortAllOperations()) - return; + //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); - 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); + 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::cleanHistory() +{ + if (!abortAllOperations()) + return; + + QObjectPtrList anObjects = mySelector->selection()->selectedObjects(); + 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 + + 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); + } + +#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 - // 2. warn about the references remove, break the delete operation if the user chose it + // 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); + foreach (const FeaturePtr& aFeature, anUnusedObjects) { aNames.append(aFeature->name().c_str()); } + aNames.sort(); QString anUnusedNames = aNames.join(", "); QString anActionId = "CLEAN_HISTORY_CMD"; @@ -1331,29 +1845,16 @@ void XGUI_Workshop::cleanHistory() 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)); - }*/ - + const char* aKeyStr = "Unused features are the following: " + "%1.\nThese features will be deleted.\nWould you like to continue?"; + QString aText = QString(tr(aKeyStr).arg(anUnusedNames)); aMessageBox.setText(aText); if (aMessageBox.exec() == QMessageBox::No) return; // 1. start operation - aDescription += "by deleting of " + aDescription.arg(XGUI_Tools::unionOfObjectNames(anObjects, ", ")); + aDescription += "by deleting of " + + aDescription.arg(XGUI_Tools::unionOfObjectNames(anObjects, ", ")); ModuleBase_OperationAction* anOpAction = new ModuleBase_OperationAction(aDescription, module()); operationMgr()->startOperation(anOpAction); @@ -1363,7 +1864,7 @@ void XGUI_Workshop::cleanHistory() mySelector->clearSelection(); std::set anIgnoredFeatures; - if (removeFeatures(anUnusedObjects, anIgnoredFeatures, anActionId)) { + if (ModelAPI_Tools::removeFeatures(anUnusedObjects, true)) { operationMgr()->commitOperation(); } else { @@ -1409,209 +1910,35 @@ void XGUI_Workshop::moveObjects() // 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)) + std::set aFeatures; + ModuleBase_Tools::convertToFeatures(anObjects, aFeatures); + if (!XGUI_Tools::canRemoveOrRename(desktop(), aFeatures)) return; DocumentPtr anActiveDocument = aMgr->activeDocument(); FeaturePtr aCurrentFeature = anActiveDocument->currentFeature(true); - foreach (ObjectPtr aObject, anObjects) { - if (!myModule->canApplyAction(aObject, anActionId)) + 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 = std::dynamic_pointer_cast(aObject); - if (aFeature.get()) { - anActiveDocument->moveFeature(aFeature, aCurrentFeature); - aCurrentFeature = anActiveDocument->currentFeature(true); - } + anActiveDocument->moveFeature(aFeature, aCurrentFeature); + aCurrentFeature = anActiveDocument->currentFeature(true); } aMgr->finishOperation(); } //************************************************************** -void XGUI_Workshop::findReferences(const QObjectPtrList& theList, - std::set& aDirectRefFeatures, - std::set& aIndirectRefFeatures) +bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theObjects) { - foreach (ObjectPtr aDeletedObj, theList) { - std::set alreadyProcessed; - XGUI_Tools::refsToFeatureInAllDocuments(aDeletedObj, aDeletedObj, theList, aDirectRefFeatures, - aIndirectRefFeatures, alreadyProcessed); - std::set aDifference; - std::set_difference(aIndirectRefFeatures.begin(), aIndirectRefFeatures.end(), - aDirectRefFeatures.begin(), aDirectRefFeatures.end(), - std::inserter(aDifference, aDifference.begin())); - aIndirectRefFeatures = aDifference; - } -} - -bool 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) - aDirectRefNames.append(aFeature->name().c_str()); - aDirectNames = aDirectRefNames.join(", "); - - QStringList aIndirectRefNames; - foreach (const FeaturePtr& aFeature, aIndirectRefFeatures) - aIndirectRefNames.append(aFeature->name().c_str()); - 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); + std::set aFeatures; + ModuleBase_Tools::convertToFeatures(theObjects, aFeatures); - 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; -} - -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; -#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 - } - - QString anActionId = "DELETE_CMD"; - 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) { - // 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; - - 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); - isDone = true; - } - } - } -#ifdef DEBUG_DELETE - qDebug(QString("remove features:%1").arg(anInfo.join("; ")).toStdString().c_str()); -#endif - return true; + return ModelAPI_Tools::removeFeaturesAndReferences(aFeatures); } +//****************************************************** bool hasResults(QObjectPtrList theObjects, const std::set& theTypes) { bool isFoundResultType = false; @@ -1639,7 +1966,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()) { @@ -1663,15 +1992,18 @@ std::list toCurrentFeatures(const ObjectPtr& theObject) DocumentPtr aDocument = theObject->document(); std::list anAllFeatures = allFeatures(aDocument); // find the object iterator - std::list::iterator aObjectIt = std::find(anAllFeatures.begin(), anAllFeatures.end(), theObject); + std::list::iterator aObjectIt = + std::find(anAllFeatures.begin(), anAllFeatures.end(), theObject); if (aObjectIt == anAllFeatures.end()) return aResult; // find the current feature iterator - std::list::iterator aCurrentIt = std::find(anAllFeatures.begin(), anAllFeatures.end(), aDocument->currentFeature(true)); + std::list::iterator aCurrentIt = + std::find(anAllFeatures.begin(), anAllFeatures.end(), aDocument->currentFeature(true)); if (aCurrentIt == anAllFeatures.end()) return aResult; // check the right order - if (std::distance(aObjectIt, anAllFeatures.end()) <= std::distance(aCurrentIt, anAllFeatures.end())) + if (std::distance(aObjectIt, anAllFeatures.end()) <= + std::distance(aCurrentIt, anAllFeatures.end())) return aResult; // exclude the object std::advance(aObjectIt, 1); @@ -1680,6 +2012,7 @@ std::list toCurrentFeatures(const ObjectPtr& theObject) return std::list(aObjectIt, aCurrentIt); } +//****************************************************** bool XGUI_Workshop::canMoveFeature() { QString anActionId = "MOVE_CMD"; @@ -1702,16 +2035,27 @@ bool XGUI_Workshop::canMoveFeature() QObjectPtrList::const_iterator anIt = aObjects.begin(), aLast = aObjects.end(); for (; anIt != aLast && aCanMove; anIt++) { ObjectPtr aObject = *anIt; - // 1. Get features placed between selected and current in the document + if (!aObject.get() || !aObject->data().get() || !aObject->data()->isValid()) { + aCanMove = false; + break; + } + FeaturePtr aFeat = std::dynamic_pointer_cast(aObject); + // only groups can be moved to the end for now (#2451) + if (aFeat.get() && aFeat->getKind() != "Group") { + aCanMove = false; + break; + } + + // 1. Get features placed between selected and current in the document std::list aFeaturesBetween = toCurrentFeatures(aObject); // if aFeaturesBetween is empty it means wrong order or aObject is the current feature if (aFeaturesBetween.empty()) aCanMove = false; else { std::set aPlacedFeatures(aFeaturesBetween.begin(), aFeaturesBetween.end()); - // 2. Get all reference features to the selected object in the document + // 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; @@ -1746,19 +2090,28 @@ bool XGUI_Workshop::canBeShaded(const ObjectPtr& theObject) const } //************************************************************** -bool XGUI_Workshop::canChangeColor() const +bool XGUI_Workshop::canChangeProperty(const QString& theActionName) const { - QObjectPtrList aObjects = mySelector->selection()->selectedObjects(); + if (theActionName == "COLOR_CMD" || + theActionName == "DEFLECTION_CMD" +#ifdef USE_TRANSPARENCY + || theActionName == "TRANSPARENCY_CMD" +#endif + ) { + 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()); + 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); + return hasResults(aObjects, aTypes); + } + return false; } +//****************************************************** void setColor(ResultPtr theResult, const std::vector& theColor) { if (!theResult.get()) @@ -1781,7 +2134,7 @@ 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 + // The objects are iterated until a first valid color is found std::vector aColor; foreach(ObjectPtr anObject, theObjects) { ResultPtr aResult = std::dynamic_pointer_cast(anObject); @@ -1806,7 +2159,7 @@ void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects) return; if (!abortAllOperations()) - return; + return; // 2. show the dialog to change the value XGUI_ColorDialog* aDlg = new XGUI_ColorDialog(desktop()); aDlg->setColor(aColor); @@ -1827,10 +2180,12 @@ void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects) foreach(ObjectPtr anObj, theObjects) { ResultPtr aResult = std::dynamic_pointer_cast(anObj); if (aResult.get() != NULL) { - ResultCompSolidPtr aCompsolidResult = std::dynamic_pointer_cast(aResult); + 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), !isRandomColor ? aColorResult : aDlg->getRandomColor()); + setColor(aCompsolidResult->subResult(i), !isRandomColor ? aColorResult : + aDlg->getRandomColor()); } } setColor(aResult, !isRandomColor ? aColorResult : aDlg->getRandomColor()); @@ -1840,27 +2195,215 @@ void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects) updateCommandStatus(); } +//************************************************************** +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 setTransparency(ResultPtr theResult, double theTransparency) +{ + if (!theResult.get()) + return; + + AttributeDoublePtr anAttribute = theResult->data()->real(ModelAPI_Result::TRANSPARENCY_ID()); + if (anAttribute.get() != NULL) + anAttribute->setValue(theTransparency); +} + +//************************************************************** +void setTransparency(double theTransparency, const QObjectPtrList& theObjects) +{ + 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 property for all sub-solids + for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) { + setTransparency(aCompsolidResult->subResult(i), theTransparency); + } + } + setTransparency(aResult, theTransparency); + } + } +} + +//************************************************************** +void XGUI_Workshop::changeDeflection(const QObjectPtrList& theObjects) +{ + AttributeDoublePtr aDoubleAttr; + // 1. find the current property of the object. This is a property of AIS presentation + // The objects are iterated until a first valid property 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 property from the AIS object + // this does not happen never because: + // 1. The property 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 property for all sub-solids + for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) { + setDeflection(aCompsolidResult->subResult(i), aDeflection); + } + } + setDeflection(aResult, aDeflection); + } + } + aMgr->finishOperation(); + updateCommandStatus(); +} + +//************************************************************** +void XGUI_Workshop::changeTransparency(const QObjectPtrList& theObjects) +{ + AttributeDoublePtr aDoubleAttr; + // 1. find the current property of the object. This is a property of AIS presentation + // The objects are iterated until a first valid property is found + double aCurrentValue = -1; + foreach(ObjectPtr anObject, theObjects) { + ResultPtr aResult = std::dynamic_pointer_cast(anObject); + if (aResult.get()) { + aCurrentValue = XGUI_CustomPrs::getResultTransparency(aResult); + } + else { + // TODO: remove the obtaining a property from the AIS object + // this does not happen never because: + // 1. The property 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()) { + aCurrentValue = anAISObj->getDeflection(); + } + } + if (aCurrentValue > 0) + break; + } + if (aCurrentValue < 0) + return; + + if (!abortAllOperations()) + return; + + // 2. show the dialog to change the value + XGUI_PropertyDialog* aDlg = new XGUI_PropertyDialog(desktop()); + aDlg->setWindowTitle("Transparency"); + XGUI_TransparencyWidget* aTransparencyWidget = new XGUI_TransparencyWidget(aDlg); + connect(aTransparencyWidget, SIGNAL(transparencyValueChanged()), + this, SLOT(onTransparencyValueChanged())); + connect(aTransparencyWidget, SIGNAL(previewStateChanged()), + this, SLOT(onPreviewStateChanged())); + aDlg->setContent(aTransparencyWidget); + aTransparencyWidget->setValue(aCurrentValue); + + // 3. abort the previous operation and start a new one + SessionPtr aMgr = ModelAPI_Session::get(); + QString aDescription = contextMenuMgr()->action("TRANSPARENCY_CMD")->text(); + aMgr->startOperation(aDescription.toStdString()); + + aDlg->move(QCursor::pos()); + bool isDone = aDlg->exec() == QDialog::Accepted; + if (!isDone) + return; + + // 4. set the value to all results + aCurrentValue = aTransparencyWidget->getValue(); + setTransparency(aCurrentValue, theObjects); + + aMgr->finishOperation(); + updateCommandStatus(); +} + +//************************************************************** +void XGUI_Workshop::onTransparencyValueChanged() +{ + XGUI_TransparencyWidget* aTransparencyWidget = (XGUI_TransparencyWidget*)sender(); + if (!aTransparencyWidget || !aTransparencyWidget->isPreviewNeeded()) + return; + + QObjectPtrList anObjects = mySelector->selection()->selectedObjects(); + setTransparency(aTransparencyWidget->getValue(), anObjects); + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); +} + +//************************************************************** +void XGUI_Workshop::onPreviewStateChanged() +{ + XGUI_TransparencyWidget* aTransparencyWidget = (XGUI_TransparencyWidget*)sender(); + if (!aTransparencyWidget || !aTransparencyWidget->isPreviewNeeded()) + return; + + QObjectPtrList anObjects = mySelector->selection()->selectedObjects(); + setTransparency(aTransparencyWidget->getValue(), anObjects); + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); +} + //************************************************************** #define SET_DISPLAY_GROUP(aGroupName, aDisplay) \ for (int i = 0; i < aDoc->size(aGroupName); i++) { \ aDoc->object(aGroupName, i)->setDisplayed(aDisplay); \ } + +//****************************************************** void XGUI_Workshop::showObjects(const QObjectPtrList& theList, bool isVisible) { + if (isVisible) { + std::set anObjects; + foreach (ObjectPtr aObj, theList) { + anObjects.insert(aObj); + } + if (!prepareForDisplay(anObjects)) + return; + } + foreach (ObjectPtr aObj, theList) { - /* - ResultPartPtr aPartRes = std::dynamic_pointer_cast(aObj); - if (aPartRes) { - DocumentPtr aDoc = aPartRes->partDoc(); - SET_DISPLAY_GROUP(ModelAPI_ResultBody::group(), isVisible) - SET_DISPLAY_GROUP(ModelAPI_ResultConstruction::group(), isVisible) - SET_DISPLAY_GROUP(ModelAPI_ResultGroup::group(), isVisible) - } else { - */ - aObj->setDisplayed(isVisible); - //} + aObj->setDisplayed(isVisible); } Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); + myObjectBrowser->updateAllIndexes(); } //************************************************************** @@ -1872,26 +2415,33 @@ void XGUI_Workshop::showOnlyObjects(const QObjectPtrList& theList) if (module()->canEraseObject(aObj)) aObj->setDisplayed(false); } + //Do not use eraseAll if you didn't send Redisplay event: + //all objects are erased from viewer, but considered as displayed in displayer + // Problem in bug 2218 + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); +#ifdef HAVE_SALOME + //issue #2159 Hide all incomplete behavior + viewer()->eraseAll(); +#endif + + std::set anObjects; + foreach (ObjectPtr aObj, theList) { + anObjects.insert(aObj); + } + + if (!prepareForDisplay(anObjects)) + return; // Show only objects from the list foreach (ObjectPtr aObj, theList) { - /* - ResultPartPtr aPartRes = std::dynamic_pointer_cast(aObj); - if (aPartRes) { - DocumentPtr aDoc = aPartRes->partDoc(); - SET_DISPLAY_GROUP(ModelAPI_ResultBody::group(), true) - SET_DISPLAY_GROUP(ModelAPI_ResultConstruction::group(), true) - SET_DISPLAY_GROUP(ModelAPI_ResultGroup::group(), true) - } else { - */ - aObj->setDisplayed(true); - //} + aObj->setDisplayed(true); } Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); + // Necessary for update icons in ObjectBrowser on Linux + myObjectBrowser->updateAllIndexes(); } - //************************************************************** void XGUI_Workshop::registerValidators() const { @@ -1911,7 +2461,7 @@ void XGUI_Workshop::displayDocumentResults(DocumentPtr theDoc) //************************************************************** void XGUI_Workshop::displayGroupResults(DocumentPtr theDoc, std::string theGroup) { - for (int i = 0; i < theDoc->size(theGroup); i++) + for (int i = 0; i < theDoc->size(theGroup); i++) theDoc->object(theGroup, i)->setDisplayed(true); //displayObject(theDoc->object(theGroup, i)); Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); @@ -1943,16 +2493,26 @@ void XGUI_Workshop::closeDocument() anOperation->abort(); anOperation = operationMgr()->currentOperation(); } - myDisplayer->closeLocalContexts(); + //myDisplayer->closeLocalContexts(); myDisplayer->eraseAll(); objectBrowser()->clearContent(); module()->closeDocument(); + // we need to clear viewer (with created filters) to do not have problems in 2nd SALOME study + module()->clearViewer(); + + + // data model need not process the document's signals about objects modifications as + // the document is closed + //bool isBlocked = objectBrowser()->dataModel()->blockEventsProcessing(true); SessionPtr aMgr = ModelAPI_Session::get(); aMgr->closeAll(); + + //objectBrowser()->dataModel()->blockEventsProcessing(isBlocked); } +//****************************************************** void XGUI_Workshop::addHistoryMenu(QObject* theObject, const char* theSignal, const char* theSlot) { XGUI_HistoryMenu* aMenu = NULL; @@ -1969,6 +2529,7 @@ void XGUI_Workshop::addHistoryMenu(QObject* theObject, const char* theSignal, co connect(aMenu, SIGNAL(actionSelected(int)), this, theSlot); } +//****************************************************** QList XGUI_Workshop::processHistoryList(const std::list& theList) const { QList aResult; @@ -1994,19 +2555,36 @@ 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 +} + +#ifdef HAVE_SALOME +//****************************************************** void XGUI_Workshop::synchronizeViewer() { SessionPtr aMgr = ModelAPI_Session::get(); - DocumentPtr aDoc = aMgr->activeDocument(); + QList aDocs; + aDocs.append(aMgr->activeDocument()); + aDocs.append(aMgr->moduleDocument()); - synchronizeGroupInViewer(aDoc, ModelAPI_ResultConstruction::group(), false); - synchronizeGroupInViewer(aDoc, ModelAPI_ResultBody::group(), false); - synchronizeGroupInViewer(aDoc, ModelAPI_ResultPart::group(), false); - synchronizeGroupInViewer(aDoc, ModelAPI_ResultGroup::group(), false); + foreach(DocumentPtr aDoc, aDocs) { + 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, +//****************************************************** +void XGUI_Workshop::synchronizeGroupInViewer(const DocumentPtr& theDoc, + const std::string& theGroup, bool theUpdateViewer) { ObjectPtr aObj; @@ -2025,19 +2603,54 @@ void XGUI_Workshop::synchronizeGroupInViewer(const DocumentPtr& theDoc, if (theUpdateViewer) myDisplayer->updateViewer(); } +#endif +//****************************************************** void XGUI_Workshop::highlightResults(const QObjectPtrList& theObjects) { FeaturePtr aFeature; QObjectPtrList aSelList = theObjects; - std::list aResList; + QObjectPtrList aNewSel; + bool aHasHidden = false; foreach(ObjectPtr aObj, theObjects) { aFeature = std::dynamic_pointer_cast(aObj); if (aFeature.get()) { - aResList = aFeature->results(); + std::list aResults; + ModelAPI_Tools::allResults(aFeature, aResults); std::list >::const_iterator aIt; - for(aIt = aResList.cbegin(); aIt != aResList.cend(); aIt++) { + for(aIt = aResults.cbegin(); aIt != aResults.cend(); aIt++) { + aHasHidden |= (*aIt)->isConcealed(); aSelList.append(*aIt); + aNewSel.append(*aIt); + } + } + } + if (aSelList.count() > theObjects.count()) { + // if something was found + bool aBlocked = objectBrowser()->blockSignals(true); + objectBrowser()->setObjectsSelected(aSelList); + objectBrowser()->blockSignals(aBlocked); + objectBrowser()->ensureVisible(aNewSel.first()); + } + 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; + QObjectPtrList aNewSel; + 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); + aNewSel.append(aFeature); } } } @@ -2046,5 +2659,79 @@ void XGUI_Workshop::highlightResults(const QObjectPtrList& theObjects) bool aBlocked = objectBrowser()->blockSignals(true); objectBrowser()->setObjectsSelected(aSelList); objectBrowser()->blockSignals(aBlocked); + objectBrowser()->ensureVisible(aNewSel.first()); } } + +void XGUI_Workshop::insertFeatureFolder() +{ + QObjectPtrList aObjects = mySelector->selection()->selectedObjects(); + if (aObjects.isEmpty()) + return; + ObjectPtr aObj = aObjects.first(); + FeaturePtr aFeature = std::dynamic_pointer_cast(aObj); + if (aFeature.get() == NULL) + return; + SessionPtr aMgr = ModelAPI_Session::get(); + DocumentPtr aDoc = aMgr->activeDocument(); + + QString aDescription = contextMenuMgr()->action("INSERT_FOLDER_CMD")->text(); + + aMgr->startOperation(aDescription.toStdString()); + aDoc->addFolder(aFeature); + aMgr->finishOperation(); + + updateCommandStatus(); +} + + +void XGUI_Workshop::insertToFolder(bool isBefore) +{ + std::list aFeatures = mySelector->getSelectedFeatures(); + if (aFeatures.empty()) + return; + + SessionPtr aMgr = ModelAPI_Session::get(); + DocumentPtr aDoc = aMgr->activeDocument(); + + FolderPtr aFolder = isBefore? aDoc->findFolderAbove(aFeatures): + aDoc->findFolderBelow(aFeatures); + if (!aFolder.get()) + return; + + QString aDescription = contextMenuMgr()->action( + isBefore ? "ADD_TO_FOLDER_BEFORE_CMD" : "ADD_TO_FOLDER_AFTER_CMD")->text(); + + QMap aStates = myObjectBrowser->getFoldersState(aDoc); + + aMgr->startOperation(aDescription.toStdString()); + aDoc->moveToFolder(aFeatures, aFolder); + aMgr->finishOperation(); + + myObjectBrowser->setFoldersState(aStates); + + updateCommandStatus(); +} + +void XGUI_Workshop::moveOutFolder(bool isBefore) +{ + std::list aFeatures = mySelector->getSelectedFeatures(); + if (aFeatures.empty()) + return; + + SessionPtr aMgr = ModelAPI_Session::get(); + DocumentPtr aDoc = aMgr->activeDocument(); + + QString aDescription = contextMenuMgr()->action( + isBefore ? "ADD_OUT_FOLDER_BEFORE_CMD" : "ADD_OUT_FOLDER_AFTER_CMD")->text(); + + QMap aStates = myObjectBrowser->getFoldersState(aDoc); + + aMgr->startOperation(aDescription.toStdString()); + aDoc->removeFromFolder(aFeatures, isBefore); + aMgr->finishOperation(); + + myObjectBrowser->setFoldersState(aStates); + + updateCommandStatus(); +}