1 // Copyright (C) 2014-2024 CEA, EDF
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "ModelAPI_IReentrant.h"
21 #include "ModelAPI_EventReentrantMessage.h"
23 #include "ModuleBase_IModule.h"
24 #include "ModuleBase_IViewer.h"
25 #include "ModuleBase_ViewerPrs.h"
26 #include "ModuleBase_Operation.h"
27 #include "ModuleBase_IPropertyPanel.h"
28 #include "ModuleBase_ISelection.h"
29 #include "ModuleBase_OperationDescription.h"
30 #include "ModuleBase_OperationFeature.h"
31 #include "ModuleBase_ModelWidget.h"
32 #include "ModuleBase_WidgetFactory.h"
33 #include "ModuleBase_PageWidget.h"
34 #include "ModuleBase_Dialog.h"
35 #include "ModuleBase_IErrorMgr.h"
37 #include <Events_InfoMessage.h>
38 #include <Events_Loop.h>
39 #include <Events_Message.h>
41 #include <ModelAPI_Events.h>
42 #include <ModelAPI_CompositeFeature.h>
43 #include <ModelAPI_Session.h>
44 #include "ModelAPI_Tools.h"
46 #include <Config_PointerMessage.h>
47 #include <Config_WidgetReader.h>
48 #include <Config_ModuleReader.h>
51 #include <QMainWindow>
54 #include <QDialogButtonBox>
55 #include <QPushButton>
57 ModuleBase_IModule::ModuleBase_IModule(ModuleBase_IWorkshop* theParent)
58 : QObject(theParent), myWorkshop(theParent)
60 connect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
63 //connect(myWorkshop->viewer(), SIGNAL(mousePress(QMouseEvent*)), this,
64 // SLOT(onMousePressed(QMouseEvent*)));
65 //connect(myWorkshop->viewer(), SIGNAL(mouseRelease(QMouseEvent*)), this,
66 // SLOT(onMouseReleased(QMouseEvent*)));
67 //connect(myWorkshop->viewer(), SIGNAL(mouseMove(QMouseEvent*)), this,
68 // SLOT(onMouseMoved(QMouseEvent*)));
69 //connect(myWorkshop->viewer(), SIGNAL(keyRelease(QKeyEvent*)), this,
70 // SLOT(onKeyRelease(QKeyEvent*)));
71 //connect(myWorkshop->viewer(), SIGNAL(mouseDoubleClick(QMouseEvent*)), this,
72 // SLOT(onMouseDoubleClick(QMouseEvent*)));
75 ModuleBase_IModule::~ModuleBase_IModule()
77 std::map<ModuleBase_SelectionFilterType, Handle(SelectMgr_Filter)>::const_iterator aFiltersIt =
78 mySelectionFilters.begin();
79 for (; aFiltersIt != mySelectionFilters.end(); aFiltersIt++) {
80 Handle(SelectMgr_Filter) aFilter = aFiltersIt->second;
81 if (!aFilter.IsNull())
87 void ModuleBase_IModule::launchModal(const QString& theCmdId)
90 if (!myWorkshop->canStartOperation(theCmdId, isCommitted))
93 std::string aXmlCfg, aDescription;
94 getXMLRepresentation(theCmdId.toStdString(), aXmlCfg, aDescription);
96 SessionPtr aMgr = ModelAPI_Session::get();
97 aMgr->startOperation(theCmdId.toStdString());
99 ModuleBase_Dialog aDlg(myWorkshop, aXmlCfg);
100 if (aDlg.exec() == QDialog::Accepted)
101 aMgr->finishOperation();
103 aMgr->abortOperation();
104 myWorkshop->updateCommandStatus();
108 void ModuleBase_IModule::launchOperation(const QString& theCmdId,
109 const bool& isStartAfterCommitOnly)
111 /// selection should be obtained from workshop before ask if the operation can be started as
112 /// the canStartOperation method performs commit/abort of previous operation.
113 /// Sometimes commit/abort may cause selection clear(Sketch operation) as a result
114 /// it will be lost and is not used for preselection.
115 ModuleBase_ISelection* aSelection = myWorkshop->selection();
116 QList<ModuleBase_ViewerPrsPtr> aPreSelected =
117 aSelection->getSelected(ModuleBase_ISelection::AllControls);
119 ModuleBase_OperationFeature* aCurOperation = dynamic_cast<ModuleBase_OperationFeature*>
120 (myWorkshop->currentOperation());
121 QString aCurOperationKind = aCurOperation ? aCurOperation->getDescription()->operationId() : "";
124 if (!myWorkshop->canStartOperation(theCmdId, isCommitted))
127 /// reentrant operation(Sketch Line) should not be started if operation is aborted
128 if (isStartAfterCommitOnly && !isCommitted)
131 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
132 (createOperation(theCmdId.toStdString()));
134 std::shared_ptr<Events_Message> aMessage = reentrantMessage();
135 if (aMessage.get()) {
136 setReentrantPreSelection(aMessage);
138 else if (canUsePreselection(aCurOperationKind, theCmdId)) {
139 // restore of previous opeation is absent or new launched operation has the same kind
140 aFOperation->initSelection(aPreSelected);
142 workshop()->processLaunchOperation(aFOperation);
145 FeaturePtr aFeature = aFOperation->feature();
146 ModelReentrantPtr aReentrantFeature =
147 std::dynamic_pointer_cast<ModelAPI_IReentrant>(aFeature);
148 if (aReentrantFeature.get()) {
149 if (aMessage.get()) {
150 ModuleBase_IPropertyPanel* aPanel = workshop()->propertyPanel();
151 std::string aPrevAttribute = aReentrantFeature->processEvent(aMessage);
152 if (!aPrevAttribute.empty()) {
153 workshop()->errorMgr()->updateActions(aFeature);
154 ModuleBase_ModelWidget* aPrevWidget = aPanel->modelWidget(aPrevAttribute);
155 aPanel->activateNextWidget(aPrevWidget);
163 AISObjectPtr ModuleBase_IModule::createPresentation(const ObjectPtr& theResult)
165 return AISObjectPtr();
168 bool ModuleBase_IModule::canBeShaded(Handle(AIS_InteractiveObject) theAIS) const
173 QString ModuleBase_IModule::getFeatureError(const FeaturePtr& theFeature)
175 // Error already translated.
176 std::string aMsg = ModelAPI_Tools::getFeatureError(theFeature);
177 return QString::fromUtf8(aMsg.c_str());
180 void ModuleBase_IModule::grantedOperationIds(ModuleBase_Operation* theOperation,
181 QStringList& theIds) const
185 ModuleBase_Operation* ModuleBase_IModule::getNewOperation(const std::string& theFeatureId)
187 return new ModuleBase_OperationFeature(theFeatureId.c_str(), this);
190 ModuleBase_Operation* ModuleBase_IModule::createOperation(const std::string& theFeatureId)
192 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
193 (getNewOperation(theFeatureId));
194 // If the operation is launched as sub-operation of another then we have to initialize
196 ModuleBase_OperationFeature* aCurOperation = dynamic_cast<ModuleBase_OperationFeature*>
197 (myWorkshop->currentOperation());
199 FeaturePtr aFeature = aCurOperation->feature();
200 CompositeFeaturePtr aCompFeature =
201 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeature);
203 aFOperation->setParentFeature(aCompFeature);
207 std::string aXmlCfg, aDescription;
208 getXMLRepresentation(theFeatureId, aXmlCfg, aDescription);
209 aFOperation->getDescription()->setDescription(QString::fromStdString(aDescription));
210 aFOperation->getDescription()->setXmlRepresentation(QString::fromStdString(aXmlCfg));
215 void ModuleBase_IModule::createFeatures()
217 registerValidators();
218 registerProperties();
220 Config_ModuleReader aXMLReader = Config_ModuleReader();
221 aXMLReader.readAll();
222 myFeaturesInFiles = aXMLReader.featuresInFiles();
223 myProprietaryFeatures = aXMLReader.proprietaryFeatures();
224 myProprietaryPlugins = aXMLReader.proprietaryPlugins();
227 void ModuleBase_IModule::processProprietaryFeatures()
229 std::set<std::string>::iterator it = myFeaturesValidLicense.begin();
230 while (it != myFeaturesValidLicense.end()) {
231 std::map<std::string, std::string>::iterator aFound = myProprietaryFeatures.find(*it);
232 if (aFound == myProprietaryFeatures.end())
235 myFeaturesInFiles[aFound->first] = aFound->second;
236 myProprietaryFeatures.erase(aFound);
237 std::set<std::string>::iterator aRemoveIt = it++;
238 myFeaturesValidLicense.erase(aRemoveIt);
243 void ModuleBase_IModule::loadProprietaryPlugins()
245 for (std::set<std::string>::const_iterator itP = myProprietaryPlugins.begin();
246 itP != myProprietaryPlugins.end(); ++itP) {
247 if (!ModelAPI_Session::get()->checkLicense(*itP))
248 Events_InfoMessage(*itP, "License of %1 plugin is not valid or not exist!").arg(*itP).send();
253 void ModuleBase_IModule::actionCreated(QAction* theFeature)
255 connect(theFeature, SIGNAL(triggered(bool)), this, SLOT(onFeatureTriggered()));
258 bool ModuleBase_IModule::canEraseObject(const ObjectPtr& theObject) const
263 bool ModuleBase_IModule::canDisplayObject(const ObjectPtr& theObject) const
268 bool ModuleBase_IModule::canUsePreselection(const QString& thePreviousOperationKind,
269 const QString& theStartedOperationKind)
271 // no previous operation
272 if (thePreviousOperationKind.isEmpty())
275 if (thePreviousOperationKind.endsWith(ModuleBase_OperationFeature::EditSuffix()))
278 // reentrant operation
279 if (thePreviousOperationKind == theStartedOperationKind)
285 bool ModuleBase_IModule::canUndo() const
287 SessionPtr aMgr = ModelAPI_Session::get();
288 return aMgr->hasModuleDocument() && aMgr->canUndo() && !aMgr->isOperation();
291 bool ModuleBase_IModule::canRedo() const
293 SessionPtr aMgr = ModelAPI_Session::get();
294 return aMgr->hasModuleDocument() && aMgr->canRedo() && !aMgr->isOperation();
297 void ModuleBase_IModule::onFeatureTriggered()
299 QAction* aCmd = dynamic_cast<QAction*>(sender());
300 //Do nothing on uncheck
301 if (aCmd->isCheckable() && !aCmd->isChecked()) {
302 ModuleBase_Operation* anOperation = myWorkshop->findStartedOperation(aCmd->data().toString());
303 if (myWorkshop->canStopOperation(anOperation)) {
305 myWorkshop->stopOperation(anOperation, isCommitted);
308 aCmd->setChecked(true);
312 QString aCmdId = aCmd->data().toString();
313 std::shared_ptr<Config_FeatureMessage> aInfo = myWorkshop->featureInfo(aCmdId);
314 if (aInfo.get() && aInfo->isModal()) {
317 launchOperation(aCmdId, false);
322 void ModuleBase_IModule::editFeature(FeaturePtr theFeature)
324 std::string aFeatureId = theFeature->getKind();
326 if (!myWorkshop->canStartOperation(aFeatureId.c_str(), isCommitted))
329 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
330 (createOperation(aFeatureId));
332 aFOperation->setFeature(theFeature);
333 workshop()->processLaunchOperation(aFOperation);
337 bool ModuleBase_IModule::canActivateSelection(const ObjectPtr& theObject) const
339 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
340 (myWorkshop->currentOperation());
341 return !aFOperation || !aFOperation->hasObject(theObject);
344 void ModuleBase_IModule::operationResumed(ModuleBase_Operation* theOperation)
346 emit resumed(theOperation);
349 void ModuleBase_IModule::getXMLRepresentation(const std::string& theFeatureId,
350 std::string& theXmlCfg, std::string& theDescription)
352 std::string aPluginFileName = myFeaturesInFiles[theFeatureId];
353 Config_WidgetReader aWdgReader = Config_WidgetReader(aPluginFileName);
354 aWdgReader.readAll();
356 theXmlCfg = aWdgReader.featureWidgetCfg(theFeatureId);
357 theDescription = aWdgReader.featureDescription(theFeatureId);
361 //******************************************************
362 QIntList ModuleBase_IModule::selectionFilters()
366 std::map<ModuleBase_SelectionFilterType, Handle(SelectMgr_Filter)>::const_iterator aFiltersIt =
367 mySelectionFilters.begin();
368 for (; aFiltersIt != mySelectionFilters.end(); aFiltersIt++)
369 aTypes.append(aFiltersIt->first);
374 //******************************************************
375 void ModuleBase_IModule::registerSelectionFilter(const ModuleBase_SelectionFilterType theFilterType,
376 const Handle(SelectMgr_Filter)& theFilter)
378 mySelectionFilters[theFilterType] = theFilter;
381 //******************************************************
382 Handle(SelectMgr_Filter) ModuleBase_IModule::selectionFilter(const int theType)
384 ModuleBase_SelectionFilterType aType = (ModuleBase_SelectionFilterType)theType;
386 if (mySelectionFilters.find(aType) != mySelectionFilters.end())
387 return mySelectionFilters[aType];
389 return Handle(SelectMgr_Filter)();