X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FXGUI%2FXGUI_Workshop.cpp;h=ded693fcf6894aace0670d1b8a44ae95c3594fae;hb=053bed33433b464fc9dc4f876310cb7b344b3031;hp=5a856925ccd2f0f173e9bfea3fcc753c269806ec;hpb=efaa3e56c591f0b6a0e018cc91027ff5f82b2438;p=modules%2Fshaper.git diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 5a856925c..ded693fcf 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -1,13 +1,8 @@ -#include "ModuleBase_IModule.h" -#include "XGUI_Constants.h" -#include "XGUI_Command.h" -#include "XGUI_MainMenu.h" -#include "XGUI_MainWindow.h" -#include "XGUI_MenuGroupPanel.h" +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +//#include "XGUI_Constants.h" #include "XGUI_Tools.h" -#include "XGUI_Workbench.h" #include "XGUI_Workshop.h" -#include "XGUI_Viewer.h" #include "XGUI_SelectionMgr.h" #include "XGUI_Selection.h" #include "XGUI_ObjectsBrowser.h" @@ -20,8 +15,19 @@ #include "XGUI_PropertyPanel.h" #include "XGUI_ContextMenuMgr.h" #include "XGUI_ModuleConnector.h" -#include "XGUI_Preferences.h" #include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include #include #include @@ -33,7 +39,7 @@ #include #include -#include +//#include #include #include @@ -46,11 +52,14 @@ #include #include #include +#include #include #include #include #include +#include +#include #include #include @@ -61,6 +70,9 @@ #include #include #include +#include +#include +#include #ifdef _DEBUG #include @@ -75,12 +87,41 @@ QMap XGUI_Workshop::myIcons; -QString XGUI_Workshop::featureIcon(const std::string& theId) + +QIcon XGUI_Workshop::featureIcon(const FeaturePtr& theFeature) { - QString aId(theId.c_str()); - if (myIcons.contains(aId)) - return myIcons[aId]; - return QString(); + QIcon anIcon; + + std::string aKind = theFeature->getKind(); + QString aId(aKind.c_str()); + if (!myIcons.contains(aId)) + return anIcon; + + QString anIconString = myIcons[aId]; + + ModelAPI_ExecState aState = theFeature->data()->execState(); + switch(aState) { + case ModelAPI_StateDone: + case ModelAPI_StateNothing: { + anIcon = QIcon(anIconString); + } + break; + case ModelAPI_StateMustBeUpdated: { + anIcon = ModuleBase_Tools::lighter(anIconString); + } + break; + case ModelAPI_StateExecFailed: { + anIcon = ModuleBase_Tools::composite(":pictures/exec_state_failed.png", anIconString); + } + break; + case ModelAPI_StateInvalidArgument: { + anIcon = ModuleBase_Tools::composite(":pictures/exec_state_invalid_parameters.png", + anIconString); + } + break; + default: break; + } + return anIcon; } XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) @@ -94,7 +135,7 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) myUpdatePrefs(false), myPartActivating(false) { - myMainWindow = mySalomeConnector ? 0 : new XGUI_MainWindow(); + myMainWindow = mySalomeConnector ? 0 : new AppElements_MainWindow(); myDisplayer = new XGUI_Displayer(this); @@ -109,21 +150,22 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) SLOT(onContextMenuCommand(const QString&, bool))); myViewerProxy = new XGUI_ViewerProxy(this); - connect(myViewerProxy, SIGNAL(selectionChanged()), this, SLOT(updateCommandsOnViewSelection())); + connect(myViewerProxy, SIGNAL(selectionChanged()), + myActionsMgr, SLOT(updateOnViewSelection())); myModuleConnector = new XGUI_ModuleConnector(this); connect(myOperationMgr, SIGNAL(operationStarted(ModuleBase_Operation*)), - SLOT(onOperationStarted())); - connect(myOperationMgr, SIGNAL(operationResumed(ModuleBase_Operation*)), SLOT(onOperationStarted())); + 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*)), + SLOT(onOperationCommitted(ModuleBase_Operation*))); + connect(myOperationMgr, SIGNAL(operationAborted(ModuleBase_Operation*)), + SLOT(onOperationAborted(ModuleBase_Operation*))); connect(myMainWindow, SIGNAL(exitKeySequence()), SLOT(onExit())); - // TODO(sbh): It seems that application works properly without update on operationStarted - connect(myOperationMgr, SIGNAL(operationStarted(ModuleBase_Operation*)), - myActionsMgr, SLOT(update())); - connect(myOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)), - myActionsMgr, SLOT(update())); connect(this, SIGNAL(errorOccurred(const QString&)), myErrorDlg, SLOT(addError(const QString&))); } @@ -137,6 +179,10 @@ XGUI_Workshop::~XGUI_Workshop(void) void XGUI_Workshop::startApplication() { initMenu(); + + Config_PropManager::registerProp("Plugins", "default_path", "Default Path", + Config_Prop::Directory, ""); + //Initialize event listening Events_Loop* aLoop = Events_Loop::loop(); aLoop->registerListener(this, Events_Error::errorID()); //!< Listening application errors. @@ -146,20 +192,27 @@ void XGUI_Workshop::startApplication() aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED)); aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED)); - aLoop->registerListener(this, Events_Loop::eventByName("LongOperation")); + aLoop->registerListener(this, Events_LongOp::eventID()); aLoop->registerListener(this, Events_Loop::eventByName(EVENT_PLUGIN_LOADED)); - aLoop->registerListener(this, Events_Loop::eventByName("CurrentDocumentChanged")); + aLoop->registerListener(this, Events_Loop::eventByName(EVENT_DOCUMENT_CHANGED)); aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TOSHOW)); aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TOHIDE)); + aLoop->registerListener(this, Events_Loop::eventByName(EVENT_SELFILTER_LOADED)); registerValidators(); + + // Calling of loadCustomProps before activating module is required + // by Config_PropManger to restore user-defined path to plugins + ModuleBase_Preferences::loadCustomProps(); activateModule(); if (myMainWindow) { myMainWindow->show(); updateCommandStatus(); } - XGUI_Preferences::loadCustomProps(); + onNew(); + + emit applicationStarted(); } //****************************************************** @@ -174,10 +227,14 @@ void XGUI_Workshop::initMenu() QIcon(":pictures/undo.png"), QKeySequence::Undo, false, "MEN_DESK_EDIT"); connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onUndo())); + addHistoryMenu(aAction, SIGNAL(updateUndoHistory(const QList&)), SLOT(onUndo(int))); + aAction = salomeConnector()->addDesktopCommand("REDO_CMD", tr("Redo"), tr("Redo last command"), QIcon(":pictures/redo.png"), QKeySequence::Redo, false, "MEN_DESK_EDIT"); connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onRedo())); + addHistoryMenu(aAction, SIGNAL(updateRedoHistory(const QList&)), SLOT(onRedo(int))); + salomeConnector()->addDesktopMenuSeparator("MEN_DESK_EDIT"); aAction = salomeConnector()->addDesktopCommand("REBUILD_CMD", tr("Rebuild"), tr("Rebuild data objects"), QIcon(":pictures/rebuild.png"), QKeySequence(), @@ -199,22 +256,32 @@ void XGUI_Workshop::initMenu() return; } // File commands group - XGUI_MenuGroupPanel* aGroup = myMainWindow->menuObject()->generalPage(); + AppElements_MenuGroupPanel* aGroup = myMainWindow->menuObject()->generalPage(); - XGUI_Command* aCommand; + AppElements_Command* aCommand; aCommand = aGroup->addFeature("SAVE_CMD", tr("Save..."), tr("Save the document"), QIcon(":pictures/save.png"), QKeySequence::Save); aCommand->connectTo(this, SLOT(onSave())); //aCommand->disable(); - aCommand = aGroup->addFeature("UNDO_CMD", tr("Undo"), tr("Undo last command"), + QString aUndoId = "UNDO_CMD"; + aCommand = aGroup->addFeature(aUndoId, tr("Undo"), tr("Undo last command"), QIcon(":pictures/undo.png"), QKeySequence::Undo); aCommand->connectTo(this, SLOT(onUndo())); + AppElements_Button* aUndoButton = qobject_cast(aGroup->widget(aUndoId)); + addHistoryMenu(aUndoButton, + SIGNAL(updateUndoHistory(const QList&)), + SLOT(onUndo(int))); - aCommand = aGroup->addFeature("REDO_CMD", tr("Redo"), tr("Redo last command"), + QString aRedoId = "REDO_CMD"; + aCommand = aGroup->addFeature(aRedoId, tr("Redo"), tr("Redo last command"), QIcon(":pictures/redo.png"), QKeySequence::Redo); aCommand->connectTo(this, SLOT(onRedo())); + AppElements_Button* aRedoButton = qobject_cast(aGroup->widget(aRedoId)); + addHistoryMenu(aRedoButton, + SIGNAL(updateRedoHistory(const QList&)), + SLOT(onRedo(int))); aCommand = aGroup->addFeature("REBUILD_CMD", tr("Rebuild"), tr("Rebuild data objects"), QIcon(":pictures/rebuild.png"), QKeySequence()); @@ -249,9 +316,9 @@ void XGUI_Workshop::initMenu() } //****************************************************** -XGUI_Workbench* XGUI_Workshop::addWorkbench(const QString& theName) +AppElements_Workbench* XGUI_Workshop::addWorkbench(const QString& theName) { - XGUI_MainMenu* aMenuBar = myMainWindow->menuObject(); + AppElements_MainMenu* aMenuBar = myMainWindow->menuObject(); return aMenuBar->addWorkbench(theName); } @@ -276,7 +343,6 @@ void XGUI_Workshop::processEvent(const std::shared_ptr& theMessa addFeature(aFeatureMsg); } } - // Process creation of Part else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) { std::shared_ptr aUpdMsg = @@ -291,36 +357,29 @@ void XGUI_Workshop::processEvent(const std::shared_ptr& theMessa else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_PLUGIN_LOADED)) { myUpdatePrefs = true; } - // Redisplay feature else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)) { std::shared_ptr aUpdMsg = std::dynamic_pointer_cast(theMessage); onFeatureRedisplayMsg(aUpdMsg); } - //Update property panel on corresponding message. If there is no current operation (no //property panel), or received message has different feature to the current - do nothing. else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) { std::shared_ptr anUpdateMsg = std::dynamic_pointer_cast(theMessage); onFeatureUpdatedMsg(anUpdateMsg); - } - - else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) { + } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) { std::shared_ptr aDelMsg = std::dynamic_pointer_cast(theMessage); onObjectDeletedMsg(aDelMsg); - } - - else if (theMessage->eventID() == Events_LongOp::eventID()) { - if (Events_LongOp::isPerformed()) + } else if (theMessage->eventID() == Events_LongOp::eventID()) { + if (Events_LongOp::isPerformed()) { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - else + } else { QApplication::restoreOverrideCursor(); - } - - else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TOSHOW)) { + } + } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TOSHOW)) { std::shared_ptr anUpdateMsg = std::dynamic_pointer_cast(theMessage); const std::set& aObjList = anUpdateMsg->objects(); @@ -329,9 +388,7 @@ void XGUI_Workshop::processEvent(const std::shared_ptr& theMessa for (aIt = aObjList.cbegin(); aIt != aObjList.cend(); ++aIt) aList.append(*aIt); showObjects(aList, true); - } - - else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TOHIDE)) { + } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TOHIDE)) { std::shared_ptr anUpdateMsg = std::dynamic_pointer_cast(theMessage); const std::set& aObjList = anUpdateMsg->objects(); @@ -341,7 +398,6 @@ void XGUI_Workshop::processEvent(const std::shared_ptr& theMessa aList.append(*aIt); showObjects(aList, false); } - //An operation passed by message. Start it, process and commit. else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OPERATION_LAUNCHED)) { std::shared_ptr aPartSetMsg = @@ -356,8 +412,7 @@ void XGUI_Workshop::processEvent(const std::shared_ptr& theMessa updateCommandStatus(); } } - } - else if (theMessage->eventID() == Events_Loop::loop()->eventByName("CurrentDocumentChanged")) { + } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) { myActionsMgr->update(); // Find and Activate active part if (myPartActivating) @@ -380,7 +435,21 @@ void XGUI_Workshop::processEvent(const std::shared_ptr& theMessa // If not found then activate global document activatePart(ResultPartPtr()); - } else { + } + else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_SELFILTER_LOADED)) { + std::shared_ptr aMsg = + std::dynamic_pointer_cast(theMessage); + if (aMsg) { + ModuleBase_FilterFactory* aFactory = moduleConnector()->selectionFilters(); + if (!aMsg->attributeId().empty()) { + aFactory->assignFilter(aMsg->selectionFilterId(), aMsg->featureId(), aMsg->attributeId(), + aMsg->parameters()); + } + } + } + + + else { //Show error dialog if error message received. std::shared_ptr anAppError = std::dynamic_pointer_cast(theMessage); if (anAppError) { @@ -394,6 +463,11 @@ void XGUI_Workshop::processEvent(const std::shared_ptr& theMessa } } +//****************************************************** +QMainWindow* XGUI_Workshop::desktop() const +{ + return isSalomeMode() ? salomeConnector()->desktop() : myMainWindow; +} //****************************************************** void XGUI_Workshop::onStartWaiting() @@ -430,6 +504,7 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptr::const_iterator aIt; for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { ObjectPtr aObj = (*aIt); + bool aHide = !aObj->data() || !aObj->data()->isValid(); if (!aHide) { // check that this is not hidden result ResultPtr aRes = std::dynamic_pointer_cast(aObj); @@ -439,18 +514,18 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptrerase(aObj, false); else { if (myDisplayer->isVisible(aObj)) { - myDisplayer->display(aObj, false); // In order to update presentation + displayObject(aObj); // In order to update presentation if (myOperationMgr->hasOperation()) { ModuleBase_Operation* aOperation = myOperationMgr->currentOperation(); - if (aOperation->hasObject(aObj) && myDisplayer->isActive(aObj)) + if (!aOperation->isEditOperation() && + aOperation->hasObject(aObj) && myDisplayer->isActive(aObj)) myDisplayer->deactivate(aObj); } } else { if (myOperationMgr->hasOperation()) { ModuleBase_Operation* aOperation = myOperationMgr->currentOperation(); - // Display only current operation results if operation has preview - if (aOperation->hasObject(aObj)/* && aOperation->hasPreview()*/) { - myDisplayer->display(aObj, false); + if (myModule->canDisplayObject(aObj)) { + displayObject(aObj); // Deactivate object of current operation from selection if (myDisplayer->isActive(aObj)) myDisplayer->deactivate(aObj); @@ -471,17 +546,15 @@ void XGUI_Workshop::onFeatureCreatedMsg(const std::shared_ptr(*aIt); if (aPart) { aHasPart = true; // If a feature is created from the aplication's python console // it doesn't stored in the operation mgr and doesn't displayed - } else if (myOperationMgr->hasOperation()) { - ModuleBase_Operation* aOperation = myOperationMgr->currentOperation(); - if (aOperation->hasObject(*aIt)) { // Display only current operation results - myDisplayer->display(*aIt, false); - isDisplayed = true; - } + } else if (myModule->canDisplayObject(*aIt)) { + displayObject(*aIt); + isDisplayed = true; } } if (myObjectBrowser) @@ -502,73 +575,95 @@ void XGUI_Workshop::onObjectDeletedMsg(const std::shared_ptrcurrentOperation(); - if (this->isSalomeMode()) - aOperation->setNestedFeatures(mySalomeConnector->nestedActions(aOperation->id())); - else - aOperation->setNestedFeatures(myActionsMgr->nestedCommands(aOperation->id())); - - if (aOperation->getDescription()->hasXmlRepresentation()) { //!< No need for property panel - connectWithOperation(aOperation); - - showPropertyPanel(); - QString aXmlRepr = aOperation->getDescription()->xmlRepresentation(); - ModuleBase_WidgetFactory aFactory = ModuleBase_WidgetFactory(aXmlRepr.toStdString(), - myModuleConnector); - - myPropertyPanel->cleanContent(); - aFactory.createWidget(myPropertyPanel->contentWidget()); - ModuleBase_Tools::zeroMargins(myPropertyPanel->contentWidget()); - - QList aWidgets = aFactory.getModelWidgets(); - foreach (ModuleBase_ModelWidget* aWidget, aWidgets) { - aWidget->setFeature(aOperation->feature()); - aWidget->enableFocusProcessing(); - QObject::connect(aWidget, SIGNAL(valuesChanged()), this, SLOT(onWidgetValuesChanged())); - // Init default values - if (!aOperation->isEditOperation() && !aWidget->isComputedDefault()) { - aWidget->storeValue(); - } - } + setNestedFeatures(theOperation); - myPropertyPanel->setModelWidgets(aWidgets); - aOperation->setPropertyPanel(myPropertyPanel); - // Do not activate widgets by default if the current operation is editing operation - // Because we don't know which widget is going to be edited. - if ((!aOperation->isEditOperation())) { - if (!aOperation->activateByPreselection()) - myPropertyPanel->activateNextWidget(NULL); - } - // Set final definitions if they are necessary - myModule->propertyPanelDefined(aOperation); + if (theOperation->getDescription()->hasXmlRepresentation()) { //!< No need for property panel + connectWithOperation(theOperation); + setPropertyPanel(theOperation); + } + updateCommandStatus(); - // Widget activation (from the previous method) may commit the current operation - // if pre-selection is enougth for it. So we shouldn't update prop panel's title - if(myOperationMgr->isCurrentOperation(aOperation)) { - myPropertyPanel->setWindowTitle(aOperation->getDescription()->description()); - } + myModule->operationStarted(theOperation); +} + +//****************************************************** +void XGUI_Workshop::onOperationResumed(ModuleBase_Operation* theOperation) +{ + setNestedFeatures(theOperation); + + if (theOperation->getDescription()->hasXmlRepresentation()) { //!< No need for property panel + // connectWithOperation(theOperation); already connected + setPropertyPanel(theOperation); } updateCommandStatus(); + + myModule->operationResumed(theOperation); } + //****************************************************** void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation) { + ModuleBase_ISelection* aSel = mySelector->selection(); + QObjectPtrList aObj = aSel->selectedPresentations(); //!< No need for property panel updateCommandStatus(); hidePropertyPanel(); myPropertyPanel->cleanContent(); - // Activate objects created by current operation - FeaturePtr aFeature = theOperation->feature(); - myDisplayer->activate(aFeature); - const std::list& aResults = aFeature->results(); - std::list::const_iterator aIt; - for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) { - myDisplayer->activate(*aIt); + // Activate objects created by current operation + // in order to clean selection modes + QIntList aModes; + myDisplayer->activateObjects(aModes); + myModule->operationStopped(theOperation); +} + + +void XGUI_Workshop::onOperationCommitted(ModuleBase_Operation* theOperation) +{ + myModule->operationCommitted(theOperation); +} + +void XGUI_Workshop::onOperationAborted(ModuleBase_Operation* theOperation) +{ + myModule->operationAborted(theOperation); +} + +void XGUI_Workshop::setNestedFeatures(ModuleBase_Operation* theOperation) +{ + if (this->isSalomeMode()) + theOperation->setNestedFeatures(mySalomeConnector->nestedActions(theOperation->id())); + else + theOperation->setNestedFeatures(myActionsMgr->nestedCommands(theOperation->id())); +} + +void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* theOperation) +{ + showPropertyPanel(); + QString aXmlRepr = theOperation->getDescription()->xmlRepresentation(); + ModuleBase_WidgetFactory aFactory = ModuleBase_WidgetFactory(aXmlRepr.toStdString(), + myModuleConnector); + + myPropertyPanel->cleanContent(); + aFactory.createWidget(myPropertyPanel->contentWidget()); + ModuleBase_Tools::zeroMargins(myPropertyPanel->contentWidget()); + + QList aWidgets = aFactory.getModelWidgets(); + foreach (ModuleBase_ModelWidget* aWidget, aWidgets) { + bool isStoreValue = !theOperation->isEditOperation() && + aWidget->isValueDefault() && !aWidget->isComputedDefault(); + aWidget->setFeature(theOperation->feature(), isStoreValue); + aWidget->enableFocusProcessing(); } + + myPropertyPanel->setModelWidgets(aWidgets); + theOperation->setPropertyPanel(myPropertyPanel); + + myModule->propertyPanelDefined(theOperation); + + myPropertyPanel->setWindowTitle(theOperation->getDescription()->description()); } bool XGUI_Workshop::event(QEvent * theEvent) @@ -593,52 +688,61 @@ void XGUI_Workshop::addFeature(const std::shared_ptr& the #endif return; } + ActionInfo aFeatureInfo; + aFeatureInfo.initFrom(theMessage); // Remember features icons - myIcons[QString::fromStdString(theMessage->id())] = QString::fromStdString(theMessage->icon()); + myIcons[QString::fromStdString(theMessage->id())] = aFeatureInfo.iconFile; - //Find or create Workbench QString aWchName = QString::fromStdString(theMessage->workbenchId()); - QString aNestedFeatures = QString::fromStdString(theMessage->nestedFeatures()); - bool isUsePropPanel = theMessage->isUseInput(); - QString aFeatureId = QString::fromStdString(theMessage->id()); + QStringList aNestedFeatures = + QString::fromStdString(theMessage->nestedFeatures()).split(" ", QString::SkipEmptyParts); + QString aDocKind = QString::fromStdString(theMessage->documentKind()); if (isSalomeMode()) { - QAction* aAction = salomeConnector()->addFeature(aWchName, aFeatureId, - QString::fromStdString(theMessage->text()), - QString::fromStdString(theMessage->tooltip()), - QIcon(theMessage->icon().c_str()), - QKeySequence(), - isUsePropPanel); - salomeConnector()->setNestedActions(aFeatureId, aNestedFeatures.split(" ", QString::SkipEmptyParts)); - salomeConnector()->setDocumentKind(aFeatureId, QString::fromStdString(theMessage->documentKind())); + QAction* aAction = salomeConnector()->addFeature(aWchName, aFeatureInfo); + salomeConnector()->setNestedActions(aFeatureInfo.id, aNestedFeatures); + salomeConnector()->setDocumentKind(aFeatureInfo.id, aDocKind); myActionsMgr->addCommand(aAction); myModule->actionCreated(aAction); } else { - - XGUI_MainMenu* aMenuBar = myMainWindow->menuObject(); - XGUI_Workbench* aPage = aMenuBar->findWorkbench(aWchName); + //Find or create Workbench + AppElements_MainMenu* aMenuBar = myMainWindow->menuObject(); + AppElements_Workbench* aPage = aMenuBar->findWorkbench(aWchName); if (!aPage) { aPage = addWorkbench(aWchName); } //Find or create Group QString aGroupName = QString::fromStdString(theMessage->groupId()); - XGUI_MenuGroupPanel* aGroup = aPage->findGroup(aGroupName); + AppElements_MenuGroupPanel* aGroup = aPage->findGroup(aGroupName); if (!aGroup) { aGroup = aPage->addGroup(aGroupName); } - QString aDocKind = QString::fromStdString(theMessage->documentKind()); // Check if hotkey sequence is already defined: - QKeySequence aHotKey = myActionsMgr->registerShortcut( - QString::fromStdString(theMessage->keysequence())); + QKeySequence aHotKey = myActionsMgr->registerShortcut(aFeatureInfo.shortcut); + if(aHotKey != aFeatureInfo.shortcut) { + aFeatureInfo.shortcut = aHotKey; + } // Create feature... - XGUI_Command* aCommand = aGroup->addFeature(aFeatureId, - QString::fromStdString(theMessage->text()), - QString::fromStdString(theMessage->tooltip()), - QIcon(theMessage->icon().c_str()), - aDocKind, - aHotKey, - isUsePropPanel); - aCommand->setNestedCommands(aNestedFeatures.split(" ", QString::SkipEmptyParts)); + AppElements_Command* aCommand = aGroup->addFeature(aFeatureInfo, + aDocKind, + aNestedFeatures); + // Enrich created button with accept/abort buttons if necessary + AppElements_Button* aButton = aCommand->button(); + if (aButton->isColumnButton()) { + QString aNestedActions = QString::fromStdString(theMessage->actionsWhenNested()); + QList anActList; + if (aNestedActions.contains("accept")) { + QAction* anAction = myActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptAll, aButton); + connect(anAction, SIGNAL(triggered()), myOperationMgr, SLOT(commitAllOperations())); + anActList << anAction; + } + if (aNestedActions.contains("abort")) { + QAction* anAction = myActionsMgr->operationStateAction(XGUI_ActionsMgr::AbortAll, aButton); + connect(anAction, SIGNAL(triggered()), myOperationMgr, SLOT(abortAllOperations())); + anActList << anAction; + } + aButton->setAdditionalButtons(anActList); + } myActionsMgr->addCommand(aCommand); myModule->actionCreated(aCommand); } @@ -655,7 +759,7 @@ void XGUI_Workshop::connectWithOperation(ModuleBase_Operation* theOperation) if (isSalomeMode()) { aCommand = salomeConnector()->command(theOperation->getDescription()->operationId()); } else { - XGUI_MainMenu* aMenu = myMainWindow->menuObject(); + AppElements_MainMenu* aMenu = myMainWindow->menuObject(); FeaturePtr aFeature = theOperation->feature(); if(aFeature) aCommand = aMenu->feature(QString::fromStdString(aFeature->getKind())); @@ -815,24 +919,28 @@ bool XGUI_Workshop::onSaveAs() } //****************************************************** -void XGUI_Workshop::onUndo() +void XGUI_Workshop::onUndo(int theTimes) { objectBrowser()->treeView()->setCurrentIndex(QModelIndex()); SessionPtr aMgr = ModelAPI_Session::get(); if (aMgr->isOperation()) operationMgr()->onAbortOperation(); - aMgr->undo(); + for (int i = 0; i < theTimes; ++i) { + aMgr->undo(); + } updateCommandStatus(); } //****************************************************** -void XGUI_Workshop::onRedo() +void XGUI_Workshop::onRedo(int theTimes) { objectBrowser()->treeView()->setCurrentIndex(QModelIndex()); SessionPtr aMgr = ModelAPI_Session::get(); if (aMgr->isOperation()) operationMgr()->onAbortOperation(); - aMgr->redo(); + for (int i = 0; i < theTimes; ++i) { + aMgr->redo(); + } updateCommandStatus(); } @@ -842,7 +950,7 @@ void XGUI_Workshop::onRebuild() SessionPtr aMgr = ModelAPI_Session::get(); bool aWasOperation = aMgr->isOperation(); // keep this value if (!aWasOperation) { - aMgr->startOperation(); + aMgr->startOperation("Rebuild"); } static const Events_ID aRebuildEvent = Events_Loop::loop()->eventByName("Rebuild"); Events_Loop::loop()->send(std::shared_ptr( @@ -855,17 +963,17 @@ void XGUI_Workshop::onRebuild() //****************************************************** void XGUI_Workshop::onPreferences() { - XGUI_Prefs aModif; - XGUI_Preferences::editPreferences(aModif); + ModuleBase_Prefs aModif; + ModuleBase_Preferences::editPreferences(aModif); if (aModif.size() > 0) { QString aSection; - foreach (XGUI_Pref aPref, aModif) + foreach (ModuleBase_Pref aPref, aModif) { aSection = aPref.first; - if (aSection == XGUI_Preferences::VIEWER_SECTION) { + if (aSection == ModuleBase_Preferences::VIEWER_SECTION) { if (!isSalomeMode()) myMainWindow->viewer()->updateFromResources(); - } else if (aSection == XGUI_Preferences::MENU_SECTION) { + } else if (aSection == ModuleBase_Preferences::MENU_SECTION) { if (!isSalomeMode()) myMainWindow->menuObject()->updateFromResources(); } @@ -952,8 +1060,8 @@ void XGUI_Workshop::updateCommandStatus() if (isSalomeMode()) { // update commands in SALOME mode aCommands = salomeConnector()->commandList(); } else { - XGUI_MainMenu* aMenuBar = myMainWindow->menuObject(); - foreach (XGUI_Command* aCmd, aMenuBar->features()) + AppElements_MainMenu* aMenuBar = myMainWindow->menuObject(); + foreach (AppElements_Command* aCmd, aMenuBar->features()) aCommands.append(aCmd); } SessionPtr aMgr = ModelAPI_Session::get(); @@ -969,8 +1077,10 @@ void XGUI_Workshop::updateCommandStatus() // Enable all commands aCmd->setEnabled(true); } - aUndoCmd->setEnabled(aMgr->canUndo() && !aMgr->isOperation()); - aRedoCmd->setEnabled(aMgr->canRedo() && !aMgr->isOperation()); + + aUndoCmd->setEnabled(myModule->canUndo()); + aRedoCmd->setEnabled(myModule->canRedo()); + updateHistory(); } else { foreach(QAction* aCmd, aCommands) { QString aId = aCmd->data().toString(); @@ -983,22 +1093,18 @@ void XGUI_Workshop::updateCommandStatus() } } myActionsMgr->update(); + emit commandStatusUpdated(); } -//****************************************************** -QList XGUI_Workshop::getModuleCommands() const +void XGUI_Workshop::updateHistory() { - QList aCommands; - if (isSalomeMode()) { // update commands in SALOME mode - aCommands = salomeConnector()->commandList(); - } else { - XGUI_MainMenu* aMenuBar = myMainWindow->menuObject(); - foreach(XGUI_Command* aCmd, aMenuBar->features()) - { - aCommands.append(aCmd); - } - } - return aCommands; + std::list aUndoList = ModelAPI_Session::get()->undoList(); + QList aUndoRes = processHistoryList(aUndoList); + emit updateUndoHistory(aUndoRes); + + std::list aRedoList = ModelAPI_Session::get()->redoList(); + QList aRedoRes = processHistoryList(aRedoList); + emit updateRedoHistory(aRedoRes); } //****************************************************** @@ -1029,21 +1135,26 @@ void XGUI_Workshop::createDockWidgets() QDockWidget* aObjDock = createObjectBrowser(aDesktop); aDesktop->addDockWidget(Qt::LeftDockWidgetArea, aObjDock); myPropertyPanel = new XGUI_PropertyPanel(aDesktop); + myPropertyPanel->setupActions(myActionsMgr); myPropertyPanel->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); aDesktop->addDockWidget(Qt::LeftDockWidgetArea, myPropertyPanel); - hidePropertyPanel(); //tabifyDockWidget(aObjDock, myPropertyPanel); myPropertyPanel->installEventFilter(myOperationMgr); - QPushButton* aOkBtn = myPropertyPanel->findChild(XGUI::PROP_PANEL_OK); - connect(aOkBtn, SIGNAL(clicked()), myOperationMgr, SLOT(onCommitOperation())); - QPushButton* aCancelBtn = myPropertyPanel->findChild(XGUI::PROP_PANEL_CANCEL); - connect(aCancelBtn, SIGNAL(clicked()), myOperationMgr, SLOT(onAbortOperation())); - connect(myPropertyPanel, SIGNAL(keyReleased(QKeyEvent*)), myOperationMgr, - SLOT(onKeyReleased(QKeyEvent*))); - connect(myOperationMgr, SIGNAL(operationValidated(bool)), myPropertyPanel, - SLOT(setAcceptEnabled(bool))); + QAction* aOkAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Accept); + connect(aOkAct, SIGNAL(triggered()), myOperationMgr, SLOT(onCommitOperation())); + QAction* aCancelAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Abort); + connect(aCancelAct, SIGNAL(triggered()), myOperationMgr, SLOT(onAbortOperation())); + connect(myPropertyPanel, SIGNAL(noMoreWidgets()), myModule, SLOT(onNoMoreWidgets())); + connect(myPropertyPanel, SIGNAL(keyReleased(QKeyEvent*)), + myOperationMgr, SLOT(onKeyReleased(QKeyEvent*))); + connect(myOperationMgr, SIGNAL(validationStateChanged(bool)), + aOkAct, SLOT(setEnabled(bool))); + QAction* aAcceptAllAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptAll); + connect(myOperationMgr, SIGNAL(nestedStateChanged(bool)), + aAcceptAllAct, SLOT(setEnabled(bool))); } @@ -1051,7 +1162,7 @@ void XGUI_Workshop::createDockWidgets() void XGUI_Workshop::showPropertyPanel() { QAction* aViewAct = myPropertyPanel->toggleViewAction(); - //setEnabled(true); myPropertyPanel->show(); myPropertyPanel->raise(); @@ -1061,7 +1172,7 @@ void XGUI_Workshop::showPropertyPanel() void XGUI_Workshop::hidePropertyPanel() { QAction* aViewAct = myPropertyPanel->toggleViewAction(); - //setEnabled(false); myPropertyPanel->hide(); } @@ -1148,27 +1259,6 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked) } } -//************************************************************** -void XGUI_Workshop::onWidgetValuesChanged() -{ - ModuleBase_Operation* anOperation = myOperationMgr->currentOperation(); - FeaturePtr aFeature = anOperation->feature(); - - ModuleBase_ModelWidget* aSenderWidget = dynamic_cast(sender()); - //if (aCustom) - // aCustom->storeValue(aFeature); - - const QList& aWidgets = myPropertyPanel->modelWidgets(); - QList::const_iterator anIt = aWidgets.begin(), aLast = aWidgets.end(); - for (; anIt != aLast; anIt++) { - ModuleBase_ModelWidget* aCustom = *anIt; - if (aCustom && (/*!aCustom->isInitialized(aFeature) ||*/aCustom == aSenderWidget)) { - //aCustom->storeValue(aFeature); - aCustom->storeValue(); - } - } -} - //************************************************************** void XGUI_Workshop::activatePart(ResultPartPtr theFeature) { @@ -1180,50 +1270,101 @@ void XGUI_Workshop::activatePart(ResultPartPtr theFeature) myObjectBrowser->activatePart(theFeature); myPartActivating = false; } + updateCommandStatus(); } //************************************************************** -void XGUI_Workshop::activateLastPart() -{ - SessionPtr aMgr = ModelAPI_Session::get(); - DocumentPtr aDoc = aMgr->moduleDocument(); - std::string aGrpName = ModelAPI_ResultPart::group(); - ObjectPtr aLastPart = aDoc->object(aGrpName, aDoc->size(aGrpName) - 1); - ResultPartPtr aPart = std::dynamic_pointer_cast(aLastPart); - if (aPart) { - activatePart(aPart); - } -} +//void XGUI_Workshop::activateLastPart() +//{ +// SessionPtr aMgr = ModelAPI_Session::get(); +// DocumentPtr aDoc = aMgr->moduleDocument(); +// std::string aGrpName = ModelAPI_ResultPart::group(); +// ObjectPtr aLastPart = aDoc->object(aGrpName, aDoc->size(aGrpName) - 1); +// ResultPartPtr aPart = std::dynamic_pointer_cast(aLastPart); +// if (aPart) { +// activatePart(aPart); +// } +//} //************************************************************** void XGUI_Workshop::deleteObjects(const QObjectPtrList& theList) { QMainWindow* aDesktop = isSalomeMode() ? salomeConnector()->desktop() : myMainWindow; - QMessageBox::StandardButton aRes = QMessageBox::warning( - aDesktop, tr("Delete features"), tr("Seleted features will be deleted. Continue?"), - QMessageBox::No | QMessageBox::Yes, QMessageBox::No); - // ToDo: definbe deleting method - if (aRes == QMessageBox::Yes) { - SessionPtr aMgr = ModelAPI_Session::get(); - aMgr->startOperation(); - foreach (ObjectPtr aObj, theList) - { - ResultPartPtr aPart = std::dynamic_pointer_cast(aObj); - if (aPart) { - DocumentPtr aDoc = aPart->document(); - if (aDoc == aMgr->activeDocument()) { - aDoc->close(); - } - //aMgr->moduleDocument()->removeFeature(aPart->owner()); - } else { - FeaturePtr aFeature = std::dynamic_pointer_cast(aObj); - if (aFeature) - aObj->document()->removeFeature(aFeature); + + std::set aRefFeatures; + foreach (ObjectPtr aObj, theList) + { + ResultPartPtr aPart = std::dynamic_pointer_cast(aObj); + if (aPart) { + // TODO: check for what there is this condition. It is placed here historicaly because + // ther is this condition during remove features. + } else { + FeaturePtr aFeature = std::dynamic_pointer_cast(aObj); + if (aFeature.get() != NULL) { + aObj->document()->refsToFeature(aFeature, aRefFeatures, false); } } - myDisplayer->updateViewer(); - aMgr->finishOperation(); } + + if (!aRefFeatures.empty()) { + QStringList aRefNames; + std::set::const_iterator anIt = aRefFeatures.begin(), + aLast = aRefFeatures.end(); + for (; anIt != aLast; anIt++) { + FeaturePtr aFeature = (*anIt); + std::string aFName = aFeature->data()->name().c_str(); + std::string aName = (*anIt)->name().c_str(); + aRefNames.append((*anIt)->name().c_str()); + } + QString aNames = aRefNames.join(", "); + + QMessageBox::StandardButton aRes = QMessageBox::warning( + aDesktop, tr("Delete features"), + QString(tr("Selected features are used in the following features: %1.\ +These features will be deleted also. Would you like to continue?")).arg(aNames), + QMessageBox::No | QMessageBox::Yes, QMessageBox::No); + if (aRes != QMessageBox::Yes) + return; + } + + SessionPtr aMgr = ModelAPI_Session::get(); + QString aDescription = tr("Delete %1"); + QStringList aObjectNames; + foreach (ObjectPtr aObj, theList) { + if (!aObj->data().get()) + continue; + aObjectNames << QString::fromStdString(aObj->data()->name()); + } + aDescription = aDescription.arg(aObjectNames.join(", ")); + aMgr->startOperation(aDescription.toStdString()); + std::set::const_iterator anIt = aRefFeatures.begin(), + aLast = aRefFeatures.end(); + for (; anIt != aLast; anIt++) { + FeaturePtr aRefFeature = (*anIt); + DocumentPtr aDoc = aRefFeature->document(); + aDoc->removeFeature(aRefFeature); + } + + + foreach (ObjectPtr aObj, theList) + { + DocumentPtr aDoc = aObj->document(); + ResultPartPtr aPart = std::dynamic_pointer_cast(aObj); + if (aPart) { + if (aDoc == aMgr->activeDocument()) { + aDoc->close(); + } + } else { + FeaturePtr aFeature = std::dynamic_pointer_cast(aObj); + if (aFeature) { + aDoc->removeFeature(aFeature); + } + } + } + + myDisplayer->updateViewer(); + aMgr->finishOperation(); + updateCommandStatus(); } //************************************************************** @@ -1231,13 +1372,10 @@ void XGUI_Workshop::showObjects(const QObjectPtrList& theList, bool isVisible) { foreach (ObjectPtr aObj, theList) { - ResultPtr aRes = std::dynamic_pointer_cast(aObj); - if (aRes) { - if (isVisible) { - myDisplayer->display(aRes, false); - } else { - myDisplayer->erase(aRes, false); - } + if (isVisible) { + displayObject(aObj); + } else { + myDisplayer->erase(aObj, false); } } myDisplayer->updateViewer(); @@ -1246,51 +1384,10 @@ void XGUI_Workshop::showObjects(const QObjectPtrList& theList, bool isVisible) //************************************************************** void XGUI_Workshop::showOnlyObjects(const QObjectPtrList& theList) { - myDisplayer->eraseAll(false); - showObjects(theList, true); + myDisplayer->showOnly(theList); } -//************************************************************** -void XGUI_Workshop::updateCommandsOnViewSelection() -{ - XGUI_Selection* aSelection = mySelector->selection(); - if (aSelection->getSelected().size() == 0) - return; - - // Restrict validators to manage only nested (child) features - // of the current feature i.e. if current feature is Sketch - - // Sketch Features & Constraints can be validated. - QStringList aNestedIds; - if(myOperationMgr->hasOperation()) { - FeaturePtr aFeature = myOperationMgr->currentOperation()->feature(); - if(aFeature) { - aNestedIds << myActionsMgr->nestedCommands(QString::fromStdString(aFeature->getKind())); - } - } - SessionPtr aMgr = ModelAPI_Session::get(); - ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); - QList aActions = getModuleCommands(); - foreach(QAction* aAction, aActions) { - QString aId = aAction->data().toString(); - if(!aNestedIds.contains(aId)) - continue; - std::list aValidators; - std::list > anArguments; - aFactory->validators(aId.toStdString(), aValidators, anArguments); - std::list::iterator aValidator = aValidators.begin(); - for (; aValidator != aValidators.end(); aValidator++) { - if (*aValidator) { - const ModuleBase_SelectionValidator* aSelValidator = - dynamic_cast(*aValidator); - if (aSelValidator) { - aAction->setEnabled(aSelValidator->isValid(aSelection)); - } - } - } - } -} - //************************************************************** void XGUI_Workshop::registerValidators() const { @@ -1325,7 +1422,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++) - myDisplayer->display(theDoc->object(theGroup, i), false); + displayObject(theDoc->object(theGroup, i)); } //************************************************************** @@ -1341,6 +1438,11 @@ void XGUI_Workshop::setDisplayMode(const QObjectPtrList& theList, int theMode) //************************************************************** void XGUI_Workshop::closeDocument() { + ModuleBase_Operation* anOperation = operationMgr()->currentOperation(); + while (anOperation) { + anOperation->abort(); + anOperation = operationMgr()->currentOperation(); + } myDisplayer->closeLocalContexts(); myDisplayer->eraseAll(); objectBrowser()->clearContent(); @@ -1349,3 +1451,51 @@ void XGUI_Workshop::closeDocument() aMgr->closeAll(); objectBrowser()->clearContent(); } + +//************************************************************** +void XGUI_Workshop::displayObject(ObjectPtr theObj) +{ + ResultBodyPtr aBody = std::dynamic_pointer_cast(theObj); + if (aBody.get() != NULL) { + int aNb = myDisplayer->objectsCount(); + myDisplayer->display(theObj, false); + if (aNb == 0) + viewer()->fitAll(); + } else + myDisplayer->display(theObj, false); +} + +void XGUI_Workshop::addHistoryMenu(QObject* theObject, const char* theSignal, const char* theSlot) +{ + XGUI_HistoryMenu* aMenu = NULL; + if (isSalomeMode()) { + QAction* anAction = qobject_cast(theObject); + if (!anAction) + return; + aMenu = new XGUI_HistoryMenu(anAction); + } else { + QToolButton* aButton = qobject_cast(theObject); + aMenu = new XGUI_HistoryMenu(aButton); + } + connect(this, theSignal, aMenu, SLOT(setHistory(const QList&))); + connect(aMenu, SIGNAL(actionSelected(int)), this, theSlot); +} + +QList XGUI_Workshop::processHistoryList(const std::list& theList) const +{ + QList aResult; + std::list::const_iterator it = theList.cbegin(); + for (; it != theList.cend(); it++) { + QString anId = QString::fromStdString(*it); + bool isEditing = anId.endsWith(ModuleBase_Operation::EditSuffix()); + if (isEditing) { + anId.chop(ModuleBase_Operation::EditSuffix().size()); + } + ActionInfo anInfo = myActionsMgr->actionInfoById(anId); + if (isEditing) { + anInfo.text = anInfo.text.prepend("Modify "); + } + aResult << anInfo; + } + return aResult; +}