X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FXGUI%2FXGUI_Workshop.cpp;h=99311b558daec401d533944b8e7841cb295b80a7;hb=9d2e6d9c21e4f16817ca5b572847fe323f6ef32a;hp=2ed8c86f53518e09c160c5ed5b4ae455ed77f916;hpb=46a28bd54e9ce0937d87d305202ab6912c1f5cd2;p=modules%2Fshaper.git diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 2ed8c86f5..646a41bfa 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -11,11 +11,13 @@ #include "XGUI_SalomeConnector.h" #include "XGUI_ActionsMgr.h" #include "XGUI_ErrorDialog.h" +#include "XGUI_ColorDialog.h" #include "XGUI_ViewerProxy.h" #include "XGUI_PropertyPanel.h" #include "XGUI_ContextMenuMgr.h" #include "XGUI_ModuleConnector.h" #include +#include #include #include @@ -23,6 +25,7 @@ #include #include #include +#include #include #include @@ -34,8 +37,11 @@ #include #include #include +#include #include #include +#include +#include //#include @@ -50,7 +56,9 @@ #include #include #include -#include +#include +#include +#include #include #include @@ -68,6 +76,9 @@ #include #include #include +#include +#include +#include #ifdef _DEBUG #include @@ -80,44 +91,9 @@ #include #endif -QMap XGUI_Workshop::myIcons; - - -QIcon XGUI_Workshop::featureIcon(const FeaturePtr& theFeature) -{ - QIcon anIcon; +//#define DEBUG_FEATURE_CREATED +//#define DEBUG_FEATURE_REDISPLAY - 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) : QObject(), @@ -128,7 +104,8 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) myObjectBrowser(0), myDisplayer(0), myUpdatePrefs(false), - myPartActivating(false) + myPartActivating(false), + myIsLoadingData(false) { myMainWindow = mySalomeConnector ? 0 : new AppElements_MainWindow(); @@ -186,14 +163,13 @@ void XGUI_Workshop::startApplication() aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); 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_LongOp::eventID()); aLoop->registerListener(this, Events_Loop::eventByName(EVENT_PLUGIN_LOADED)); - 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)); + aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED)); + aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED)); + registerValidators(); // Calling of loadCustomProps before activating module is required @@ -222,10 +198,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(), @@ -256,13 +236,23 @@ void XGUI_Workshop::initMenu() 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()); @@ -350,34 +340,12 @@ void XGUI_Workshop::processEvent(const std::shared_ptr& theMessa std::shared_ptr anUpdateMsg = std::dynamic_pointer_cast(theMessage); onFeatureUpdatedMsg(anUpdateMsg); - } 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()) { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); } else { QApplication::restoreOverrideCursor(); } - } 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(); - QObjectPtrList aList; - std::set::const_iterator aIt; - 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)) { - std::shared_ptr anUpdateMsg = - std::dynamic_pointer_cast(theMessage); - const std::set& aObjList = anUpdateMsg->objects(); - QObjectPtrList aList; - std::set::const_iterator aIt; - for (aIt = aObjList.cbegin(); aIt != aObjList.cend(); ++aIt) - 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)) { @@ -393,30 +361,7 @@ void XGUI_Workshop::processEvent(const std::shared_ptr& theMessa updateCommandStatus(); } } - } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) { - myActionsMgr->update(); - // Find and Activate active part - if (myPartActivating) - return; - SessionPtr aMgr = ModelAPI_Session::get(); - DocumentPtr aActiveDoc = aMgr->activeDocument(); - DocumentPtr aDoc = aMgr->moduleDocument(); - if (aActiveDoc == aDoc) { - activatePart(ResultPartPtr()); - return; - } - std::string aGrpName = ModelAPI_ResultPart::group(); - for (int i = 0; i < aDoc->size(aGrpName); i++) { - ResultPartPtr aPart = std::dynamic_pointer_cast(aDoc->object(aGrpName, i)); - if (aPart->partDoc() == aActiveDoc) { - activatePart(aPart); // Activate a part which corresponds to active Doc - return; - } - } - // If not found then activate global document - activatePart(ResultPartPtr()); - - } + } else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_SELFILTER_LOADED)) { std::shared_ptr aMsg = std::dynamic_pointer_cast(theMessage); @@ -427,15 +372,19 @@ void XGUI_Workshop::processEvent(const std::shared_ptr& theMessa aMsg->parameters()); } } - } - - - else { + } else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED)) { + // the viewer's update context will not happens until viewer updated is emitted + myDisplayer->enableUpdateViewer(false); + } else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED)) { + // the viewer's update context is unblocked, the viewer's update works + myDisplayer->enableUpdateViewer(true); + } else { //Show error dialog if error message received. std::shared_ptr anAppError = std::dynamic_pointer_cast(theMessage); if (anAppError) { emit errorOccurred(QString::fromLatin1(anAppError->description())); } + return; } if (!isSalomeMode()) { SessionPtr aMgr = ModelAPI_Session::get(); @@ -474,8 +423,8 @@ void XGUI_Workshop::onFeatureUpdatedMsg(const std::shared_ptronValidateOperation(); - if (myObjectBrowser) - myObjectBrowser->processEvent(theMsg); + //if (myObjectBrowser) + // myObjectBrowser->processEvent(theMsg); } //****************************************************** @@ -483,10 +432,22 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptr aObjects = theMsg->objects(); std::set::const_iterator aIt; + +#ifdef DEBUG_FEATURE_REDISPLAY + QStringList anInfo; + for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { + anInfo.append(ModuleBase_Tools::objectInfo((*aIt))); + } + QString anInfoStr = anInfo.join(", "); + qDebug(QString("onFeatureRedisplayMsg: %1, %2").arg(aObjects.size()).arg(anInfoStr).toStdString().c_str()); +#endif + for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { ObjectPtr aObj = (*aIt); - bool aHide = !aObj->data() || !aObj->data()->isValid(); + // Hide the object if it is invalid or concealed one + bool aHide = !aObj->data() || !aObj->data()->isValid() || + aObj->isDisabled() || (!aObj->isDisplayed()); if (!aHide) { // check that this is not hidden result ResultPtr aRes = std::dynamic_pointer_cast(aObj); aHide = aRes && aRes->isConcealed(); @@ -494,19 +455,36 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptrerase(aObj, false); else { - if (myDisplayer->isVisible(aObj)) { - displayObject(aObj); // In order to update presentation - if (myOperationMgr->hasOperation()) { - ModuleBase_Operation* aOperation = myOperationMgr->currentOperation(); - if (!aOperation->isEditOperation() && - aOperation->hasObject(aObj) && myDisplayer->isActive(aObj)) + // Redisplay the visible object or the object of the current operation + bool isVisibleObject = myDisplayer->isVisible(aObj); + #ifdef DEBUG_FEATURE_REDISPLAY + //QString anObjInfo = ModuleBase_Tools::objectInfo((aObj)); + //qDebug(QString("visible=%1 : display= %2").arg(isVisibleObject).arg(anObjInfo).toStdString().c_str()); + #endif + + if (isVisibleObject) { // redisplay visible object + //displayObject(aObj); // In order to update presentation + // in order to avoid the check whether the object can be redisplayed, the exact method + // of redisplay is called. This modification is made in order to have the line is updated + // by creation of a horizontal constraint on the line by preselection + myDisplayer->redisplay(aObj, false); + //if (myOperationMgr->hasOperation()) { + // ModuleBase_Operation* aOperation = myOperationMgr->currentOperation(); + // if (!aOperation->isEditOperation() && + // aOperation->hasObject(aObj) && myDisplayer->isActive(aObj)) + if (!myModule->canActivateSelection(aObj)) { + if (myDisplayer->isActive(aObj)) myDisplayer->deactivate(aObj); } - } else { - if (myOperationMgr->hasOperation()) { - ModuleBase_Operation* aOperation = myOperationMgr->currentOperation(); - if (myModule->canDisplayObject(aObj)) { - displayObject(aObj); + } else { // display object if the current operation has it + if (displayObject(aObj)) { + //ModuleBase_Operation* aOperation = myOperationMgr->currentOperation(); + //if (aOperation && aOperation->hasObject(aObj)) { + if (!myModule->canActivateSelection(aObj)) { + #ifdef DEBUG_FEATURE_REDISPLAY + QString anObjInfo = ModuleBase_Tools::objectInfo((aObj)); + qDebug(QString(" display object = %1").arg(anObjInfo).toStdString().c_str()); + #endif // Deactivate object of current operation from selection if (myDisplayer->isActive(aObj)) myDisplayer->deactivate(aObj); @@ -522,24 +500,37 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptr& theMsg) { std::set aObjects = theMsg->objects(); - std::set::const_iterator aIt; - bool aHasPart = false; - bool isDisplayed = false; +#ifdef DEBUG_FEATURE_CREATED + QStringList anInfo; for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { + anInfo.append(ModuleBase_Tools::objectInfo((*aIt))); + } + QString anInfoStr = anInfo.join(", "); + qDebug(QString("onFeatureCreatedMsg: %1, %2").arg(aObjects.size()).arg(anInfoStr).toStdString().c_str()); +#endif - ResultPartPtr aPart = std::dynamic_pointer_cast(*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 (myModule->canDisplayObject(*aIt)) { - displayObject(*aIt); - isDisplayed = true; + //bool aHasPart = false; + bool isDisplayed = false; + for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { + ObjectPtr anObject = *aIt; + // the validity of the data should be checked here in order to avoid display of the objects, + // which were created, then deleted, but flush for the creation event happens after that + // we should not display disabled objects + bool aHide = !anObject->data() || !anObject->data()->isValid() || + anObject->isDisabled() || (!anObject->isDisplayed()); + if (!aHide) { + // setDisplayed has to be called in order to synchronize internal state of the object + // with list of displayed objects + if (myModule->canDisplayObject(anObject)) { + anObject->setDisplayed(true); + isDisplayed = displayObject(*aIt); + } else + anObject->setDisplayed(false); } } - if (myObjectBrowser) - myObjectBrowser->processEvent(theMsg); + //if (myObjectBrowser) + // myObjectBrowser->processEvent(theMsg); if (isDisplayed) myDisplayer->updateViewer(); //if (aHasPart) { // TODO: Avoid activate last part on loading of document @@ -547,14 +538,6 @@ void XGUI_Workshop::onFeatureCreatedMsg(const std::shared_ptr& theMsg) -{ - if (myObjectBrowser) - myObjectBrowser->processEvent(theMsg); - //std::set aFeatures = theMsg->objects(); -} - //****************************************************** void XGUI_Workshop::onOperationStarted(ModuleBase_Operation* theOperation) { @@ -575,7 +558,7 @@ void XGUI_Workshop::onOperationResumed(ModuleBase_Operation* theOperation) setNestedFeatures(theOperation); if (theOperation->getDescription()->hasXmlRepresentation()) { //!< No need for property panel - connectWithOperation(theOperation); + // connectWithOperation(theOperation); already connected setPropertyPanel(theOperation); } updateCommandStatus(); @@ -596,9 +579,26 @@ void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation) // Activate objects created by current operation // in order to clean selection modes + // the deactivation should be pefromed in the same place, where the mode is activated, + // e.g. activation in the current widget activation, deactivation - in the widget's deactivation + //QIntList aModes; + //myDisplayer->activateObjects(aModes); + myModule->operationStopped(theOperation); + + // if the operation is nested, do not deactivate objects + //if (myOperationMgr->operationsCount() == 0) { + // Activate selection mode for all objects QIntList aModes; + // TODO: check on OCC_6.9.0 + // the module current active modes should not be deactivated in order to save the objects selected + // the deactivate object in the mode of selection leads to the object is deselected in the viewer. + // But, in OCC_6.8.0 this deselection does not happened automatically. It is necessary to call + // ClearOutdatedSelection, but this method has an error in the realization, which should be fixed in + // the OCC_6.9.0 release. Moreother, it is possible that ClearOutdatedSelection will be called inside + // Deactivate method of AIS_InteractiveContext. In this case, we need not call it. + module()->activeSelectionModes(aModes); myDisplayer->activateObjects(aModes); - myModule->operationStopped(theOperation); + //} } @@ -629,17 +629,14 @@ void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* theOperation) myPropertyPanel->cleanContent(); aFactory.createWidget(myPropertyPanel->contentWidget()); - ModuleBase_Tools::zeroMargins(myPropertyPanel->contentWidget()); QList aWidgets = aFactory.getModelWidgets(); foreach (ModuleBase_ModelWidget* aWidget, aWidgets) { - aWidget->setFeature(theOperation->feature()); + bool isStoreValue = !theOperation->isEditOperation() && + !aWidget->getDefaultValue().empty() && + !aWidget->isComputedDefault(); + aWidget->setFeature(theOperation->feature(), isStoreValue); aWidget->enableFocusProcessing(); - QObject::connect(aWidget, SIGNAL(valuesChanged()), this, SLOT(onWidgetValuesChanged())); - // Init default values - if (!theOperation->isEditOperation() && aWidget->isValueDefault() && !aWidget->isComputedDefault()) { - aWidget->storeValue(); - } } myPropertyPanel->setModelWidgets(aWidgets); @@ -672,28 +669,43 @@ void XGUI_Workshop::addFeature(const std::shared_ptr& the #endif return; } - // Remember features icons - myIcons[QString::fromStdString(theMessage->id())] = QString::fromStdString(theMessage->icon()); + ActionInfo aFeatureInfo; + aFeatureInfo.initFrom(theMessage); - //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()); + QList aNestedActList; + bool isColumnButton = !aNestedFeatures.isEmpty(); + if (isColumnButton) { + QString aNestedActions = QString::fromStdString(theMessage->actionsWhenNested()); + if (aNestedActions.contains("accept")) { + QAction* anAction = myActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptAll, NULL); + connect(anAction, SIGNAL(triggered()), myOperationMgr, SLOT(commitAllOperations())); + aNestedActList << anAction; + } + if (aNestedActions.contains("abort")) { + QAction* anAction = myActionsMgr->operationStateAction(XGUI_ActionsMgr::AbortAll, NULL); + connect(anAction, SIGNAL(triggered()), myOperationMgr, SLOT(abortAllOperations())); + aNestedActList << anAction; + } + } + 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; + if (isColumnButton) { + aAction = salomeConnector()->addNestedFeature(aWchName, aFeatureInfo, aNestedActList); + } else { + aAction = salomeConnector()->addFeature(aWchName, aFeatureInfo); + } + salomeConnector()->setNestedActions(aFeatureInfo.id, aNestedFeatures); + salomeConnector()->setDocumentKind(aFeatureInfo.id, aDocKind); myActionsMgr->addCommand(aAction); myModule->actionCreated(aAction); } else { - + //Find or create Workbench AppElements_MainMenu* aMenuBar = myMainWindow->menuObject(); AppElements_Workbench* aPage = aMenuBar->findWorkbench(aWchName); if (!aPage) { @@ -705,19 +717,20 @@ void XGUI_Workshop::addFeature(const std::shared_ptr& the 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... - AppElements_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()) { + aButton->setAdditionalButtons(aNestedActList); + } myActionsMgr->addCommand(aCommand); myModule->actionCreated(aCommand); } @@ -819,7 +832,6 @@ void XGUI_Workshop::onOpen() } else if (anAnswer == QMessageBox::Cancel) { return; } - aSession->closeAll(); myCurrentDir = ""; } @@ -834,10 +846,13 @@ void XGUI_Workshop::onOpen() return; } QApplication::setOverrideCursor(Qt::WaitCursor); + myIsLoadingData = true; + aSession->closeAll(); aSession->load(myCurrentDir.toLatin1().constData()); myObjectBrowser->rebuildDataTree(); - displayAllResults(); + //displayAllResults(); updateCommandStatus(); + myIsLoadingData = false; QApplication::restoreOverrideCursor(); } @@ -894,25 +909,39 @@ 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) { + // 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 + bool isUpdateEnabled = myDisplayer->enableUpdateViewer(false); + 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(); + + // unblock the viewer update functionality and make update on purpose + myDisplayer->enableUpdateViewer(isUpdateEnabled); + myDisplayer->updateViewer(); } //****************************************************** @@ -921,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( @@ -929,6 +958,7 @@ void XGUI_Workshop::onRebuild() if (!aWasOperation) { aMgr->finishOperation(); } + updateCommandStatus(); } //****************************************************** @@ -1019,6 +1049,12 @@ bool XGUI_Workshop::activateModule() myModule = loadModule(moduleName); if (!myModule) return false; + + connect(myDisplayer, SIGNAL(objectDisplayed(ObjectPtr, AISObjectPtr)), + myModule, SLOT(onObjectDisplayed(ObjectPtr, AISObjectPtr))); + connect(myDisplayer, SIGNAL(beforeObjectErase(ObjectPtr, AISObjectPtr)), + myModule, SLOT(onBeforeObjectErase(ObjectPtr, AISObjectPtr))); + myModule->createFeatures(); myActionsMgr->update(); return true; @@ -1048,8 +1084,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(); @@ -1065,6 +1103,17 @@ void XGUI_Workshop::updateCommandStatus() emit commandStatusUpdated(); } +void XGUI_Workshop::updateHistory() +{ + 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); +} + //****************************************************** QDockWidget* XGUI_Workshop::createObjectBrowser(QWidget* theParent) { @@ -1074,8 +1123,8 @@ QDockWidget* XGUI_Workshop::createObjectBrowser(QWidget* theParent) aObjDock->setStyleSheet( "::title { position: relative; padding-left: 5px; text-align: left center }"); myObjectBrowser = new XGUI_ObjectsBrowser(aObjDock); - connect(myObjectBrowser, SIGNAL(activePartChanged(ObjectPtr)), this, - SLOT(changeCurrentDocument(ObjectPtr))); + myObjectBrowser->setDataModel(myModule->dataModel()); + myModule->customizeObjectBrowser(myObjectBrowser); aObjDock->setWidget(myObjectBrowser); myContextMenuMgr->connectObjectBrowser(); @@ -1093,24 +1142,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); - - connect(myPropertyPanel, SIGNAL(noMoreWidgets()), myModule, SLOT(onNoMoreWidgets())); - aDesktop->addDockWidget(Qt::LeftDockWidgetArea, myPropertyPanel); hidePropertyPanel(); ///tabifyDockWidget(aObjDock, myPropertyPanel); myPropertyPanel->installEventFilter(myOperationMgr); - QPushButton* aOkBtn = myPropertyPanel->findChild(PROP_PANEL_OK); - connect(aOkBtn, SIGNAL(clicked()), myOperationMgr, SLOT(onCommitOperation())); - QPushButton* aCancelBtn = myPropertyPanel->findChild(PROP_PANEL_CANCEL); - connect(aCancelBtn, SIGNAL(clicked()), myOperationMgr, SLOT(onAbortOperation())); - connect(myPropertyPanel, SIGNAL(keyReleased(QKeyEvent*)), myOperationMgr, - SLOT(onKeyReleased(QKeyEvent*))); - connect(myOperationMgr, SIGNAL(applyEnableChanged(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))); } @@ -1156,23 +1207,6 @@ void XGUI_Workshop::onFeatureTriggered() } } -//****************************************************** -void XGUI_Workshop::changeCurrentDocument(ObjectPtr theObj) -{ - SessionPtr aMgr = ModelAPI_Session::get(); - if (theObj) { - ResultPartPtr aPart = std::dynamic_pointer_cast(theObj); - if (aPart) { - DocumentPtr aPartDoc = aPart->partDoc(); - if (aPartDoc) { - aMgr->setActiveDocument(aPartDoc); - return; - } - } - } - aMgr->setActiveDocument(aMgr->moduleDocument()); -} - //****************************************************** void XGUI_Workshop::salomeViewerSelectionChanged() { @@ -1189,13 +1223,10 @@ ModuleBase_IViewer* XGUI_Workshop::salomeViewer() const void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked) { QObjectPtrList aObjects = mySelector->selection()->selectedObjects(); - if ((theId == "ACTIVATE_PART_CMD") && (aObjects.size() > 0)) { - ResultPartPtr aPart = std::dynamic_pointer_cast(aObjects.first()); - activatePart(aPart); - } else if (theId == "DEACTIVATE_PART_CMD") - activatePart(ResultPartPtr()); - else if (theId == "DELETE_CMD") - deleteObjects(aObjects); + if (theId == "DELETE_CMD") + deleteObjects(); + else if (theId == "COLOR_CMD") + changeColor(aObjects); else if (theId == "SHOW_CMD") showObjects(aObjects, true); else if (theId == "HIDE_CMD") @@ -1206,150 +1237,288 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked) setDisplayMode(aObjects, XGUI_Displayer::Shading); else if (theId == "WIREFRAME_CMD") setDisplayMode(aObjects, XGUI_Displayer::Wireframe); - else if (theId == "HIDEALL_CMD") - myDisplayer->eraseAll(); - else if (theId == "EDIT_CMD") { - FeaturePtr aFeature = std::dynamic_pointer_cast(aObjects.first()); - if (aFeature) - myModule->editFeature(aFeature); + else if (theId == "HIDEALL_CMD") { + QObjectPtrList aList = myDisplayer->displayedObjects(); + foreach (ObjectPtr aObj, aList) + aObj->setDisplayed(false); + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); } } //************************************************************** -void XGUI_Workshop::onWidgetValuesChanged() +void XGUI_Workshop::deleteObjects() { - ModuleBase_Operation* anOperation = myOperationMgr->currentOperation(); - FeaturePtr aFeature = anOperation->feature(); + ModuleBase_IModule* aModule = module(); + // 1. allow the module to delete objects, do nothing if it has succeed + if (aModule->deleteObjects()) { + updateCommandStatus(); + return; + } - ModuleBase_ModelWidget* aSenderWidget = dynamic_cast(sender()); + if (!isActiveOperationAborted()) + return; + QObjectPtrList anObjects = mySelector->selection()->selectedObjects(); + bool hasResult = false; + bool hasFeature = false; + bool hasParameter = false; + ModuleBase_Tools::checkObjects(anObjects, hasResult, hasFeature, hasParameter); + if (!(hasFeature || hasParameter)) + return; - 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 == aSenderWidget)) { - aCustom->storeValue(); - } + // 1. start operation + QString aDescription = contextMenuMgr()->action("DELETE_CMD")->text(); + aDescription += tr(" %1"); + QStringList aObjectNames; + foreach (ObjectPtr aObj, anObjects) { + if (!aObj->data()->isValid()) + continue; + aObjectNames << QString::fromStdString(aObj->data()->name()); } -} + aDescription = aDescription.arg(aObjectNames.join(", ")); -//************************************************************** -void XGUI_Workshop::activatePart(ResultPartPtr theFeature) -{ - if (!myPartActivating) { - myPartActivating = true; - if (theFeature) - theFeature->activate(); - changeCurrentDocument(theFeature); - myObjectBrowser->activatePart(theFeature); - myPartActivating = false; + SessionPtr aMgr = ModelAPI_Session::get(); + aMgr->startOperation(aDescription.toStdString()); + // 2. close the documents of the removed parts if the result part is in a list of selected objects + foreach (ObjectPtr aObj, anObjects) + { + ResultPartPtr aPart = std::dynamic_pointer_cast(aObj); + if (aPart) { + DocumentPtr aDoc = aObj->document(); + if (aDoc == aMgr->activeDocument()) { + aDoc->close(); + } + } + } + // 3. delete objects + QMainWindow* aDesktop = isSalomeMode() ? salomeConnector()->desktop() : myMainWindow; + std::set anIgnoredFeatures; + if (deleteFeatures(anObjects, anIgnoredFeatures, aDesktop, true)) { + myDisplayer->updateViewer(); + aMgr->finishOperation(); + updateCommandStatus(); + } + else { + aMgr->abortOperation(); } - 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::deleteObjects(const QObjectPtrList& theList) +bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList, + std::set theIgnoredFeatures, + QWidget* theParent, + const bool theAskAboutDeleteReferences) { - QMainWindow* aDesktop = isSalomeMode() ? salomeConnector()->desktop() : myMainWindow; - + // 1. find all referenced features 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); - } + foreach (ObjectPtr aObj, theList) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aObj); + if (aFeature.get() != NULL) { + aObj->document()->refsToFeature(aFeature, aRefFeatures, false); } } - - if (!aRefFeatures.empty()) { + // 2. warn about the references remove, break the delete operation if the user chose it + if (theAskAboutDeleteReferences && !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"), + theParent, 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; + return false; } - SessionPtr aMgr = ModelAPI_Session::get(); - aMgr->startOperation(); + // 3. remove referenced features std::set::const_iterator anIt = aRefFeatures.begin(), aLast = aRefFeatures.end(); for (; anIt != aLast; anIt++) { - FeaturePtr aRefFeature = (*anIt); - DocumentPtr aDoc = aRefFeature->document(); - aDoc->removeFeature(aRefFeature); - } + FeaturePtr aFeature = (*anIt); + DocumentPtr aDoc = aFeature->document(); + if (theIgnoredFeatures.find(aFeature) == theIgnoredFeatures.end()) + aDoc->removeFeature(aFeature); + } + // 4. remove the parameter features + foreach (ObjectPtr aObj, theList) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aObj); + if (aFeature) { + DocumentPtr aDoc = aObj->document(); + if (theIgnoredFeatures.find(aFeature) == theIgnoredFeatures.end()) + aDoc->removeFeature(aFeature); + } + } + return true; +} - foreach (ObjectPtr aObj, theList) +bool hasResults(QObjectPtrList theObjects, const std::set& theTypes) +{ + bool isFoundResultType = false; + foreach(ObjectPtr anObj, theObjects) { - DocumentPtr aDoc = aObj->document(); - ResultPartPtr aPart = std::dynamic_pointer_cast(aObj); - if (aPart) { - if (aDoc == aMgr->activeDocument()) { - aDoc->close(); + ResultPtr aResult = std::dynamic_pointer_cast(anObj); + if (aResult.get() == NULL) + continue; + + isFoundResultType = theTypes.find(aResult->groupName()) != theTypes.end(); + if (isFoundResultType) + break; + } + return isFoundResultType; +} + +//************************************************************** +bool XGUI_Workshop::canChangeColor() const +{ + QObjectPtrList aObjects = mySelector->selection()->selectedObjects(); + + std::set aTypes; + aTypes.insert(ModelAPI_ResultGroup::group()); + aTypes.insert(ModelAPI_ResultConstruction::group()); + aTypes.insert(ModelAPI_ResultBody::group()); + aTypes.insert(ModelAPI_ResultPart::group()); + + return hasResults(aObjects, aTypes); +} + +void setColor(ResultPtr theResult, std::vector& theColor) +{ + if (!theResult.get()) + return; + + AttributeIntArrayPtr aColorAttr = theResult->data()->intArray(ModelAPI_Result::COLOR_ID()); + if (aColorAttr.get() != NULL) { + if (!aColorAttr->size()) { + aColorAttr->setSize(3); + } + aColorAttr->setValue(0, theColor[0]); + aColorAttr->setValue(1, theColor[1]); + aColorAttr->setValue(2, theColor[2]); + } +} + +//************************************************************** +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 + std::vector aColor; + foreach(ObjectPtr anObject, theObjects) { + if (anObject->groupName() == ModelAPI_ResultPart::group()) { + ResultPartPtr aPart = std::dynamic_pointer_cast(anObject); + DocumentPtr aPartDoc = aPart->partDoc(); + // the document should be checked on null, because in opened document if the part + // has not been activated yet, the part document is empty + if (!aPartDoc.get()) { + emit errorOccurred(QString::fromLatin1("Color can not be changed on a part with an empty document")); } - } else { - FeaturePtr aFeature = std::dynamic_pointer_cast(aObj); - if (aFeature) { - aDoc->removeFeature(aFeature); + else { + if (aPartDoc->size(ModelAPI_ResultBody::group()) > 0) { + ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultBody::group(), 0); + ResultBodyPtr aBody = std::dynamic_pointer_cast(aObject); + if (aBody.get()) { + std::string aSection, aName, aDefault; + aBody->colorConfigInfo(aSection, aName, aDefault); + if (!aSection.empty() && !aName.empty()) { + aColor = Config_PropManager::color(aSection, aName, aDefault); + } + } + } } } + else { + AISObjectPtr anAISObj = myDisplayer->getAISObject(anObject); + if (anAISObj.get()) { + aColor.resize(3); + anAISObj->getColor(aColor[0], aColor[1], aColor[2]); + } + } + if (!aColor.empty()) + break; } + if (aColor.size() != 3) + return; - myDisplayer->updateViewer(); - aMgr->finishOperation(); + // 2. show the dialog to change the value + XGUI_ColorDialog* aDlg = new XGUI_ColorDialog(mainWindow()); + aDlg->setColor(aColor); + aDlg->move(QCursor::pos()); + bool isDone = aDlg->exec() == QDialog::Accepted; + if (!isDone) + return; + + bool isRandomColor = aDlg->isRandomColor(); + + // 3. abort the previous operation and start a new one + SessionPtr aMgr = ModelAPI_Session::get(); + bool aWasOperation = aMgr->isOperation(); // keep this value + if (!aWasOperation) { + QString aDescription = contextMenuMgr()->action("COLOR_CMD")->text(); + aMgr->startOperation(aDescription.toStdString()); + } + + // 4. set the value to all results + foreach(ObjectPtr anObj, theObjects) { + ResultPtr aResult = std::dynamic_pointer_cast(anObj); + if (aResult.get() != NULL) { + if (aResult->groupName() == ModelAPI_ResultPart::group()) { + ResultPartPtr aPart = std::dynamic_pointer_cast(aResult); + DocumentPtr aPartDoc = aPart->partDoc(); + // the document should be checked on null, because in opened document if the part + // has not been activated yet, the part document is empty + if (aPartDoc.get()) { + for (int i = 0; i < aPartDoc->size(ModelAPI_ResultBody::group()); i++) { + ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultBody::group(), i); + ResultBodyPtr aBody = std::dynamic_pointer_cast(aObject); + std::vector aColorResult = aDlg->getColor(); + setColor(aBody, aColorResult); + } + } + } + else { + std::vector aColorResult = aDlg->getColor(); + setColor(aResult, aColorResult); + } + } + } + if (!aWasOperation) + aMgr->finishOperation(); + updateCommandStatus(); } //************************************************************** void XGUI_Workshop::showObjects(const QObjectPtrList& theList, bool isVisible) { - foreach (ObjectPtr aObj, theList) - { + foreach (ObjectPtr aObj, theList) { if (isVisible) { - displayObject(aObj); + aObj->setDisplayed(true); + //displayObject(aObj); } else { - myDisplayer->erase(aObj, false); + aObj->setDisplayed(false); + //myDisplayer->erase(aObj, false); } } - myDisplayer->updateViewer(); + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); + //myDisplayer->updateViewer(); } //************************************************************** void XGUI_Workshop::showOnlyObjects(const QObjectPtrList& theList) { - myDisplayer->showOnly(theList); + QObjectPtrList aList = myDisplayer->displayedObjects(); + foreach (ObjectPtr aObj, aList) + aObj->setDisplayed(false); + foreach (ObjectPtr aObj, theList) + aObj->setDisplayed(true); + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); + } @@ -1386,8 +1555,10 @@ void XGUI_Workshop::displayDocumentResults(DocumentPtr theDoc) //************************************************************** void XGUI_Workshop::displayGroupResults(DocumentPtr theDoc, std::string theGroup) { - for (int i = 0; i < theDoc->size(theGroup); i++) - displayObject(theDoc->object(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)); } //************************************************************** @@ -1414,18 +1585,63 @@ void XGUI_Workshop::closeDocument() SessionPtr aMgr = ModelAPI_Session::get(); aMgr->closeAll(); - objectBrowser()->clearContent(); } //************************************************************** -void XGUI_Workshop::displayObject(ObjectPtr theObj) +bool XGUI_Workshop::displayObject(ObjectPtr theObj) { + if (!myModule->canDisplayObject(theObj)) + return false; + 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 + } else if (!(myIsLoadingData || myPartActivating)) myDisplayer->display(theObj, false); + + return true; +} + +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; + QAction* aContextMenuAct = myContextMenuMgr->actionByName(anId); + if (aContextMenuAct) { + anInfo.initFrom(aContextMenuAct); + } else { + anInfo = myActionsMgr->actionInfoById(anId); + } + if (isEditing) { + anInfo.text = anInfo.text.prepend("Modify "); + } + aResult << anInfo; + } + return aResult; }