1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
\r
3 // File: XGUI_OperationMgr.cpp
\r
4 // Created: 20 Apr 2014
\r
5 // Author: Natalia ERMOLAEVA
\r
7 #include "XGUI_OperationMgr.h"
\r
8 #include "XGUI_ModuleConnector.h"
\r
9 #include "XGUI_Workshop.h"
\r
10 #include "XGUI_ErrorMgr.h"
\r
11 #include "XGUI_Tools.h"
\r
12 #include "XGUI_ObjectsBrowser.h"
\r
13 #include "XGUI_ContextMenuMgr.h"
\r
15 #include <ModuleBase_IPropertyPanel.h>
\r
16 #include <ModuleBase_ModelWidget.h>
\r
17 #include "ModuleBase_Operation.h"
\r
18 #include "ModuleBase_IWorkshop.h"
\r
19 #include "ModuleBase_IModule.h"
\r
20 #include <ModuleBase_IViewer.h>
\r
21 #include "ModuleBase_OperationDescription.h"
\r
22 #include "ModuleBase_OperationFeature.h"
\r
23 #include "ModuleBase_Tools.h"
\r
25 #include "ModelAPI_CompositeFeature.h"
\r
26 #include "ModelAPI_Session.h"
\r
28 #include <XGUI_PropertyPanel.h>
\r
29 #include <QToolButton>
\r
30 #include <QLineEdit>
\r
32 #include <QMessageBox>
\r
33 #include <QApplication>
\r
34 #include <QKeyEvent>
\r
36 //#define DEBUG_CURRENT_FEATURE
\r
38 /// Processes "Delete" key event of application. This key is used by several application actions.
\r
39 /// There is a logical order of the actions processing. So the key can not be set for actions
\r
40 /// as a shortcut. The class listens the key event and call operation manager processor.
\r
41 class XGUI_ShortCutListener : public QObject
\r
45 /// \param theParent the parent to be deleted when the parent is deleted
\r
46 /// \param theOperationMgr the class to perform deletion
\r
47 XGUI_ShortCutListener(QObject* theParent, XGUI_OperationMgr* theOperationMgr)
\r
48 : QObject(theParent), myOperationMgr(theOperationMgr)
\r
50 qApp->installEventFilter(this);
\r
52 ~XGUI_ShortCutListener() {}
\r
54 /// Switch on short cut listener
\r
55 void setActive(const bool theIsActive) { myIsActive = theIsActive; }
\r
57 /// Redefinition of virtual function to process Delete key release
\r
58 virtual bool eventFilter(QObject *theObject, QEvent *theEvent)
\r
60 bool isAccepted = false;
\r
61 if (myIsActive && theEvent->type() == QEvent::KeyRelease) {
\r
62 QKeyEvent* aKeyEvent = dynamic_cast<QKeyEvent*>(theEvent);
\r
64 switch (aKeyEvent->key()) {
\r
65 case Qt::Key_Delete: {
\r
66 isAccepted = myOperationMgr->onProcessDelete(theObject);
\r
72 isAccepted = QObject::eventFilter(theObject, theEvent);
\r
77 XGUI_OperationMgr* myOperationMgr; /// processor for key event
\r
78 bool myIsActive; /// boolean state whether the event filter perform own signal processing
\r
81 XGUI_OperationMgr::XGUI_OperationMgr(QObject* theParent,
\r
82 ModuleBase_IWorkshop* theWorkshop)
\r
83 : QObject(theParent), myWorkshop(theWorkshop)
\r
85 /// we need to install filter to the application in order to react to 'Delete' key button
\r
86 /// this key can not be a short cut for a corresponded action because we need to set
\r
87 /// the actions priority
\r
88 myShortCutListener = new XGUI_ShortCutListener(theParent, this);
\r
91 XGUI_OperationMgr::~XGUI_OperationMgr()
\r
95 void XGUI_OperationMgr::activate()
\r
97 myShortCutListener->setActive(true);
\r
100 void XGUI_OperationMgr::deactivate()
\r
102 myShortCutListener->setActive(false);
\r
105 ModuleBase_Operation* XGUI_OperationMgr::currentOperation() const
\r
107 return myOperations.count() > 0 ? myOperations.last() : 0;
\r
110 bool XGUI_OperationMgr::isCurrentOperation(ModuleBase_Operation* theOperation)
\r
112 if(!hasOperation())
\r
114 return currentOperation() == theOperation;
\r
117 bool XGUI_OperationMgr::hasOperation() const
\r
119 return !myOperations.isEmpty() && (myOperations.last() != NULL);
\r
122 bool XGUI_OperationMgr::hasOperation(const QString& theId) const
\r
124 foreach(ModuleBase_Operation* aOp, myOperations) {
\r
125 if (aOp->id() == theId)
\r
131 ModuleBase_Operation* XGUI_OperationMgr::findOperation(const QString& theId) const
\r
133 QList<ModuleBase_Operation*>::const_iterator anIt = myOperations.end();
\r
134 while (anIt != myOperations.begin()) {
\r
136 ModuleBase_Operation* anOperation = *anIt;
\r
137 if (anOperation->id() == theId)
\r
138 return anOperation;
\r
144 int XGUI_OperationMgr::operationsCount() const
\r
146 return myOperations.count();
\r
149 QStringList XGUI_OperationMgr::operationList() const
\r
151 QStringList result;
\r
152 foreach(ModuleBase_Operation* eachOperation, myOperations) {
\r
153 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(eachOperation);
\r
155 FeaturePtr aFeature = aFOperation->feature();
\r
157 result << QString::fromStdString(aFeature->getKind());
\r
164 ModuleBase_Operation* XGUI_OperationMgr::previousOperation(ModuleBase_Operation* theOperation) const
\r
166 int idx = myOperations.lastIndexOf(theOperation);
\r
167 if(idx == -1 || idx == 0) {
\r
170 return myOperations.at(idx - 1);
\r
173 bool XGUI_OperationMgr::eventFilter(QObject *theObject, QEvent *theEvent)
\r
175 bool isAccepted = false;
\r
176 if (theEvent->type() == QEvent::KeyRelease) {
\r
177 QKeyEvent* aKeyEvent = dynamic_cast<QKeyEvent*>(theEvent);
\r
179 isAccepted = onKeyReleased(theObject, aKeyEvent);
\r
182 isAccepted = QObject::eventFilter(theObject, theEvent);
\r
187 bool XGUI_OperationMgr::startOperation(ModuleBase_Operation* theOperation)
\r
189 if (hasOperation())
\r
190 currentOperation()->postpone();
\r
191 myOperations.append(theOperation);
\r
193 connect(theOperation, SIGNAL(beforeStarted()), SLOT(onBeforeOperationStarted()));
\r
194 connect(theOperation, SIGNAL(beforeAborted()), SLOT(onBeforeOperationAborted()));
\r
195 connect(theOperation, SIGNAL(beforeCommitted()), SLOT(onBeforeOperationCommitted()));
\r
197 connect(theOperation, SIGNAL(started()), SLOT(onOperationStarted()));
\r
198 connect(theOperation, SIGNAL(aborted()), SLOT(onOperationAborted()));
\r
199 connect(theOperation, SIGNAL(committed()), SLOT(onOperationCommitted()));
\r
201 connect(theOperation, SIGNAL(stopped()), SLOT(onOperationStopped()));
\r
202 connect(theOperation, SIGNAL(resumed()), SLOT(onOperationResumed()));
\r
204 bool isStarted = theOperation->start();
\r
206 onValidateOperation();
\r
210 bool XGUI_OperationMgr::abortAllOperations()
\r
212 bool aResult = true;
\r
213 if(!hasOperation())
\r
216 if (operationsCount() == 1) {
\r
217 ModuleBase_Operation* aCurrentOperation = currentOperation();
\r
218 if (canStopOperation(aCurrentOperation)) {
\r
219 abortOperation(aCurrentOperation);
\r
225 aResult = QMessageBox::question(qApp->activeWindow(),
\r
226 tr("Abort operation"),
\r
227 tr("All active operations will be aborted."),
\r
228 QMessageBox::Ok | QMessageBox::Cancel,
\r
229 QMessageBox::Cancel) == QMessageBox::Ok;
\r
230 while(aResult && hasOperation()) {
\r
231 abortOperation(currentOperation());
\r
237 bool XGUI_OperationMgr::commitAllOperations()
\r
239 bool isCompositeCommitted = false, anOperationProcessed = false;
\r
240 while (hasOperation()) {
\r
241 ModuleBase_Operation* anOperation = currentOperation();
\r
242 if (XGUI_Tools::workshop(myWorkshop)->errorMgr()->isApplyEnabled()) {
\r
243 anOperationProcessed = onCommitOperation();
\r
245 abortOperation(anOperation);
\r
246 anOperationProcessed = true;
\r
248 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
\r
251 FeaturePtr aFeature = aFOperation->feature();
\r
252 CompositeFeaturePtr aComposite =
\r
253 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeature);
\r
254 isCompositeCommitted = aComposite.get();
\r
255 if (isCompositeCommitted)
\r
258 // not processed[committed] operation might be used in composite feature,
\r
259 // so the while will be stopped by the previous check.
\r
260 // this code is not necessary, but logically should be done when the processing will not
\r
261 // be done for not composite feature by some reasons
\r
262 if (!anOperationProcessed)
\r
268 void XGUI_OperationMgr::onValidateOperation()
\r
270 if (!hasOperation())
\r
272 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
\r
273 (currentOperation());
\r
274 if(aFOperation && aFOperation->feature().get())
\r
275 XGUI_Tools::workshop(myWorkshop)->errorMgr()->updateActions(aFOperation->feature());
\r
278 void XGUI_OperationMgr::updateApplyOfOperations(ModuleBase_Operation* theOperation)
\r
280 XGUI_ErrorMgr* anErrorMgr = XGUI_Tools::workshop(myWorkshop)->errorMgr();
\r
281 if (theOperation) {
\r
282 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
\r
284 anErrorMgr->updateAcceptAllAction(aFOperation->feature());
\r
287 foreach(ModuleBase_Operation* anOperation, myOperations) {
\r
289 updateApplyOfOperations(anOperation);
\r
292 // Apply button of the current operation should also be updated
\r
293 onValidateOperation();
\r
296 bool XGUI_OperationMgr::canStopOperation(ModuleBase_Operation* theOperation)
\r
298 //in case of nested (sketch) operation no confirmation needed
\r
299 if (isGrantedOperation(theOperation->id()))
\r
301 if (theOperation && theOperation->isModified()) {
\r
302 QString aMessage = tr("%1 operation will be aborted.").arg(theOperation->id());
\r
303 int anAnswer = QMessageBox::question(qApp->activeWindow(),
\r
304 tr("Abort operation"),
\r
306 QMessageBox::Ok | QMessageBox::Cancel,
\r
307 QMessageBox::Cancel);
\r
308 return anAnswer == QMessageBox::Ok;
\r
313 bool XGUI_OperationMgr::commitOperation()
\r
315 //if (hasOperation() && currentOperation()->isValid()) {
\r
316 // onCommitOperation();
\r
320 return onCommitOperation();
\r
323 void XGUI_OperationMgr::resumeOperation(ModuleBase_Operation* theOperation)
\r
325 theOperation->resume();
\r
328 bool XGUI_OperationMgr::isGrantedOperation(const QString& theId)
\r
330 bool isGranted = false;
\r
332 QListIterator<ModuleBase_Operation*> anIt(myOperations);
\r
334 ModuleBase_Operation* aPreviousOperation = 0;
\r
335 while (anIt.hasPrevious() && !isGranted) {
\r
336 ModuleBase_Operation* anOp = anIt.previous();
\r
338 isGranted = anOp->isGranted(theId);
\r
343 void XGUI_OperationMgr::setCurrentFeature(const FeaturePtr& theFeature)
\r
345 SessionPtr aMgr = ModelAPI_Session::get();
\r
346 DocumentPtr aDoc = aMgr->activeDocument();
\r
347 bool aIsOp = aMgr->isOperation();
\r
349 aMgr->startOperation(QString("Set current feature: %1").arg(theFeature->getKind().c_str()).toStdString());
\r
350 aDoc->setCurrentFeature(theFeature, false);
\r
352 aMgr->finishOperation();
\r
355 bool XGUI_OperationMgr::canStartOperation(const QString& theId)
\r
357 bool aCanStart = true;
\r
358 ModuleBase_Operation* aCurrentOp = currentOperation();
\r
360 bool aGranted = aCurrentOp->isGranted(theId);
\r
361 // the started operation is granted for the current one,
\r
362 // e.g. current - Sketch, started - Line
\r
367 if (!isGrantedOperation(theId)) {
\r
368 // the operation is not granted in the current list of operations
\r
369 // e.g. Edit Parameter when Sketch, Line in Sketch is active.
\r
370 aCanStart = abortAllOperations();
\r
372 else if (canStopOperation(aCurrentOp)) {
\r
373 // the started operation is granted in the parrent operation,
\r
374 // e.g. current - Line in Sketch, started Circle
\r
375 stopOperation(aCurrentOp);
\r
384 void XGUI_OperationMgr::stopOperation(ModuleBase_Operation* theOperation)
\r
386 if (XGUI_Tools::workshop(myWorkshop)->errorMgr()->isApplyEnabled() && theOperation->isModified())
\r
387 theOperation->commit();
\r
389 abortOperation(theOperation);
\r
392 void XGUI_OperationMgr::abortOperation(ModuleBase_Operation* theOperation)
\r
394 ModuleBase_Operation* aCurrentOperation = currentOperation();
\r
395 if (theOperation == aCurrentOperation)
\r
396 theOperation->abort();
\r
398 // it is possible to trigger upper operation(e.g. sketch, current is sketch line)
\r
399 // all operation from the current to triggered should also be aborted
\r
400 // operations over the parameter one are not aborted(e.g. extrusion cut, sketch abort)
\r
401 while(hasOperation()) {
\r
402 ModuleBase_Operation* aCurrentOperation = currentOperation();
\r
403 aCurrentOperation->abort();
\r
404 if(theOperation == aCurrentOperation)
\r
410 bool XGUI_OperationMgr::onCommitOperation()
\r
412 bool isCommitted = false;
\r
413 ModuleBase_Operation* anOperation = currentOperation();
\r
414 if (anOperation && myWorkshop->module()->canCommitOperation())
\r
415 isCommitted = anOperation->commit();
\r
416 return isCommitted;
\r
419 void XGUI_OperationMgr::onAbortOperation()
\r
421 ModuleBase_Operation* aCurrentOperation = currentOperation();
\r
422 if (aCurrentOperation && canStopOperation(aCurrentOperation)) {
\r
423 abortOperation(aCurrentOperation);
\r
427 void XGUI_OperationMgr::onBeforeOperationStarted()
\r
429 ModuleBase_Operation* aCurrentOperation = dynamic_cast<ModuleBase_Operation*>(sender());
\r
430 if (!aCurrentOperation)
\r
433 /// Set current feature and remeber old current feature
\r
434 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(aCurrentOperation);
\r
436 SessionPtr aMgr = ModelAPI_Session::get();
\r
437 DocumentPtr aDoc = aMgr->activeDocument();
\r
438 // the parameter of current feature should be false, we should use all feature, not only visible
\r
439 // in order to correctly save the previous feature of the nested operation, where the
\r
440 // features can be not visible in the tree. The problem case is Edit sketch entitity(line)
\r
441 // in the Sketch, created in ExtrusionCut operation. The entity disappears by commit.
\r
442 // When sketch entity operation started, the sketch should be cashed here as the current.
\r
443 // Otherwise(the flag is true), the ExtrusionCut is cashed, when commit happens, the sketch
\r
444 // is disabled, sketch entity is disabled as extrusion cut is created earliest then sketch.
\r
445 // As a result the sketch disappears from the viewer. However after commit it is displayed back.
\r
446 aFOperation->setPreviousCurrentFeature(aDoc->currentFeature(false));
\r
448 #ifdef DEBUG_CURRENT_FEATURE
\r
449 FeaturePtr aFeature = aFOperation->feature();
\r
450 QString aKind = aFeature ? aFeature->getKind().c_str() : "";
\r
451 qDebug(QString("onBeforeOperationStarted(), edit operation = %1, feature = %2")
\r
452 .arg(aFOperation->isEditOperation())
\r
453 .arg(ModuleBase_Tools::objectInfo(aFeature)).toStdString().c_str());
\r
455 qDebug(QString("\tdocument->currentFeature(false) = %1").arg(
\r
456 ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str());
\r
459 if (aFOperation->isEditOperation()) {// it should be performed by the feature edit only
\r
460 // in create operation, the current feature is changed by addFeature()
\r
461 aDoc->setCurrentFeature(aFOperation->feature(), false);
\r
462 // this is the only place where flushes must be called after setCurrentFeature for the current
\r
463 // moment: after this the opertion is not finished, so, the ObjectBrowser state may be corrupted
\r
465 static Events_Loop* aLoop = Events_Loop::loop();
\r
466 static Events_ID aCreateEvent = aLoop->eventByName(EVENT_OBJECT_CREATED);
\r
467 aLoop->flush(aCreateEvent);
\r
468 static Events_ID aDeleteEvent = aLoop->eventByName(EVENT_OBJECT_DELETED);
\r
469 aLoop->flush(aDeleteEvent);
\r
472 #ifdef DEBUG_CURRENT_FEATURE
\r
473 qDebug("\tdocument->setCurrentFeature");
\r
474 qDebug(QString("\tdocument->currentFeature(false) = %1").arg(
\r
475 ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str());
\r
480 void XGUI_OperationMgr::onOperationStarted()
\r
482 ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
\r
483 updateApplyOfOperations(aSenderOperation);
\r
484 XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
\r
485 aWorkshop->operationStarted(aSenderOperation);
\r
488 void XGUI_OperationMgr::onBeforeOperationAborted()
\r
490 onBeforeOperationCommitted();
\r
493 void XGUI_OperationMgr::onOperationAborted()
\r
495 ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
\r
496 emit operationAborted(aSenderOperation);
\r
499 void XGUI_OperationMgr::onBeforeOperationCommitted()
\r
501 ModuleBase_Operation* aCurrentOperation = dynamic_cast<ModuleBase_Operation*>(sender());
\r
502 if (!aCurrentOperation)
\r
505 /// Restore the previous current feature
\r
506 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(aCurrentOperation);
\r
508 #ifdef DEBUG_CURRENT_FEATURE
\r
509 QString aKind = aFOperation->feature()->getKind().c_str();
\r
510 qDebug(QString("onBeforeOperationCommitted(), edit operation = %1, feature = %2")
\r
511 .arg(aFOperation->isEditOperation())
\r
512 .arg(ModuleBase_Tools::objectInfo(aFOperation->feature())).toStdString().c_str());
\r
514 qDebug(QString("\tdocument->currentFeature(false) = %1").arg(
\r
515 ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str());
\r
518 if (aFOperation->isEditOperation()) {
\r
519 /// Restore the previous current feature
\r
520 setCurrentFeature(aFOperation->previousCurrentFeature());
\r
522 else { // create operation
\r
523 // the Top created feature should stays the current. In nested operations, like Line in the Sketch or
\r
524 // Sketch in ExtrusionCut, a previous feature should be restored on commit. It is performed here
\r
525 // in order to perform it in the current transaction without opening a new one.
\r
526 if (myOperations.front() != aFOperation)
\r
527 setCurrentFeature(aFOperation->previousCurrentFeature());
\r
529 #ifdef DEBUG_CURRENT_FEATURE
\r
530 qDebug("\tdocument->setCurrentFeature");
\r
531 qDebug(QString("\tdocument->currentFeature(false) = %1").arg(
\r
532 ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str());
\r
534 ModuleBase_IModule* aModule = myWorkshop->module();
\r
536 aModule->beforeOperationStopped(aFOperation);
\r
540 void XGUI_OperationMgr::onOperationCommitted()
\r
542 // apply state for all features from the stack of operations should be updated
\r
543 updateApplyOfOperations();
\r
545 ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
\r
546 emit operationCommitted(aSenderOperation);
\r
549 void XGUI_OperationMgr::onOperationResumed()
\r
551 ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
\r
552 emit operationResumed(aSenderOperation);
\r
555 void XGUI_OperationMgr::onOperationStopped()
\r
557 ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
\r
558 ModuleBase_Operation* aCurrentOperation = currentOperation();
\r
559 if (!aSenderOperation || !aCurrentOperation || aSenderOperation != aCurrentOperation)
\r
562 myOperations.removeAll(aCurrentOperation);
\r
563 aCurrentOperation->deleteLater();
\r
565 emit operationStopped(aCurrentOperation);
\r
567 // get last operation which can be resumed
\r
568 ModuleBase_Operation* aResultOp = 0;
\r
569 QListIterator<ModuleBase_Operation*> anIt(myOperations);
\r
571 while (anIt.hasPrevious()) {
\r
572 ModuleBase_Operation* anOp = anIt.previous();
\r
579 bool isModified = aCurrentOperation->isModified();
\r
580 aResultOp->setIsModified(aResultOp->isModified() || isModified);
\r
581 resumeOperation(aResultOp);
\r
582 onValidateOperation();
\r
586 bool XGUI_OperationMgr::onKeyReleased(QObject *theObject, QKeyEvent* theEvent)
\r
588 // Let the manager decide what to do with the given key combination.
\r
589 ModuleBase_Operation* anOperation = currentOperation();
\r
590 bool isAccepted = false;
\r
591 switch (theEvent->key()) {
\r
592 case Qt::Key_Return:
\r
593 case Qt::Key_Enter: {
\r
594 isAccepted = onProcessEnter(theObject);
\r
599 bool noModifiers = (theEvent->modifiers() == Qt::NoModifier);
\r
601 ModuleBase_IViewer* aViewer = myWorkshop->viewer();
\r
602 Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
\r
603 if (!aContext.IsNull()) {
\r
604 Handle(V3d_View) aView = aViewer->activeView();
\r
605 if ((theEvent->key() == Qt::Key_N))
\r
606 aContext->HilightNextDetected(aView);
\r
607 else if ((theEvent->key() == Qt::Key_P))
\r
608 aContext->HilightPreviousDetected(aView);
\r
615 isAccepted = false;
\r
618 //if(anOperation) {
\r
619 // anOperation->keyReleased(theEvent->key());
\r
624 bool XGUI_OperationMgr::onProcessEnter(QObject* theObject)
\r
626 bool isAccepted = false;
\r
627 ModuleBase_Operation* aOperation = currentOperation();
\r
628 // to avoid enter processing when operation has not been started yet
\r
631 ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
\r
632 // only property panel enter is processed in order to do not process enter in application dialogs
\r
633 bool isPPChild = isChildObject(theObject, aPanel);
\r
637 ModuleBase_ModelWidget* anActiveWgt = aPanel->activeWidget();
\r
638 bool isAborted = false;
\r
639 if (!anActiveWgt) {
\r
640 QWidget* aFocusWidget = aPanel->focusWidget();
\r
641 QToolButton* aCancelBtn = dynamic_cast<XGUI_PropertyPanel*>(aPanel)->findButton(PROP_PANEL_CANCEL);
\r
642 if (aFocusWidget && aCancelBtn && aFocusWidget == aCancelBtn) {
\r
643 abortOperation(aOperation);
\r
649 isAccepted = anActiveWgt && anActiveWgt->processEnter();
\r
651 isAccepted = myWorkshop->module()->processEnter(anActiveWgt ? anActiveWgt->attributeID() : "");
\r
653 /// functionality is similar to Apply click
\r
654 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(currentOperation());
\r
655 if (!aFOperation || myWorkshop->module()->getFeatureError(aFOperation->feature()).isEmpty()) {
\r
656 // key released is emitted to apply the current value to the model if it was modified in PP
\r
657 emit keyEnterReleased();
\r
662 isAccepted = false;
\r
669 bool editorControl(QObject* theObject)
\r
671 QLineEdit* aLineEdit = dynamic_cast<QLineEdit*>(theObject);
\r
675 bool XGUI_OperationMgr::onProcessDelete(QObject* theObject)
\r
677 bool isAccepted = false;
\r
678 ModuleBase_Operation* aOperation = currentOperation();
\r
679 ModuleBase_ModelWidget* anActiveWgt = 0;
\r
680 // firstly the widget should process Delete action
\r
681 ModuleBase_IPropertyPanel* aPanel;
\r
682 bool isPPChildObject = false;
\r
684 aPanel = aOperation->propertyPanel();
\r
686 isPPChildObject = isChildObject(theObject, aPanel);
\r
687 // process delete in active widget only if delete sender is child of property panel
\r
688 // it is necessary for the case when OB is shown, user perform selection and click Delete
\r
689 if (isPPChildObject) {
\r
690 anActiveWgt = aPanel->activeWidget();
\r
692 isAccepted = anActiveWgt->processDelete();
\r
698 // after widget, object browser and viewer should process delete
\r
699 /// other widgets such as line edit controls should not lead to
\r
700 /// processing delete by workshop
\r
701 XGUI_ObjectsBrowser* aBrowser = XGUI_Tools::workshop(myWorkshop)->objectBrowser();
\r
702 QWidget* aViewPort = myWorkshop->viewer()->activeViewPort();
\r
703 bool isToDeleteObject = false;
\r
704 XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
\r
705 XGUI_ContextMenuMgr* aContextMenuMgr = aWorkshop->contextMenuMgr();
\r
706 if (theObject == aBrowser->treeView()) {
\r
707 aContextMenuMgr->updateObjectBrowserMenu();
\r
708 isToDeleteObject = aContextMenuMgr->action("DELETE_CMD")->isEnabled();
\r
710 else if (isChildObject(theObject, aViewPort)) {
\r
711 aContextMenuMgr->updateViewerMenu();
\r
712 isToDeleteObject = aContextMenuMgr->action("DELETE_CMD")->isEnabled();
\r
714 else if (isPPChildObject) {
\r
715 // property panel child object is processed to process delete performed on Apply button of PP
\r
716 isToDeleteObject = true;
\r
718 else if (editorControl(theObject)) {
\r
719 isToDeleteObject = false; /// Line Edit of Rename operation in ObjectBrowser
\r
723 if (isToDeleteObject) {
\r
724 aWorkshop->deleteObjects();
\r
732 bool XGUI_OperationMgr::isChildObject(const QObject* theObject, const QObject* theParent)
\r
734 bool isPPChild = false;
\r
735 if (theParent && theObject) {
\r
736 QObject* aParent = (QObject*)theObject;
\r
738 isPPChild = aParent == theParent;
\r
741 aParent = aParent->parent();
\r