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 //QString aText = index.data().toString();
84 //if ((aText == NoName) || (aText == NoValue))
85 // painter->setPen(Qt::red);
87 QStyledItemDelegate::paint(painter, option, index);
89 //painter->setPen(aPen);
90 painter->setBrush(aBrush);
94 //QWidget* ParametersPlugin_ItemDelegate::createEditor(QWidget* parent,
95 // const QStyleOptionViewItem& option,
96 // const QModelIndex& index) const
98 // QWidget* aWgt = QStyledItemDelegate::createEditor(parent, option, index);
99 // aWgt->setMinimumSize(option.rect.width() - option.decorationSize.width(),
100 // option.rect.height());
105 /////////////////////////////////////////////////////////////////////////////////////////////////
107 ParametersPlugin_WidgetParamsMgr::ParametersPlugin_WidgetParamsMgr(QWidget* theParent, const Config_WidgetAPI* theData)
108 : ModuleBase_ModelWidget(theParent, theData)
110 QVBoxLayout* aLayout = new QVBoxLayout(this);
112 myTable = new QTreeWidget(this);
113 myTable->setColumnCount(4);
114 QStringList aHeaders;
115 aHeaders << tr("Name") << tr("Equation") << tr("Result") << tr("Comment");
116 myTable->setHeaderLabels(aHeaders);
117 myTable->setColumnWidth(Col_Name, 200);
118 myTable->setColumnWidth(Col_Equation, 100);
119 myTable->setColumnWidth(Col_Result, 80);
120 myTable->setColumnWidth(Col_Comment, 200);
121 myTable->setMinimumWidth(600);
122 myTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
123 myTable->setSelectionMode(QAbstractItemView::SingleSelection);
125 connect(myTable, SIGNAL(doubleClicked(const QModelIndex&)),
126 SLOT(onDoubleClick(const QModelIndex&)));
127 connect(myTable, SIGNAL(itemSelectionChanged()), SLOT(onSelectionChanged()));
129 myDelegate = new ParametersPlugin_ItemDelegate(myTable);
130 connect(myDelegate, SIGNAL(closeEditor(QWidget*, QAbstractItemDelegate::EndEditHint)),
131 SLOT(onCloseEditor(QWidget*, QAbstractItemDelegate::EndEditHint)));
133 myTable->setItemDelegate(myDelegate);
134 aLayout->addWidget(myTable);
138 aNames<<tr("Parameters");
139 myParameters = new QTreeWidgetItem(aNames);
140 myTable->addTopLevelItem(myParameters);
143 aNames<<tr("Features");
144 myFeatures = new QTreeWidgetItem(aNames);
145 myTable->addTopLevelItem(myFeatures);
147 QHBoxLayout* aBtnLayout = new QHBoxLayout(this);
149 myUpBtn = new QToolButton(this);
150 myUpBtn->setArrowType(Qt::UpArrow);
151 connect(myUpBtn, SIGNAL(clicked(bool)), SLOT(onUp()));
152 aBtnLayout->addWidget(myUpBtn);
154 myDownBtn = new QToolButton(this);
155 myDownBtn->setArrowType(Qt::DownArrow);
156 connect(myDownBtn, SIGNAL(clicked(bool)), SLOT(onDown()));
157 aBtnLayout->addWidget(myDownBtn);
159 aBtnLayout->addStretch();
161 myAddBtn = new QPushButton(tr("Add"), this);
162 connect(myAddBtn, SIGNAL(clicked(bool)), SLOT(onAdd()));
163 aBtnLayout->addWidget(myAddBtn);
165 myInsertBtn = new QPushButton(tr("Insert"), this);
166 connect(myInsertBtn, SIGNAL(clicked(bool)), SLOT(onInsert()));
167 aBtnLayout->addWidget(myInsertBtn);
169 myRemoveBtn = new QPushButton(tr("Remove"), this);
170 connect(myRemoveBtn, SIGNAL(clicked(bool)), SLOT(onRemove()));
171 aBtnLayout->addWidget(myRemoveBtn);
173 aLayout->addLayout(aBtnLayout);
175 onSelectionChanged();
178 QList<QWidget*> ParametersPlugin_WidgetParamsMgr::getControls() const
180 QList<QWidget*> aList;
185 void ParametersPlugin_WidgetParamsMgr::selectItemScroll(QTreeWidgetItem* aItem)
187 myTable->clearSelection();
188 QModelIndex aParent = myTable->model()->index(0, 0);
189 int aChildIdx = myParameters->indexOfChild(aItem);
190 QModelIndex aIndex = myTable->model()->index(aChildIdx, Col_Name, aParent);
191 myTable->selectionModel()->select(aIndex,
192 QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
193 myTable->scrollToItem(aItem);
197 bool ParametersPlugin_WidgetParamsMgr::storeValueCustom()
199 ParametersPlugin_ExpressionValidator aValidator;
200 std::list<std::string> aArgs;
201 std::string aAttrId = ParametersPlugin_Parameter::VARIABLE_ID();
204 foreach(FeaturePtr aFeature, myParametersList) {
205 if (!aValidator.isValid(aFeature->attribute(aAttrId), aArgs, aErr)) {
206 QMessageBox::warning(this, tr("Warning"), aErr.c_str());
207 selectItemScroll(myParameters->child(aId));
215 bool ParametersPlugin_WidgetParamsMgr::restoreValueCustom()
220 void ParametersPlugin_WidgetParamsMgr::activateCustom()
222 FeaturePtr aFeature = feature();
223 DocumentPtr aDoc = aFeature->document();
224 int aNbParam = aDoc->size(ModelAPI_ResultParameter::group());
226 FeaturePtr aParamFeature;
227 for (int i = 0; i < aNbParam; i++) {
228 aObj = aDoc->object(ModelAPI_ResultParameter::group(), i);
229 aParamFeature = ModelAPI_Feature::feature(aObj);
230 if (aParamFeature.get() && (aParamFeature->getKind() == ParametersPlugin_Parameter::ID())) {
231 myParametersList.append(aParamFeature);
234 updateParametersPart();
235 updateFeaturesPart();
237 myFeatures->setExpanded(true);
238 myParameters->setExpanded(true);
241 void ParametersPlugin_WidgetParamsMgr::updateFeaturesPart()
243 updateItem(myFeatures, featuresItems(myParametersList));
246 void ParametersPlugin_WidgetParamsMgr::updateParametersPart()
248 updateItem(myParameters, parametersItems(myParametersList));
252 QList<QStringList> ParametersPlugin_WidgetParamsMgr::
253 featuresItems(const QList<FeaturePtr>& theFeatures) const
255 QList<QStringList> aItemsList;
256 ResultParameterPtr aParam;
257 foreach(FeaturePtr aParameter, theFeatures) {
258 aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aParameter->firstResult());
259 const std::set<std::shared_ptr<ModelAPI_Attribute>>& aRefs = aParam->data()->refsToMe();
260 std::set<std::shared_ptr<ModelAPI_Attribute> >::const_iterator aIt;
261 for(aIt = aRefs.cbegin(); aIt != aRefs.cend(); aIt++) {
262 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
263 FeaturePtr aReferenced = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
264 if (aReferenced.get()) {
265 if (aReferenced->getKind() == ParametersPlugin_Parameter::ID()) {
266 // Find referenced feature Recursive
267 QList<FeaturePtr> aList;
268 aList.append(aReferenced);
269 QList<QStringList> aItems = featuresItems(aList);
270 aItemsList.append(aItems);
272 QStringList aValNames;
273 aValNames << aReferenced->data()->name().c_str();
275 AttributeDoublePtr aDouble = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aAttr);
277 aValNames << aDouble->text().c_str();
278 aValNames << QString::number(aDouble->value());
280 AttributeIntegerPtr aInt = std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(aAttr);
282 aValNames << aInt->text().c_str();
283 aValNames << QString::number(aInt->value());
286 aItemsList.append(aValNames);
295 QList<QStringList> ParametersPlugin_WidgetParamsMgr::
296 parametersItems(const QList<FeaturePtr>& theFeatures) const
298 QList<QStringList> aItemsList;
299 foreach(FeaturePtr aParameter, theFeatures) {
300 ResultPtr aParam = aParameter->firstResult();
302 aValues << aParameter->string(ParametersPlugin_Parameter::VARIABLE_ID())->value().c_str();
303 aValues << aParameter->string(ParametersPlugin_Parameter::EXPRESSION_ID())->value().c_str();
305 AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
306 aValues << QString::number(aValueAttribute->value());
308 aValues << aParameter->string(ParametersPlugin_Parameter::COMMENT_ID())->value().c_str();
309 aItemsList.append(aValues);
315 void ParametersPlugin_WidgetParamsMgr::onDoubleClick(const QModelIndex& theIndex)
317 if (myDelegate->isEditable(theIndex)) {
318 myTable->edit(theIndex);
319 myEditingIndex = theIndex;
323 void ParametersPlugin_WidgetParamsMgr::onCloseEditor(QWidget* theEditor,
324 QAbstractItemDelegate::EndEditHint theHint)
326 FeaturePtr aFeature = myParametersList.at(myEditingIndex.row());
327 QTreeWidgetItem* aItem = myParameters->child(myEditingIndex.row());
328 int aColumn = myEditingIndex.column();
329 QString aText = aItem->text(aColumn);
330 bool isModified = false;
335 AttributeStringPtr aStringAttr = aFeature->string(ParametersPlugin_Parameter::VARIABLE_ID());
336 if (!aText.isEmpty()) {
337 if (hasName(aText)) {
338 myMessage = tr("Name %1 already exists.").arg(aText);
339 aItem->setText(Col_Name, aStringAttr->value().c_str());
340 QTimer::singleShot(50, this, SLOT(sendWarning()));
343 aStringAttr->setValue(aText.toStdString());
346 aItem->setText(Col_Name, aStringAttr->value().c_str());
352 AttributeStringPtr aStringAttr = aFeature->string(ParametersPlugin_Parameter::EXPRESSION_ID());
353 if (!aText.isEmpty()) {
354 if (aText != aStringAttr->value().c_str()) {
355 aStringAttr->setValue(aText.toStdString());
359 aItem->setText(Col_Equation, aStringAttr->value().c_str());
365 AttributeStringPtr aStringAttr = aFeature->string(ParametersPlugin_Parameter::COMMENT_ID());
366 aStringAttr->setValue(aText.toStdString());
374 Events_Loop* aLoop = Events_Loop::loop();
375 aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
377 ResultParameterPtr aResult =
378 std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aFeature->firstResult());
380 AttributeDoublePtr aValueAttribute =
381 aResult->data()->real(ModelAPI_ResultParameter::VALUE());
382 aItem->setText(Col_Result, QString::number(aValueAttribute->value()));
384 myEditingIndex = QModelIndex();
386 if (aColumn == Col_Equation)
387 updateParametersPart();
388 updateFeaturesPart();
391 void ParametersPlugin_WidgetParamsMgr::updateItem(QTreeWidgetItem* theItem,
392 const QList<QStringList>& theFeaturesList)
394 if (theFeaturesList.count() != theItem->childCount()) {
395 if (theItem->childCount() < theFeaturesList.count()) {
396 while (theItem->childCount() != theFeaturesList.count())
397 theItem->addChild(createNewItem());
399 while (theItem->childCount() != theFeaturesList.count())
400 theItem->removeChild(theItem->child(theItem->childCount() - 1));
404 foreach(QStringList aFeature, theFeaturesList) {
406 foreach(QString aText, aFeature) {
407 theItem->child(i)->setText(aCol, aText);
414 FeaturePtr ParametersPlugin_WidgetParamsMgr::createParameter() const
416 SessionPtr aMgr = ModelAPI_Session::get();
417 std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
419 FeaturePtr aFeature = aDoc->addFeature(ParametersPlugin_Parameter::ID());
420 if (aFeature.get()) {
421 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
422 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
428 QTreeWidgetItem* ParametersPlugin_WidgetParamsMgr::createNewItem() const
434 QTreeWidgetItem* aItem = new QTreeWidgetItem(aValues);
435 aItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
440 void ParametersPlugin_WidgetParamsMgr::onAdd()
442 FeaturePtr aFeature = createParameter();
446 QTreeWidgetItem* aItem = createNewItem();
447 if (aFeature->name().length() > 0)
448 aItem->setText(Col_Name, aFeature->name().c_str());
449 myParameters->addChild(aItem);
450 myParametersList.append(aFeature);
452 myTable->scrollToItem(aItem);
455 QTreeWidgetItem* ParametersPlugin_WidgetParamsMgr::selectedItem() const
457 QList<QTreeWidgetItem*> aItemsList = myTable->selectedItems();
458 if (aItemsList.count() == 0)
461 QTreeWidgetItem* aCurrentItem = aItemsList.first();
462 if (aCurrentItem->parent() != myParameters)
469 void ParametersPlugin_WidgetParamsMgr::onInsert()
471 QTreeWidgetItem* aCurrentItem = selectedItem();
475 SessionPtr aMgr = ModelAPI_Session::get();
476 std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
478 FeaturePtr aNewFeature = createParameter();
479 if (!aNewFeature.get())
482 QTreeWidgetItem* aItem = createNewItem();
483 int aCurrentPos = myParameters->indexOfChild(aCurrentItem);
484 if (aCurrentPos == 0) {
485 aDoc->moveFeature(aNewFeature, FeaturePtr());
487 FeaturePtr aCurFeature = myParametersList.at(aCurrentPos - 1);
488 aDoc->moveFeature(aNewFeature, aCurFeature);
490 myParametersList.insert(aCurrentPos, aNewFeature);
491 myParameters->insertChild(aCurrentPos, aItem);
494 void ParametersPlugin_WidgetParamsMgr::onRemove()
496 QTreeWidgetItem* aCurrentItem = selectedItem();
500 SessionPtr aMgr = ModelAPI_Session::get();
501 std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
503 int aCurrentPos = myParameters->indexOfChild(aCurrentItem);
504 FeaturePtr aCurFeature = myParametersList.at(aCurrentPos);
506 QObjectPtrList anObjects;
507 anObjects.append(aCurFeature);
509 std::set<FeaturePtr> aDirectRefFeatures, aIndirectRefFeatures;
510 ModuleBase_Tools::findReferences(anObjects, aDirectRefFeatures, aIndirectRefFeatures);
512 bool doDeleteReferences = true;
513 if (ModuleBase_Tools::isDeleteFeatureWithReferences(anObjects, aDirectRefFeatures,
514 aIndirectRefFeatures, this, doDeleteReferences)) {
515 myParametersList.removeOne(aCurFeature);
516 myParameters->removeChild(aCurrentItem);
518 std::set<FeaturePtr> aFeaturesToDelete;
519 if (doDeleteReferences) {
520 aFeaturesToDelete = aDirectRefFeatures;
521 aFeaturesToDelete.insert(aIndirectRefFeatures.begin(), aIndirectRefFeatures.end());
523 aDoc->removeFeature(aCurFeature);
524 std::set<FeaturePtr>::const_iterator anIt = aFeaturesToDelete.begin(),
525 aLast = aFeaturesToDelete.end();
526 for (; anIt != aLast; anIt++) {
527 FeaturePtr aFeature = (*anIt);
528 DocumentPtr aDoc = aFeature->document();
529 aDoc->removeFeature(aFeature);
532 Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY));
533 updateFeaturesPart();
537 void ParametersPlugin_WidgetParamsMgr::onUp()
539 QTreeWidgetItem* aCurrentItem = selectedItem();
543 QString aName = aCurrentItem->text(0);
545 int aCurrentPos = myParameters->indexOfChild(aCurrentItem);
546 if (aCurrentPos == 0)
548 FeaturePtr aCurFeature = myParametersList.at(aCurrentPos);
550 std::string aNm = aCurFeature->data()->name();
552 SessionPtr aMgr = ModelAPI_Session::get();
553 std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
555 FeaturePtr aa = myParametersList.at(aCurrentPos - 1);
556 std::string aN = aa->data()->name();
558 if (aCurrentPos == 1)
559 aDoc->moveFeature(aCurFeature, FeaturePtr());
561 aDoc->moveFeature(aCurFeature, myParametersList.at(aCurrentPos - 2));
563 myParametersList.removeOne(aCurFeature);
564 myParametersList.insert(aCurrentPos - 1, aCurFeature);
566 myParameters->removeChild(aCurrentItem);
567 myParameters->insertChild(aCurrentPos - 1, aCurrentItem);
569 selectItemScroll(aCurrentItem);
572 void ParametersPlugin_WidgetParamsMgr::onDown()
574 QTreeWidgetItem* aCurrentItem = selectedItem();
578 int aCurrentPos = myParameters->indexOfChild(aCurrentItem);
579 if (aCurrentPos == (myParametersList.count() - 1))
581 FeaturePtr aCurFeature = myParametersList.at(aCurrentPos);
583 SessionPtr aMgr = ModelAPI_Session::get();
584 std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
585 aDoc->moveFeature(aCurFeature, myParametersList.at(aCurrentPos + 1));
587 myParametersList.removeOne(aCurFeature);
588 myParametersList.insert(aCurrentPos + 1, aCurFeature);
590 myParameters->removeChild(aCurrentItem);
591 myParameters->insertChild(aCurrentPos + 1, aCurrentItem);
593 selectItemScroll(aCurrentItem);
597 bool ParametersPlugin_WidgetParamsMgr::hasName(const QString& theName) const
599 foreach(FeaturePtr aFeature, myParametersList) {
600 if (aFeature->data()->name() == theName.toStdString())
606 void ParametersPlugin_WidgetParamsMgr::sendWarning()
608 QMessageBox::warning(this, tr("Warning"), myMessage);
611 void ParametersPlugin_WidgetParamsMgr::onSelectionChanged()
613 QList<QTreeWidgetItem*> aItemsList = myTable->selectedItems();
614 bool isParameter = false;
615 foreach(QTreeWidgetItem* aItem, aItemsList) {
616 if (aItem->parent() == myParameters) {
621 myInsertBtn->setEnabled(isParameter);
622 myRemoveBtn->setEnabled(isParameter);
623 myUpBtn->setEnabled(isParameter);
624 myDownBtn->setEnabled(isParameter);