1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
3 // File: ParametersPlugin_WidgetParamsMgr.cpp
4 // Created: 11 Apr 2016
5 // Author: Vitaly SMETANNIKOV
7 #include "ParametersPlugin_WidgetParamsMgr.h"
8 #include "ParametersPlugin_Parameter.h"
9 #include "ParametersPlugin_Validators.h"
11 #include <ModelAPI_ResultParameter.h>
12 #include <ModelAPI_AttributeString.h>
13 #include <ModelAPI_AttributeRefList.h>
14 #include <ModelAPI_AttributeDouble.h>
15 #include <ModelAPI_AttributeInteger.h>
16 #include <ModelAPI_Events.h>
17 #include <ModelAPI_Session.h>
19 #include <ModuleBase_Tools.h>
21 #include <Events_Loop.h>
24 #include <QTreeWidget>
25 #include <QPushButton>
26 #include <QToolButton>
27 #include <QStyledItemDelegate>
29 #include <QMessageBox>
39 const char* NoName = "<NoName>";
40 const char* NoValue = "<NoValue>";
42 class ParametersPlugin_ItemDelegate : public QStyledItemDelegate
45 ParametersPlugin_ItemDelegate(QObject* thaParent) :
46 QStyledItemDelegate(thaParent) {}
48 virtual void paint(QPainter* painter,
49 const QStyleOptionViewItem& option,
50 const QModelIndex& index ) const;
52 //virtual QWidget* createEditor(QWidget* parent,
53 // const QStyleOptionViewItem& option,
54 // const QModelIndex& index) const;
56 bool isEditable(const QModelIndex& theIndex) const;
59 bool ParametersPlugin_ItemDelegate::isEditable(const QModelIndex& theIndex) const
61 QModelIndex aParent = theIndex.parent();
62 if (aParent.isValid() && (aParent.row() == 0)) {
63 if (theIndex.column() == 2)
70 void ParametersPlugin_ItemDelegate::paint(QPainter* painter,
71 const QStyleOptionViewItem& option,
72 const QModelIndex& index ) const
74 QBrush aBrush = painter->brush();
75 QPen aPen = painter->pen();
76 if (!isEditable(index))
77 painter->setBrush(Qt::lightGray);
79 painter->setPen(Qt::darkGray);
80 painter->drawRect(option.rect);
81 painter->setPen(aPen);
83 QStyledItemDelegate::paint(painter, option, index);
84 painter->setBrush(aBrush);
88 /////////////////////////////////////////////////////////////////////////////////////////////////
90 ParametersPlugin_WidgetParamsMgr::ParametersPlugin_WidgetParamsMgr(QWidget* theParent, const Config_WidgetAPI* theData)
91 : ModuleBase_ModelWidget(theParent, theData)
93 QVBoxLayout* aLayout = new QVBoxLayout(this);
95 myTable = new QTreeWidget(this);
96 myTable->setColumnCount(4);
98 aHeaders << tr("Name") << tr("Equation") << tr("Result") << tr("Comment");
99 myTable->setHeaderLabels(aHeaders);
100 myTable->setColumnWidth(Col_Name, 200);
101 myTable->setColumnWidth(Col_Equation, 100);
102 myTable->setColumnWidth(Col_Result, 80);
103 myTable->setColumnWidth(Col_Comment, 200);
104 myTable->setMinimumWidth(600);
105 myTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
106 myTable->setSelectionMode(QAbstractItemView::SingleSelection);
108 connect(myTable, SIGNAL(doubleClicked(const QModelIndex&)),
109 SLOT(onDoubleClick(const QModelIndex&)));
110 connect(myTable, SIGNAL(itemSelectionChanged()), SLOT(onSelectionChanged()));
112 myDelegate = new ParametersPlugin_ItemDelegate(myTable);
113 connect(myDelegate, SIGNAL(closeEditor(QWidget*, QAbstractItemDelegate::EndEditHint)),
114 SLOT(onCloseEditor(QWidget*, QAbstractItemDelegate::EndEditHint)));
116 myTable->setItemDelegate(myDelegate);
117 aLayout->addWidget(myTable);
121 aNames<<tr("Parameters");
122 myParameters = new QTreeWidgetItem(aNames);
123 myTable->addTopLevelItem(myParameters);
126 aNames<<tr("Features");
127 myFeatures = new QTreeWidgetItem(aNames);
128 myTable->addTopLevelItem(myFeatures);
130 QHBoxLayout* aBtnLayout = new QHBoxLayout(this);
132 myUpBtn = new QToolButton(this);
133 myUpBtn->setArrowType(Qt::UpArrow);
134 connect(myUpBtn, SIGNAL(clicked(bool)), SLOT(onUp()));
135 aBtnLayout->addWidget(myUpBtn);
137 myDownBtn = new QToolButton(this);
138 myDownBtn->setArrowType(Qt::DownArrow);
139 connect(myDownBtn, SIGNAL(clicked(bool)), SLOT(onDown()));
140 aBtnLayout->addWidget(myDownBtn);
142 aBtnLayout->addStretch();
144 myAddBtn = new QPushButton(tr("Add"), this);
145 connect(myAddBtn, SIGNAL(clicked(bool)), SLOT(onAdd()));
146 aBtnLayout->addWidget(myAddBtn);
148 myInsertBtn = new QPushButton(tr("Insert"), this);
149 connect(myInsertBtn, SIGNAL(clicked(bool)), SLOT(onInsert()));
150 aBtnLayout->addWidget(myInsertBtn);
152 myRemoveBtn = new QPushButton(tr("Remove"), this);
153 connect(myRemoveBtn, SIGNAL(clicked(bool)), SLOT(onRemove()));
154 aBtnLayout->addWidget(myRemoveBtn);
156 aLayout->addLayout(aBtnLayout);
158 onSelectionChanged();
161 QList<QWidget*> ParametersPlugin_WidgetParamsMgr::getControls() const
163 QList<QWidget*> aList;
168 void ParametersPlugin_WidgetParamsMgr::selectItemScroll(QTreeWidgetItem* aItem)
170 myTable->clearSelection();
171 QModelIndex aParent = myTable->model()->index(0, 0);
172 int aChildIdx = myParameters->indexOfChild(aItem);
173 QModelIndex aIndex = myTable->model()->index(aChildIdx, Col_Name, aParent);
174 myTable->selectionModel()->select(aIndex,
175 QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
176 myTable->scrollToItem(aItem);
180 bool ParametersPlugin_WidgetParamsMgr::storeValueCustom()
182 ParametersPlugin_ExpressionValidator aValidator;
183 std::list<std::string> aArgs;
184 std::string aAttrId = ParametersPlugin_Parameter::VARIABLE_ID();
187 foreach(FeaturePtr aFeature, myParametersList) {
188 if (!aValidator.isValid(aFeature->attribute(aAttrId), aArgs, aErr)) {
189 QMessageBox::warning(this, tr("Warning"), aErr.c_str());
190 selectItemScroll(myParameters->child(aId));
198 bool ParametersPlugin_WidgetParamsMgr::restoreValueCustom()
203 void ParametersPlugin_WidgetParamsMgr::activateCustom()
205 FeaturePtr aFeature = feature();
206 DocumentPtr aDoc = aFeature->document();
207 int aNbParam = aDoc->size(ModelAPI_ResultParameter::group());
209 FeaturePtr aParamFeature;
210 for (int i = 0; i < aNbParam; i++) {
211 aObj = aDoc->object(ModelAPI_ResultParameter::group(), i);
212 aParamFeature = ModelAPI_Feature::feature(aObj);
213 if (aParamFeature.get() && (aParamFeature->getKind() == ParametersPlugin_Parameter::ID())) {
214 myParametersList.append(aParamFeature);
217 updateParametersPart();
218 updateFeaturesPart();
220 myFeatures->setExpanded(true);
221 myParameters->setExpanded(true);
224 void ParametersPlugin_WidgetParamsMgr::updateFeaturesPart()
226 updateItem(myFeatures, featuresItems(myParametersList));
229 void ParametersPlugin_WidgetParamsMgr::updateParametersPart()
231 updateItem(myParameters, parametersItems(myParametersList));
235 QList<QStringList> ParametersPlugin_WidgetParamsMgr::
236 featuresItems(const QList<FeaturePtr>& theFeatures) const
238 QList<QStringList> aItemsList;
239 ResultParameterPtr aParam;
240 foreach(FeaturePtr aParameter, theFeatures) {
241 aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aParameter->firstResult());
242 const std::set<std::shared_ptr<ModelAPI_Attribute>>& aRefs = aParam->data()->refsToMe();
243 std::set<std::shared_ptr<ModelAPI_Attribute> >::const_iterator aIt;
244 for(aIt = aRefs.cbegin(); aIt != aRefs.cend(); aIt++) {
245 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
246 FeaturePtr aReferenced = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
247 if (aReferenced.get()) {
248 if (aReferenced->getKind() == ParametersPlugin_Parameter::ID()) {
249 // Find referenced feature Recursive
250 QList<FeaturePtr> aList;
251 aList.append(aReferenced);
252 QList<QStringList> aItems = featuresItems(aList);
253 aItemsList.append(aItems);
255 QStringList aValNames;
256 aValNames << aReferenced->data()->name().c_str();
258 AttributeDoublePtr aDouble = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aAttr);
260 aValNames << aDouble->text().c_str();
261 aValNames << QString::number(aDouble->value());
263 AttributeIntegerPtr aInt = std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(aAttr);
265 aValNames << aInt->text().c_str();
266 aValNames << QString::number(aInt->value());
269 aItemsList.append(aValNames);
278 QList<QStringList> ParametersPlugin_WidgetParamsMgr::
279 parametersItems(const QList<FeaturePtr>& theFeatures) const
281 QList<QStringList> aItemsList;
282 foreach(FeaturePtr aParameter, theFeatures) {
283 ResultPtr aParam = aParameter->firstResult();
285 aValues << aParameter->string(ParametersPlugin_Parameter::VARIABLE_ID())->value().c_str();
286 aValues << aParameter->string(ParametersPlugin_Parameter::EXPRESSION_ID())->value().c_str();
288 AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
289 aValues << QString::number(aValueAttribute->value());
291 aValues << aParameter->string(ParametersPlugin_Parameter::COMMENT_ID())->value().c_str();
292 aItemsList.append(aValues);
298 void ParametersPlugin_WidgetParamsMgr::onDoubleClick(const QModelIndex& theIndex)
300 if (myDelegate->isEditable(theIndex)) {
301 myTable->edit(theIndex);
302 myEditingIndex = theIndex;
306 void ParametersPlugin_WidgetParamsMgr::onCloseEditor(QWidget* theEditor,
307 QAbstractItemDelegate::EndEditHint theHint)
309 FeaturePtr aFeature = myParametersList.at(myEditingIndex.row());
310 QTreeWidgetItem* aItem = myParameters->child(myEditingIndex.row());
311 int aColumn = myEditingIndex.column();
312 QString aText = aItem->text(aColumn);
313 bool isModified = false;
318 AttributeStringPtr aStringAttr = aFeature->string(ParametersPlugin_Parameter::VARIABLE_ID());
319 if (!aText.isEmpty()) {
320 if (hasName(aText)) {
321 myMessage = tr("Name %1 already exists.").arg(aText);
322 aItem->setText(Col_Name, aStringAttr->value().c_str());
323 QTimer::singleShot(50, this, SLOT(sendWarning()));
326 aStringAttr->setValue(aText.toStdString());
329 aItem->setText(Col_Name, aStringAttr->value().c_str());
335 AttributeStringPtr aStringAttr = aFeature->string(ParametersPlugin_Parameter::EXPRESSION_ID());
336 if (!aText.isEmpty()) {
337 if (aText != aStringAttr->value().c_str()) {
338 aStringAttr->setValue(aText.toStdString());
342 aItem->setText(Col_Equation, aStringAttr->value().c_str());
348 AttributeStringPtr aStringAttr = aFeature->string(ParametersPlugin_Parameter::COMMENT_ID());
349 aStringAttr->setValue(aText.toStdString());
357 Events_Loop* aLoop = Events_Loop::loop();
358 aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
360 ResultParameterPtr aResult =
361 std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aFeature->firstResult());
363 AttributeDoublePtr aValueAttribute =
364 aResult->data()->real(ModelAPI_ResultParameter::VALUE());
365 aItem->setText(Col_Result, QString::number(aValueAttribute->value()));
367 myEditingIndex = QModelIndex();
369 if (aColumn == Col_Equation)
370 updateParametersPart();
371 updateFeaturesPart();
374 void ParametersPlugin_WidgetParamsMgr::updateItem(QTreeWidgetItem* theItem,
375 const QList<QStringList>& theFeaturesList)
377 if (theFeaturesList.count() != theItem->childCount()) {
378 if (theItem->childCount() < theFeaturesList.count()) {
379 while (theItem->childCount() != theFeaturesList.count())
380 theItem->addChild(createNewItem());
382 while (theItem->childCount() != theFeaturesList.count())
383 theItem->removeChild(theItem->child(theItem->childCount() - 1));
387 foreach(QStringList aFeature, theFeaturesList) {
389 foreach(QString aText, aFeature) {
390 theItem->child(i)->setText(aCol, aText);
397 FeaturePtr ParametersPlugin_WidgetParamsMgr::createParameter() const
399 SessionPtr aMgr = ModelAPI_Session::get();
400 std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
402 FeaturePtr aFeature = aDoc->addFeature(ParametersPlugin_Parameter::ID());
403 if (aFeature.get()) {
404 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
405 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
411 QTreeWidgetItem* ParametersPlugin_WidgetParamsMgr::createNewItem() const
417 QTreeWidgetItem* aItem = new QTreeWidgetItem(aValues);
418 aItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
423 void ParametersPlugin_WidgetParamsMgr::onAdd()
425 FeaturePtr aFeature = createParameter();
429 QTreeWidgetItem* aItem = createNewItem();
430 if (aFeature->name().length() > 0)
431 aItem->setText(Col_Name, aFeature->name().c_str());
432 myParameters->addChild(aItem);
433 myParametersList.append(aFeature);
435 myTable->scrollToItem(aItem);
438 QTreeWidgetItem* ParametersPlugin_WidgetParamsMgr::selectedItem() const
440 QList<QTreeWidgetItem*> aItemsList = myTable->selectedItems();
441 if (aItemsList.count() == 0)
444 QTreeWidgetItem* aCurrentItem = aItemsList.first();
445 if (aCurrentItem->parent() != myParameters)
452 void ParametersPlugin_WidgetParamsMgr::onInsert()
454 QTreeWidgetItem* aCurrentItem = selectedItem();
458 SessionPtr aMgr = ModelAPI_Session::get();
459 std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
461 FeaturePtr aNewFeature = createParameter();
462 if (!aNewFeature.get())
465 QTreeWidgetItem* aItem = createNewItem();
466 int aCurrentPos = myParameters->indexOfChild(aCurrentItem);
467 if (aCurrentPos == 0) {
468 aDoc->moveFeature(aNewFeature, FeaturePtr());
470 FeaturePtr aCurFeature = myParametersList.at(aCurrentPos - 1);
471 aDoc->moveFeature(aNewFeature, aCurFeature);
473 myParametersList.insert(aCurrentPos, aNewFeature);
474 myParameters->insertChild(aCurrentPos, aItem);
477 void ParametersPlugin_WidgetParamsMgr::onRemove()
479 QTreeWidgetItem* aCurrentItem = selectedItem();
483 SessionPtr aMgr = ModelAPI_Session::get();
484 std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
486 int aCurrentPos = myParameters->indexOfChild(aCurrentItem);
487 FeaturePtr aCurFeature = myParametersList.at(aCurrentPos);
489 QObjectPtrList anObjects;
490 anObjects.append(aCurFeature);
492 std::set<FeaturePtr> aDirectRefFeatures, aIndirectRefFeatures;
493 ModuleBase_Tools::findReferences(anObjects, aDirectRefFeatures, aIndirectRefFeatures);
495 bool doDeleteReferences = true;
496 if (ModuleBase_Tools::isDeleteFeatureWithReferences(anObjects, aDirectRefFeatures,
497 aIndirectRefFeatures, this, doDeleteReferences)) {
498 myParametersList.removeOne(aCurFeature);
499 myParameters->removeChild(aCurrentItem);
501 std::set<FeaturePtr> aFeaturesToDelete;
502 if (doDeleteReferences) {
503 aFeaturesToDelete = aDirectRefFeatures;
504 aFeaturesToDelete.insert(aIndirectRefFeatures.begin(), aIndirectRefFeatures.end());
506 aDoc->removeFeature(aCurFeature);
507 std::set<FeaturePtr>::const_iterator anIt = aFeaturesToDelete.begin(),
508 aLast = aFeaturesToDelete.end();
509 for (; anIt != aLast; anIt++) {
510 FeaturePtr aFeature = (*anIt);
511 DocumentPtr aDoc = aFeature->document();
512 aDoc->removeFeature(aFeature);
515 Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED));
516 Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY));
517 updateFeaturesPart();
521 void ParametersPlugin_WidgetParamsMgr::onUp()
523 QTreeWidgetItem* aCurrentItem = selectedItem();
527 QString aName = aCurrentItem->text(0);
529 int aCurrentPos = myParameters->indexOfChild(aCurrentItem);
530 if (aCurrentPos == 0)
532 FeaturePtr aCurFeature = myParametersList.at(aCurrentPos);
534 std::string aNm = aCurFeature->data()->name();
536 SessionPtr aMgr = ModelAPI_Session::get();
537 std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
539 FeaturePtr aa = myParametersList.at(aCurrentPos - 1);
540 std::string aN = aa->data()->name();
542 if (aCurrentPos == 1)
543 aDoc->moveFeature(aCurFeature, FeaturePtr());
545 aDoc->moveFeature(aCurFeature, myParametersList.at(aCurrentPos - 2));
547 myParametersList.removeOne(aCurFeature);
548 myParametersList.insert(aCurrentPos - 1, aCurFeature);
550 myParameters->removeChild(aCurrentItem);
551 myParameters->insertChild(aCurrentPos - 1, aCurrentItem);
553 selectItemScroll(aCurrentItem);
556 void ParametersPlugin_WidgetParamsMgr::onDown()
558 QTreeWidgetItem* aCurrentItem = selectedItem();
562 int aCurrentPos = myParameters->indexOfChild(aCurrentItem);
563 if (aCurrentPos == (myParametersList.count() - 1))
565 FeaturePtr aCurFeature = myParametersList.at(aCurrentPos);
567 SessionPtr aMgr = ModelAPI_Session::get();
568 std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
569 aDoc->moveFeature(aCurFeature, myParametersList.at(aCurrentPos + 1));
571 myParametersList.removeOne(aCurFeature);
572 myParametersList.insert(aCurrentPos + 1, aCurFeature);
574 myParameters->removeChild(aCurrentItem);
575 myParameters->insertChild(aCurrentPos + 1, aCurrentItem);
577 selectItemScroll(aCurrentItem);
581 bool ParametersPlugin_WidgetParamsMgr::hasName(const QString& theName) const
583 foreach(FeaturePtr aFeature, myParametersList) {
584 if (aFeature->data()->name() == theName.toStdString())
590 void ParametersPlugin_WidgetParamsMgr::sendWarning()
592 QMessageBox::warning(this, tr("Warning"), myMessage);
595 void ParametersPlugin_WidgetParamsMgr::onSelectionChanged()
597 QList<QTreeWidgetItem*> aItemsList = myTable->selectedItems();
598 bool isParameter = false;
599 foreach(QTreeWidgetItem* aItem, aItemsList) {
600 if (aItem->parent() == myParameters) {
605 myInsertBtn->setEnabled(isParameter);
606 myRemoveBtn->setEnabled(isParameter);
607 myUpBtn->setEnabled(isParameter);
608 myDownBtn->setEnabled(isParameter);