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