]> SALOME platform Git repositories - modules/shaper.git/blob - src/ParametersPlugin/ParametersPlugin_WidgetParamsMgr.cpp
Salome HOME
Issue #3086: Avoid crash when FeatureInfo is null.
[modules/shaper.git] / src / ParametersPlugin / ParametersPlugin_WidgetParamsMgr.cpp
1 // Copyright (C) 2014-2019  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "ParametersPlugin_WidgetParamsMgr.h"
21 #include "ParametersPlugin_Parameter.h"
22 #include "ParametersPlugin_Validators.h"
23
24 #include <Events_InfoMessage.h>
25
26 #include <ModelAPI_ResultParameter.h>
27 #include <ModelAPI_AttributeString.h>
28 #include <ModelAPI_AttributeRefList.h>
29 #include <ModelAPI_AttributeDouble.h>
30 #include <ModelAPI_AttributeInteger.h>
31 #include <ModelAPI_Events.h>
32 #include <ModelAPI_Session.h>
33 #include <ModelAPI_Tools.h>
34 #include <ModelAPI_Expression.h>
35
36 #include <GeomDataAPI_Point.h>
37 #include <GeomDataAPI_Point2D.h>
38
39 #include <ModuleBase_Tools.h>
40
41 #include <Events_Loop.h>
42 #include <Config_PropManager.h>
43
44 #include <QLayout>
45 #include <QPushButton>
46 #include <QToolButton>
47 #include <QStyledItemDelegate>
48 #include <QPainter>
49 #include <QMessageBox>
50 #include <QTimer>
51 #include <QEvent>
52 #include <QKeyEvent>
53 #include <QDialogButtonBox>
54 #include <QShortcut>
55
56 enum ColumnType {
57   Col_Name,
58   Col_Equation,
59   Col_Result,
60   Col_Comment
61 };
62
63 const char* NoName = "<NoName>";
64 const char* NoValue = "<NoValue>";
65
66 /*!
67  * \ingroup GUI
68  * ItemDelegate object in order to redefine items behavior
69  */
70 class ParametersPlugin_ItemDelegate : public QStyledItemDelegate
71 {
72 public:
73   /// Constructor
74   /// \param thaParent a parent
75   ParametersPlugin_ItemDelegate(QObject* thaParent) :
76       QStyledItemDelegate(thaParent) {}
77
78   /// Redefinition of virtual method
79   /// \param painter a painter object
80   /// \param option the item options
81   /// \param index the current index
82   virtual void paint(QPainter* painter,
83     const QStyleOptionViewItem& option,
84     const QModelIndex& index ) const;
85
86   /// Redefinition of virtual method
87   /// \param parent a parent widget
88   /// \param option the item options
89   /// \param index the current index
90   virtual QWidget* createEditor(QWidget* parent,
91                                 const QStyleOptionViewItem& option,
92                                 const QModelIndex& index) const;
93
94   /// Returns True if the given index is editable item
95   /// \param theIndex an item index
96   bool isEditable(const QModelIndex& theIndex) const;
97
98   /// Returns currently editing index
99   QModelIndex editIndex() const { return myEditingIdx; }
100
101 private:
102   mutable QModelIndex myEditingIdx;
103 };
104
105 bool ParametersPlugin_ItemDelegate::isEditable(const QModelIndex& theIndex) const
106 {
107   QModelIndex aParent = theIndex.parent();
108   if (aParent.isValid() && (aParent.row() == 0)) {
109     if (theIndex.column() == 2)
110       return false;
111   } else
112     return false;
113   return true;
114 }
115
116 void ParametersPlugin_ItemDelegate::paint(QPainter* painter,
117                                           const QStyleOptionViewItem& option,
118                                           const QModelIndex& index ) const
119 {
120   QBrush aBrush = painter->brush();
121   QPen aPen = painter->pen();
122   //if (!isEditable(index))
123   //  painter->setBrush(Qt::lightGray);
124   if (!index.parent().isValid())
125     painter->setBrush(Qt::lightGray);
126
127   painter->setPen(Qt::lightGray);
128   painter->drawRect(option.rect);
129   painter->setPen(aPen);
130
131   QStyledItemDelegate::paint(painter, option, index);
132   painter->setBrush(aBrush);
133 }
134
135 QWidget* ParametersPlugin_ItemDelegate::createEditor(QWidget* parent,
136                                                      const QStyleOptionViewItem& option,
137                                                      const QModelIndex& index) const
138 {
139   myEditingIdx = index;
140   return QStyledItemDelegate::createEditor(parent, option, index);
141 }
142
143 /////////////////////////////////////////////////////////////////////////////////////////////////
144 void ParametersPlugin_TreeWidget::closeEditor(QWidget* theEditor,
145                                               QAbstractItemDelegate::EndEditHint theHint)
146 {
147   if (theHint == QAbstractItemDelegate::EditNextItem) {
148     QModelIndex aCurrent = currentIndex();
149     QModelIndex aParent = model()->index(0, 0);
150     int aNbRows = model()->rowCount(aParent);
151     QModelIndex aIdx;
152     switch (aCurrent.column()) {
153     case 0:
154       aIdx = model()->index(aCurrent.row(), 1, aParent);
155       break;
156     case 1:
157       if (aCurrent.row() < (aNbRows - 1))
158         aIdx = model()->index(aCurrent.row() + 1, 0, aParent);
159       else {
160         QTreeWidget::closeEditor(theEditor, QAbstractItemDelegate::NoHint);
161         return;
162       }
163       break;
164     case 3:
165       QTreeWidget::closeEditor(theEditor, theHint);
166       return;
167     }
168     if (aIdx.isValid()) {
169       QTreeWidget::closeEditor(theEditor, QAbstractItemDelegate::NoHint);
170       setCurrentIndex(aIdx);
171       edit(aIdx);
172       return;
173     }
174   }
175   QTreeWidget::closeEditor(theEditor, theHint);
176 }
177
178 /////////////////////////////////////////////////////////////////////////////////////////////////
179
180 ParametersPlugin_WidgetParamsMgr::ParametersPlugin_WidgetParamsMgr(QWidget* theParent,
181   const Config_WidgetAPI* theData)
182   : ModuleBase_ModelDialogWidget(theParent, theData),
183   isUpplyBlocked(false)
184 {
185   QVBoxLayout* aLayout = new QVBoxLayout(this);
186
187   myTable = new ParametersPlugin_TreeWidget(this);
188   myTable->setColumnCount(4);
189   QStringList aHeaders;
190   aHeaders << translate("Name") << translate("Expression")
191            << translate("Result") << translate("Comment");
192   myTable->setHeaderLabels(aHeaders);
193   myTable->setColumnWidth(Col_Name, 200);
194   myTable->setColumnWidth(Col_Equation, 100);
195   myTable->setColumnWidth(Col_Result, 80);
196   myTable->setColumnWidth(Col_Comment, 200);
197   myTable->setMinimumWidth(600);
198   myTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
199   myTable->setSelectionMode(QAbstractItemView::SingleSelection);
200
201   connect(myTable, SIGNAL(doubleClicked(const QModelIndex&)),
202           SLOT(onDoubleClick(const QModelIndex&)));
203   connect(myTable, SIGNAL(itemSelectionChanged()), SLOT(onSelectionChanged()));
204
205   myDelegate = new ParametersPlugin_ItemDelegate(myTable);
206   connect(myDelegate, SIGNAL(closeEditor(QWidget*, QAbstractItemDelegate::EndEditHint)),
207           SLOT(onCloseEditor(QWidget*, QAbstractItemDelegate::EndEditHint)));
208
209   myTable->setItemDelegate(myDelegate);
210   aLayout->addWidget(myTable);
211
212   // Define root nodes
213   QStringList aNames;
214   aNames<<translate("Parameters");
215   myParameters = new QTreeWidgetItem(aNames);
216   myParameters->setFlags(Qt::ItemIsEnabled);
217   myTable->addTopLevelItem(myParameters);
218
219   aNames.clear();
220   aNames<<translate("Features");
221   myFeatures = new QTreeWidgetItem(aNames);
222   myFeatures->setFlags(Qt::ItemIsEnabled);
223   myTable->addTopLevelItem(myFeatures);
224
225   QHBoxLayout* aBtnLayout = new QHBoxLayout(this);
226
227   myUpBtn = new QToolButton(this);
228   myUpBtn->setArrowType(Qt::UpArrow);
229   connect(myUpBtn, SIGNAL(clicked(bool)), SLOT(onUp()));
230   aBtnLayout->addWidget(myUpBtn);
231
232   myDownBtn = new QToolButton(this);
233   myDownBtn->setArrowType(Qt::DownArrow);
234   connect(myDownBtn, SIGNAL(clicked(bool)), SLOT(onDown()));
235   aBtnLayout->addWidget(myDownBtn);
236
237   aBtnLayout->addStretch();
238
239   myAddBtn = new QPushButton(translate("Add"), this);
240   connect(myAddBtn, SIGNAL(clicked(bool)), SLOT(onAdd()));
241   aBtnLayout->addWidget(myAddBtn);
242
243   QString aAddStr(Config_PropManager::string("Shortcuts", "add_parameter_shortcut").c_str());
244   if (aAddStr.isEmpty())
245     aAddStr = "Ctrl+A";
246
247   QShortcut* aAddShc = new QShortcut(QKeySequence(aAddStr), myAddBtn);
248   connect(aAddShc, SIGNAL(activated()), SLOT(onAdd()));
249
250   myInsertBtn = new QPushButton(translate("Insert"), this);
251   connect(myInsertBtn, SIGNAL(clicked(bool)), SLOT(onInsert()));
252   aBtnLayout->addWidget(myInsertBtn);
253
254   myRemoveBtn = new QPushButton(translate("Remove"), this);
255   connect(myRemoveBtn, SIGNAL(clicked(bool)), SLOT(onRemove()));
256   aBtnLayout->addWidget(myRemoveBtn);
257
258   aLayout->addLayout(aBtnLayout);
259
260   onSelectionChanged();
261 }
262
263 void ParametersPlugin_WidgetParamsMgr::setDialogButtons(QDialogButtonBox* theButtons)
264 {
265   ModuleBase_ModelDialogWidget::setDialogButtons(theButtons);
266
267   QWidget* aBtnParentWgt = myOkCancelBtn->parentWidget();
268   QHBoxLayout* aBtnParentLayout = dynamic_cast<QHBoxLayout*>(aBtnParentWgt->layout());
269
270   QPushButton* aPreviewBtn = new QPushButton(translate("See preview"), aBtnParentWgt);
271   aBtnParentLayout->insertWidget(0, aPreviewBtn);
272   aBtnParentLayout->insertStretch(1, 1);
273   connect(aPreviewBtn, SIGNAL(clicked(bool)), SLOT(onShowPreview()));
274 }
275
276
277 QList<QWidget*> ParametersPlugin_WidgetParamsMgr::getControls() const
278 {
279   QList<QWidget*> aList;
280
281   return aList;
282 }
283
284 void ParametersPlugin_WidgetParamsMgr::selectItemScroll(QTreeWidgetItem* aItem)
285 {
286   myTable->clearSelection();
287   QModelIndex aParent = myTable->model()->index(0, 0);
288   int aChildIdx = myParameters->indexOfChild(aItem);
289   QModelIndex aIndex = myTable->model()->index(aChildIdx, Col_Name, aParent);
290   myTable->selectionModel()->select(aIndex,
291     QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
292   myTable->scrollToItem(aItem);
293 }
294
295
296 bool ParametersPlugin_WidgetParamsMgr::storeValueCustom()
297 {
298   ParametersPlugin_ExpressionValidator aValidator;
299   std::list<std::string> aArgs;
300   std::string aAttrId = ParametersPlugin_Parameter::VARIABLE_ID();
301   Events_InfoMessage aErr;
302   int aId = 0;
303   foreach(FeaturePtr aFeature, myParametersList) {
304     if (!aValidator.isValid(aFeature->attribute(aAttrId), aArgs, aErr)) {
305       QMessageBox::warning(this, translate("Warning"), aErr.messageString().c_str());
306       selectItemScroll(myParameters->child(aId));
307       return false;
308     }
309     aId++;
310   }
311   // #2813 : make the current feature the latest in the document
312   std::list<FeaturePtr> allFeatures = myFeature->document()->allFeatures();
313   if (!allFeatures.empty()) {
314     myFeature->document()->setCurrentFeature(*(allFeatures.rbegin()), true);
315   }
316   return true;
317 }
318
319 bool ParametersPlugin_WidgetParamsMgr::restoreValueCustom()
320 {
321   return true;
322 }
323
324 void ParametersPlugin_WidgetParamsMgr::activateCustom()
325 {
326   updateParametersFeatures();
327   updateParametersPart();
328   updateFeaturesPart();
329
330   myFeatures->setExpanded(true);
331   myParameters->setExpanded(true);
332 }
333
334 void ParametersPlugin_WidgetParamsMgr::updateParametersFeatures()
335 {
336   myParametersList.clear();
337   FeaturePtr aFeature = feature();
338   DocumentPtr aDoc = aFeature->document();
339   ObjectPtr aObj;
340   FeaturePtr aParamFeature;
341   int aNbFeatures = aDoc->numInternalFeatures();
342   for (int i = 0; i < aNbFeatures; i++) {
343     aParamFeature = aDoc->internalFeature(i);
344     if (aParamFeature && aParamFeature->getKind() == ParametersPlugin_Parameter::ID()) {
345       myParametersList.append(aParamFeature);
346     }
347   }
348 }
349
350 void ParametersPlugin_WidgetParamsMgr::updateFeaturesPart()
351 {
352   QList<FeaturePtr> aFeatureList;
353   updateItem(myFeatures, featuresItems(myParametersList, aFeatureList));
354 }
355
356 void ParametersPlugin_WidgetParamsMgr::updateParametersPart()
357 {
358   updateItem(myParameters, parametersItems(myParametersList));
359   bool aIsValid = isValid();
360   enableButtons(aIsValid);
361 }
362
363
364 QList<QStringList> ParametersPlugin_WidgetParamsMgr::
365   featuresItems(const QList<FeaturePtr>& theFeatures, QList<FeaturePtr>& theFeatureList) const
366 {
367   QList<QStringList> aItemsList;
368   ResultParameterPtr aParam;
369   foreach(FeaturePtr aParameter, theFeatures) {
370     aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aParameter->firstResult());
371     const std::set<std::shared_ptr<ModelAPI_Attribute>>& aRefs = aParam->data()->refsToMe();
372     std::set<std::shared_ptr<ModelAPI_Attribute> >::const_iterator aIt;
373     for(aIt = aRefs.cbegin(); aIt != aRefs.cend(); aIt++) {
374       std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
375       FeaturePtr aReferenced = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
376       if (aReferenced.get() && (aReferenced != aParameter)) {
377         if (aReferenced->getKind() == ParametersPlugin_Parameter::ID()) {
378           // Find referenced feature Recursive
379           QList<FeaturePtr> aList;
380           aList.append(aReferenced);
381           QList<QStringList> aItems = featuresItems(aList, theFeatureList);
382           aItemsList.append(aItems);
383         } else {
384           if (!theFeatureList.contains(aReferenced)) {
385             QStringList aValNames;
386             aValNames << aReferenced->data()->name().c_str();
387
388             std::string aId = aAttr->attributeType();
389             if (aId == ModelAPI_AttributeDouble::typeId()) {
390               AttributeDoublePtr aDouble =
391                 std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aAttr);
392               aValNames << aDouble->text().c_str();
393               aValNames << QString::number(aDouble->value());
394             }
395             else if (aId == ModelAPI_AttributeInteger::typeId()) {
396               AttributeIntegerPtr aInt =
397                 std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(aAttr);
398               aValNames << aInt->text().c_str();
399               aValNames << QString::number(aInt->value());
400             }
401             else if (aId == GeomDataAPI_Point::typeId()) {
402               std::shared_ptr<GeomDataAPI_Point> aPnt =
403                 std::dynamic_pointer_cast<GeomDataAPI_Point>(aAttr);
404
405               QString aExpr = QString("%1,%2,%3").arg(aPnt->textX().c_str()).
406                 arg(aPnt->textY().c_str()).arg(aPnt->textZ().c_str());
407               aValNames << aExpr;
408
409               QString aRes = QString("%1,%2,%3").arg(aPnt->x()).arg(aPnt->y()).arg(aPnt->z());
410               aValNames << aRes;
411             }
412             else if (aId == GeomDataAPI_Point2D::typeId()) {
413               std::shared_ptr<GeomDataAPI_Point2D> aPnt =
414                 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aAttr);
415
416               QString aExpr = QString("%1,%2").arg(aPnt->textX().c_str()).
417                 arg(aPnt->textY().c_str());
418               aValNames << aExpr;
419
420               QString aRes = QString("%1,%2").arg(aPnt->x()).arg(aPnt->y());
421               aValNames << aRes;
422             }
423             aItemsList.append(aValNames);
424             theFeatureList.append(aReferenced);
425           }
426         }
427       }
428     }
429   }
430   return aItemsList;
431 }
432
433
434 QList<QStringList> ParametersPlugin_WidgetParamsMgr::
435   parametersItems(const QList<FeaturePtr>& theFeatures) const
436 {
437   std::list<std::string> aArgs;
438   std::string aErr;
439   QList<QStringList> aItemsList;
440   foreach(FeaturePtr aParameter, theFeatures) {
441     ResultPtr aParam = aParameter->firstResult();
442     QStringList aValues;
443
444     std::string aName = aParameter->string(ParametersPlugin_Parameter::VARIABLE_ID())->value();
445     if (aName.empty()) {
446       aValues << translate(NoName);
447     } else
448       aValues << aName.c_str();
449
450     std::string aExpr = aParameter->string(ParametersPlugin_Parameter::EXPRESSION_ID())->value();
451     if (aName.empty()) {
452       aValues << translate(NoValue);
453     } else
454       aValues << aExpr.c_str();
455
456     std::string aErr =
457       aParameter->data()->string(ParametersPlugin_Parameter::EXPRESSION_ERROR_ID())->value();
458     if (aErr.empty()) {
459       AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
460       aValues << QString::number(aValueAttribute->value());
461     } else {
462       aValues << aErr.c_str();
463     }
464     aValues << aParameter->string(ParametersPlugin_Parameter::COMMENT_ID())->value().c_str();
465     aItemsList.append(aValues);
466   }
467   return aItemsList;
468 }
469
470
471 void ParametersPlugin_WidgetParamsMgr::onDoubleClick(const QModelIndex& theIndex)
472 {
473   if (myDelegate->isEditable(theIndex)) {
474     myTable->setCurrentIndex(theIndex);
475     myTable->edit(theIndex);
476   }
477 }
478
479 void ParametersPlugin_WidgetParamsMgr::onCloseEditor(QWidget* theEditor,
480                                                      QAbstractItemDelegate::EndEditHint theHint)
481 {
482   FeaturePtr aFeature = myParametersList.at(myDelegate->editIndex().row());
483   QTreeWidgetItem* aItem = myParameters->child(myDelegate->editIndex().row());
484   int aColumn = myDelegate->editIndex().column();
485   QString aText = aItem->text(aColumn);
486   bool isModified = false;
487
488   switch (aColumn) {
489   case Col_Name:
490     {
491       AttributeStringPtr aStringAttr = aFeature->string(ParametersPlugin_Parameter::VARIABLE_ID());
492       if (!aText.isEmpty()) {
493         while (aText.indexOf(" ") != -1) {
494           aText.replace(" ", "");
495         }
496         if (hasName(aText)) {
497           myMessage = translate("Name '%1' already exists.").arg(aText);
498           QTimer::singleShot(50, this, SLOT(sendWarning()));
499           return;
500         }
501         aStringAttr->setValue(aText.toStdString());
502         isModified = true;
503       }
504     }
505     break;
506   case Col_Equation:
507     {
508       AttributeStringPtr aStringAttr =
509         aFeature->string(ParametersPlugin_Parameter::EXPRESSION_ID());
510       if (!aText.isEmpty()) {
511         if (aText != aStringAttr->value().c_str()) {
512           aStringAttr->setValue(aText.toStdString());
513           aFeature->execute();
514           isModified = true;
515         }
516       }
517     }
518     break;
519   case Col_Comment:
520     {
521       AttributeStringPtr aStringAttr = aFeature->string(ParametersPlugin_Parameter::COMMENT_ID());
522       aStringAttr->setValue(aText.toStdString());
523       isModified = true;
524     }
525     break;
526   }
527
528   if (!isModified)
529     return;
530   Events_Loop* aLoop = Events_Loop::loop();
531   aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
532   aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
533   aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
534
535   if (aColumn != Col_Comment)
536     updateParametersPart();
537   updateFeaturesPart();
538
539   onSelectionChanged();
540 }
541
542 void ParametersPlugin_WidgetParamsMgr::updateItem(QTreeWidgetItem* theItem,
543                                                   const QList<QStringList>& theFeaturesList)
544 {
545   if (theFeaturesList.count() != theItem->childCount()) {
546     if (theItem->childCount()  < theFeaturesList.count()) {
547       while (theItem->childCount() != theFeaturesList.count())
548         theItem->addChild(createNewItem(theItem));
549     } else {
550       while (theItem->childCount() != theFeaturesList.count())
551         theItem->removeChild(theItem->child(theItem->childCount() - 1));
552     }
553   }
554   int i = 0;
555   foreach(QStringList aFeature, theFeaturesList) {
556     int aCol = 0;
557     foreach(QString aText, aFeature) {
558       if (aText.length() > 0) {
559         theItem->child(i)->setText(aCol, aText);
560         theItem->child(i)->setToolTip(aCol, aText);
561       }
562       aCol++;
563     }
564     i++;
565   }
566 }
567
568 FeaturePtr ParametersPlugin_WidgetParamsMgr::createParameter() const
569 {
570   SessionPtr aMgr = ModelAPI_Session::get();
571   std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
572
573   FeaturePtr aFeature = aDoc->addFeature(ParametersPlugin_Parameter::ID());
574   if (aFeature.get()) {
575     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
576     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
577   }
578   return aFeature;
579 }
580
581
582 QTreeWidgetItem* ParametersPlugin_WidgetParamsMgr::createNewItem(QTreeWidgetItem* theParent) const
583 {
584   QStringList aValues;
585   aValues << translate(NoName);
586   aValues << translate(NoValue);
587
588   QTreeWidgetItem* aItem = new QTreeWidgetItem(aValues);
589   if (theParent == myParameters) {
590     aItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
591     aItem->setForeground(2, Qt::darkGray);
592   } else
593     aItem->setFlags(Qt::NoItemFlags);
594   return aItem;
595 }
596
597
598 void ParametersPlugin_WidgetParamsMgr::onAdd()
599 {
600   FeaturePtr aFeature = createParameter();
601   if (!aFeature.get())
602     return;
603
604   myParametersList.append(aFeature);
605   updateParametersPart();
606
607   QTreeWidgetItem* aItem = myParameters->child(myParameters->childCount() - 1);
608
609   myTable->scrollToItem(aItem);
610   myTable->setCurrentItem(aItem);
611   myTable->editItem(aItem);
612
613   enableButtons(false);
614 }
615
616 QTreeWidgetItem* ParametersPlugin_WidgetParamsMgr::selectedItem() const
617 {
618   QList<QTreeWidgetItem*> aItemsList = myTable->selectedItems();
619   if (aItemsList.count() == 0)
620     return 0;
621
622   QTreeWidgetItem* aCurrentItem = aItemsList.first();
623   if (aCurrentItem->parent() != myParameters)
624     return 0;
625
626   return aCurrentItem;
627 }
628
629
630 void ParametersPlugin_WidgetParamsMgr::onInsert()
631 {
632   QTreeWidgetItem* aCurrentItem = selectedItem();
633   if (!aCurrentItem)
634     return;
635
636   SessionPtr aMgr = ModelAPI_Session::get();
637   std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
638
639   FeaturePtr aNewFeature = createParameter();
640   if (!aNewFeature.get())
641     return;
642
643   int aCurrentPos = myParameters->indexOfChild(aCurrentItem);
644   if (aCurrentPos == 0) {
645     aDoc->moveFeature(aNewFeature, FeaturePtr());
646   } else {
647     FeaturePtr aCurFeature = myParametersList.at(aCurrentPos - 1);
648     aDoc->moveFeature(aNewFeature, aCurFeature);
649   }
650   updateParametersFeatures();
651   updateParametersPart();
652
653   myTable->scrollToItem(aCurrentItem);
654   myTable->setCurrentItem(aCurrentItem);
655   myTable->editItem(aCurrentItem);
656 }
657
658 void ParametersPlugin_WidgetParamsMgr::onRemove()
659 {
660   QTreeWidgetItem* aCurrentItem = selectedItem();
661   if (!aCurrentItem)
662     return;
663
664   SessionPtr aMgr = ModelAPI_Session::get();
665   std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
666
667   int aCurrentPos = myParameters->indexOfChild(aCurrentItem);
668   FeaturePtr aCurFeature = myParametersList.at(aCurrentPos);
669
670   QObjectPtrList anObjects;
671   anObjects.append(aCurFeature);
672
673   std::map<FeaturePtr, std::set<FeaturePtr> > aReferences;
674   std::set<FeaturePtr> aFeatures;
675   ModuleBase_Tools::convertToFeatures(anObjects, aFeatures);
676   ModelAPI_Tools::findAllReferences(aFeatures, aReferences);
677
678   std::set<FeaturePtr> aFeatureRefsToDelete;
679   if (ModuleBase_Tools::askToDelete(aFeatures, aReferences, this, aFeatureRefsToDelete)) {
680     if (!aFeatureRefsToDelete.empty())
681       aFeatures.insert(aFeatureRefsToDelete.begin(), aFeatureRefsToDelete.end());
682     ModelAPI_Tools::removeFeatures(aFeatures, false);
683
684     Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED));
685     Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY));
686     updateParametersFeatures();
687     updateFeaturesPart();
688     updateParametersPart();
689   }
690 }
691
692 void ParametersPlugin_WidgetParamsMgr::onUp()
693 {
694   QTreeWidgetItem* aCurrentItem = selectedItem();
695   if (!aCurrentItem)
696     return;
697
698   int aCurrentPos = myParameters->indexOfChild(aCurrentItem);
699   if (aCurrentPos == 0)
700     return;
701   FeaturePtr aCurFeature = myParametersList.at(aCurrentPos);
702
703   SessionPtr aMgr = ModelAPI_Session::get();
704   std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
705
706   if (aCurrentPos == 1)
707     aDoc->moveFeature(aCurFeature, FeaturePtr());
708   else
709     aDoc->moveFeature(aCurFeature, myParametersList.at(aCurrentPos - 2));
710
711   // add the updated also the feature that goes down
712   Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED));
713   static Events_ID EVENT_UPD = Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED);
714   ModelAPI_EventCreator::get()->sendUpdated(myParametersList.at(aCurrentPos - 1), EVENT_UPD);
715   Events_Loop::loop()->flush(EVENT_UPD);
716   Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED));
717   Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED));
718   Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY));
719   updateParametersFeatures();
720   updateParametersPart();
721   updateFeaturesPart();
722
723   if (aCurrentPos > 0) {
724     aCurrentItem = myParameters->child(aCurrentPos - 1);
725     myTable->setCurrentItem(aCurrentItem);
726     selectItemScroll(aCurrentItem);
727   }
728 }
729
730 void ParametersPlugin_WidgetParamsMgr::onDown()
731 {
732   QTreeWidgetItem* aCurrentItem = selectedItem();
733   if (!aCurrentItem)
734     return;
735
736   int aCurrentPos = myParameters->indexOfChild(aCurrentItem);
737   if (aCurrentPos == (myParametersList.count() - 1))
738     return;
739   FeaturePtr aCurFeature = myParametersList.at(aCurrentPos);
740
741   SessionPtr aMgr = ModelAPI_Session::get();
742   std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
743   aDoc->moveFeature(aCurFeature, myParametersList.at(aCurrentPos + 1));
744   // add the updated also the feature that goes up
745   static Events_ID EVENT_UPD = Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED);
746   ModelAPI_EventCreator::get()->sendUpdated(myParametersList.at(aCurrentPos + 1), EVENT_UPD);
747
748   Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED));
749   Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED));
750   Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED));
751   Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED));
752   Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY));
753   updateParametersFeatures();
754   updateParametersPart();
755   updateFeaturesPart();
756
757   if (aCurrentPos < myParameters->childCount() - 1) {
758     aCurrentItem = myParameters->child(aCurrentPos + 1);
759     myTable->setCurrentItem(aCurrentItem);
760     selectItemScroll(aCurrentItem);
761   }
762 }
763
764
765 bool ParametersPlugin_WidgetParamsMgr::hasName(const QString& theName) const
766 {
767   int aCurrent = myDelegate->editIndex().row();
768   int i = 0;
769   foreach(FeaturePtr aFeature, myParametersList) {
770     if ((i != aCurrent) && (aFeature->data()->name() == theName.toStdString()))
771       return true;
772     i++;
773   }
774   return false;
775 }
776
777 void ParametersPlugin_WidgetParamsMgr::sendWarning()
778 {
779   QMessageBox::warning(this, translate("Warning"), myMessage);
780   QTreeWidgetItem* aItem = myTable->currentItem();
781   if (aItem)
782     myTable->editItem(aItem);
783 }
784
785 void ParametersPlugin_WidgetParamsMgr::onSelectionChanged()
786 {
787   QList<QTreeWidgetItem*> aItemsList = myTable->selectedItems();
788   bool aIsValid = isValid();
789   if (aIsValid) {
790     bool isParameter = false;
791     foreach(QTreeWidgetItem* aItem, aItemsList) {
792       if (aItem->parent() == myParameters) {
793         isParameter = true;
794         break;
795       }
796     }
797     myInsertBtn->setEnabled(isParameter);
798     //myRemoveBtn->setEnabled(isParameter);
799     myUpBtn->setEnabled(isParameter);
800     myDownBtn->setEnabled(isParameter);
801   } else {
802     myInsertBtn->setEnabled(false);
803     //myRemoveBtn->setEnabled(false);
804     myUpBtn->setEnabled(false);
805     myDownBtn->setEnabled(false);
806   }
807   myRemoveBtn->setEnabled(!aItemsList.isEmpty());
808 }
809
810 void ParametersPlugin_WidgetParamsMgr::enableButtons(bool theEnable)
811 {
812   myAddBtn->setEnabled(theEnable);
813   if (theEnable)
814     onSelectionChanged();
815   else {
816     myInsertBtn->setEnabled(theEnable);
817     //myRemoveBtn->setEnabled(theEnable);
818     myUpBtn->setEnabled(theEnable);
819     myDownBtn->setEnabled(theEnable);
820   }
821   myOkCancelBtn->button(QDialogButtonBox::Ok)->setEnabled(theEnable);
822 }
823
824 bool ParametersPlugin_WidgetParamsMgr::isValid()
825 {
826   QTreeWidgetItem* aItem;
827   for(int i = 0; i < myParameters->childCount(); i++) {
828     aItem = myParameters->child(i);
829     if ((aItem->text(Col_Name) == NoName) ||
830         (aItem->text(Col_Equation) == translate(NoValue)) ||
831         (!ModelAPI_Expression::isVariable(aItem->text(Col_Name).toStdString())) ) {
832       return false;
833     }
834   }
835   return true;
836 }
837
838 void ParametersPlugin_WidgetParamsMgr::showEvent(QShowEvent* theEvent)
839 {
840   ModuleBase_ModelDialogWidget::showEvent(theEvent);
841   SessionPtr aMgr = ModelAPI_Session::get();
842   isUpplyBlocked = aMgr->isAutoUpdateBlocked();
843   aMgr->blockAutoUpdate(true);
844   Events_Loop* aLoop = Events_Loop::loop();
845   aLoop->flush(aLoop->eventByName(EVENT_AUTOMATIC_RECOMPUTATION_DISABLE));
846 }
847
848 void ParametersPlugin_WidgetParamsMgr::hideEvent(QHideEvent* theEvent)
849 {
850   ModuleBase_ModelDialogWidget::hideEvent(theEvent);
851   SessionPtr aMgr = ModelAPI_Session::get();
852   aMgr->blockAutoUpdate(isUpplyBlocked);
853 }
854
855 void ParametersPlugin_WidgetParamsMgr::onShowPreview()
856 {
857   SessionPtr aMgr = ModelAPI_Session::get();
858   aMgr->blockAutoUpdate(false);
859   aMgr->blockAutoUpdate(true);
860 }