Salome HOME
0c0ceac9b44396f82a11241839ab1bd1cc12cd34
[modules/geom.git] / src / CurveCreator / CurveCreator_Widget.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File:        CurveCreator_Widget.cxx
24 // Created:     Mon Jul  01 12:49:31 2013
25 // Author:      Sergey KHROMOV
26 //
27
28
29 #include <CurveCreator_Widget.h>
30 #include <CurveCreator_EditPntsWidget.h>
31 #include <CurveCreator_UndoOptsDlg.h>
32 #include <CurveCreator_EditPntDlg.h>
33 #include <CurveCreator_PointItem.h>
34 #include <QPushButton>
35 #include <QButtonGroup>
36 #include <QHBoxLayout>
37 #include <QListWidget>
38 #include <QGroupBox>
39 #include <QLabel>
40 #include <QLineEdit>
41 #include <QRadioButton>
42 #include <QComboBox>
43 #include <QCheckBox>
44
45 #define SECTION_ADD          0
46 #define SECTION_MODIFY       1
47 #define POLYLINE_INDEX       0
48 #define BSPLINE_INDEX        1
49 #define UNDO_REDO_DISABLED   0
50 #define UNDO_REDO_UNLIMITED -1
51
52 //=======================================================================
53 // function: Constructor
54 // purpose:
55 //=======================================================================
56 CurveCreator_Widget::CurveCreator_Widget(QWidget* parent,
57                                          CurveCreator_Curve *theCurve,
58                                          Qt::WindowFlags fl)
59   : QWidget          (parent, fl),
60     myEditor         (theCurve),
61     myDimension      (theCurve == NULL ?
62                        CurveCreator::Dim2d : theCurve->getDimension()),
63     myEnabledUndoLbl (NULL),
64     myBufSizeUndoLbl (NULL),
65     myUndoBtn        (NULL),
66     myRedoBtn        (NULL),
67     myUndoOptsBtn    (NULL),
68     myUndoOptsDlg    (NULL),
69     myAddSecGrp      (NULL),
70     mySecBtnGrp      (NULL),
71     mySecTypeCmbBox  (NULL),
72     mySecCloseChkBox (NULL),
73     mySecAddModifBtn (NULL),
74     mySecRmBtn       (NULL),
75     mySecJoinBtn     (NULL),
76     mySecJoinAllBtn  (NULL),
77     mySecClearBtn    (NULL),
78     mySecUpBtn       (NULL),
79     mySecDownBtn     (NULL),
80     mySecList        (NULL),
81     myEditSecPnts    (NULL),
82     myPntsGrp        (NULL),
83     myPntsList       (NULL),
84     myPntEditDlg     (NULL),
85     myEditPnts       (NULL),
86     myAddPntsBtn     (NULL),
87     myInsertPntsBtn  (NULL),
88     myRmPntsBtn      (NULL)
89 {
90   setWindowTitle(tr("CC_TITLE"));
91
92   // Set undo/redo options group
93   QGroupBox   *anUndoOptsGrp = new QGroupBox(tr("CC_UNDO_REDO_OPTIONS"));
94   QGridLayout *anUndoOptsLO  = new QGridLayout(anUndoOptsGrp);
95
96   myEnabledUndoLbl = new QLabel(tr("CC_UNDO_REDO_ENABLED"), anUndoOptsGrp);
97   myBufSizeUndoLbl = new QLabel(tr("CC_UNDO_REDO_BUFFER_SIZE"), anUndoOptsGrp);
98   myUndoOptsBtn    = new QPushButton(tr("CC_UNDO_REDO_MODIFY"), anUndoOptsGrp);
99   anUndoOptsLO->setMargin(9);
100   anUndoOptsLO->setSpacing(6);
101   anUndoOptsLO->addWidget(myEnabledUndoLbl, 0, 0);
102   anUndoOptsLO->addWidget(myBufSizeUndoLbl, 1, 0);
103   anUndoOptsLO->addWidget(myUndoOptsBtn,    0, 1, 2, 1);
104
105   // Set undo/redo group
106   QGroupBox   *anUndoRedoGrp     = new QGroupBox(tr("CC_UNDO_REDO_TITLE"));
107   QHBoxLayout *anUndoRedoLO      = new QHBoxLayout(anUndoRedoGrp);
108
109   myUndoBtn = new QPushButton(tr("CC_UNDO"), anUndoRedoGrp);
110   myRedoBtn = new QPushButton(tr("CC_REDO"), anUndoRedoGrp);
111   anUndoRedoLO->setMargin(9);
112   anUndoRedoLO->setSpacing(6);
113   anUndoRedoLO->addWidget(myUndoBtn,     0, Qt::AlignRight);
114   anUndoRedoLO->addWidget(myRedoBtn,     0, Qt::AlignLeft);
115   anUndoRedoLO->addWidget(anUndoOptsGrp, 0, Qt::AlignRight);
116
117   // Set section add/modification group.
118   myAddSecGrp = new QGroupBox(tr("CC_SECTION_ADD_TITLE"));
119
120   QGridLayout  *anAddSecLO      = new QGridLayout(myAddSecGrp);
121   QLabel       *aSectTypeLbl    =
122                 new QLabel(tr("CC_SECTION_TYPE"), myAddSecGrp);
123   QLabel       *aSecPntsLbl     =
124                 new QLabel(tr("CC_SECTION_POINTS_ADD_LBL"), myAddSecGrp);
125
126   mySecCloseChkBox = new QCheckBox(tr("CC_SECTION_CLOSED"), myAddSecGrp);
127   mySecTypeCmbBox  = new QComboBox(myAddSecGrp);
128   mySecAddModifBtn = new QPushButton(tr("CC_SECTION_NEW"), myAddSecGrp);
129   myEditSecPnts    = new CurveCreator_EditPntsWidget
130                 (myAddSecGrp, true, myDimension);
131   anAddSecLO->setMargin(9);
132   anAddSecLO->setSpacing(6);
133   anAddSecLO->addWidget(mySecCloseChkBox, 0, 0);
134   anAddSecLO->addWidget(aSectTypeLbl,     1, 0);
135   anAddSecLO->addWidget(mySecTypeCmbBox,  1, 1);
136   anAddSecLO->addWidget(aSecPntsLbl,      2, 0);
137   anAddSecLO->addWidget(myEditSecPnts,    2, 1);
138   anAddSecLO->addWidget(mySecAddModifBtn, 1, 3);
139
140   // Set section group
141   QGroupBox    *aSecGrp         = new QGroupBox(tr("CC_SECTION_TITLE"));
142   QGridLayout  *aSecLO          = new QGridLayout(aSecGrp);
143   QRadioButton *anAddSecRdBtn   =
144                new QRadioButton(tr("CC_SECTION_ADD_TITLE"), aSecGrp);
145   QRadioButton *aModifSecRdBtn  =
146                new QRadioButton(tr("CC_SECTION_MODIFY_TITLE"), aSecGrp);
147
148   mySecRmBtn      = new QPushButton(tr("CC_SECTION_REMOVE"), aSecGrp);
149   mySecJoinBtn    = new QPushButton(tr("CC_SECTION_JOIN"), aSecGrp);
150   mySecJoinAllBtn = new QPushButton(tr("CC_SECTION_JOIN_ALL"), aSecGrp);
151   mySecClearBtn   = new QPushButton(tr("CC_SECTION_CLEAR"), aSecGrp);
152   mySecUpBtn      = new QPushButton(tr("CC_SECTION_UP"), aSecGrp);
153   mySecDownBtn    = new QPushButton(tr("CC_SECTION_DOWN"), aSecGrp);
154   mySecBtnGrp     = new QButtonGroup(aSecGrp);
155   mySecList       = new QListWidget(aSecGrp);
156   aSecLO->setMargin(9);
157   aSecLO->setSpacing(6);
158   aSecLO->addWidget(anAddSecRdBtn,   0, 0);
159   aSecLO->addWidget(aModifSecRdBtn,  0, 1);
160   aSecLO->addWidget(myAddSecGrp,     1, 0, 1, 5);
161   aSecLO->addWidget(mySecRmBtn,      2, 0);
162   aSecLO->addWidget(mySecJoinBtn,    2, 1);
163   aSecLO->addWidget(mySecJoinAllBtn, 2, 2);
164   aSecLO->addWidget(mySecClearBtn,   2, 3);
165   aSecLO->addWidget(mySecUpBtn,      4, 4);
166   aSecLO->addWidget(mySecDownBtn,    5, 4);
167   aSecLO->addWidget(mySecList,       3, 0, 4, 4);
168   mySecBtnGrp->addButton(anAddSecRdBtn,  SECTION_ADD);
169   mySecBtnGrp->addButton(aModifSecRdBtn, SECTION_MODIFY);
170
171   // Set point add/modification group.
172   QGroupBox    *anAddPntsGrp   = new QGroupBox(tr("CC_POINTS_ADD_TITLE"));
173
174   QGridLayout  *anAddPntsLO    = new QGridLayout(anAddPntsGrp);
175   QLabel       *aPntsLbl       =
176                 new QLabel(tr("CC_POINTS_ADD_LBL"), anAddPntsGrp);
177
178   myEditPnts      = new CurveCreator_EditPntsWidget
179                             (anAddPntsGrp, false, myDimension);
180   myAddPntsBtn    = new QPushButton(tr("CC_POINTS_ADD"), anAddPntsGrp);
181   myInsertPntsBtn = new QPushButton(tr("CC_POINTS_INSERT"), anAddPntsGrp);
182   anAddPntsLO->setMargin(9);
183   anAddPntsLO->setSpacing(6);
184   anAddPntsLO->addWidget(aPntsLbl,        0, 0);
185   anAddPntsLO->addWidget(myEditPnts,      0, 1);
186   anAddPntsLO->addWidget(myAddPntsBtn,    0, 4);
187   anAddPntsLO->addWidget(myInsertPntsBtn, 1, 4);
188
189   // Set Points group
190   myPntsGrp = new QGroupBox(tr("CC_POINTS_TITLE"));
191
192   QGridLayout *aPntsLO = new QGridLayout(myPntsGrp);
193
194   myPntsList  = new QListWidget(myPntsGrp);
195   myRmPntsBtn = new QPushButton(tr("CC_POINTS_REMOVE"), myPntsGrp);
196   aPntsLO->setMargin(9);
197   aPntsLO->setSpacing(6);
198   aPntsLO->addWidget(anAddPntsGrp, 0, 0, 1, 4);
199   aPntsLO->addWidget(myRmPntsBtn,  1, 0);
200   aPntsLO->addWidget(myPntsList,   2, 0, 4, 4);
201
202   // Set main group
203   QGroupBox   *aMainGrp = new QGroupBox(tr("CC_TITLE"));
204   QGridLayout *aMainLO = new QGridLayout(aMainGrp);
205
206   aMainLO->setMargin(9);
207   aMainLO->setSpacing(6);
208   aMainLO->addWidget(anUndoRedoGrp, 0, 0, 1, 2);
209   aMainLO->addWidget(aSecGrp,       1, 0);
210   aMainLO->addWidget(myPntsGrp,     1, 1);
211
212   setLayout(aMainLO);
213
214   init();
215 }
216
217 //=======================================================================
218 // function: init
219 // purpose:
220 //=======================================================================
221 void CurveCreator_Widget::init()
222 {
223   // Initialize Undo/Redo group.
224   QString anUnlim = tr("CC_UNDO_REDO_UNLIMITED");
225
226   myEnabledUndoLbl->setText(tr("CC_UNDO_REDO_ENABLED"));
227   myBufSizeUndoLbl->setText(tr("CC_UNDO_REDO_BUFFER_SIZE").arg(anUnlim));
228   connect(myUndoOptsBtn, SIGNAL(clicked()), this, SLOT(undoOptionsChanged()));
229   connect(myUndoBtn, SIGNAL(clicked()), this, SLOT(undo()));
230   connect(myRedoBtn, SIGNAL(clicked()), this, SLOT(redo()));
231   updateUndoRedoButtons();
232
233   // Initialize sections group.
234   mySecBtnGrp->setExclusive(true);
235   mySecBtnGrp->button(SECTION_ADD)->setChecked(true);
236   connect(mySecBtnGrp, SIGNAL(buttonClicked(int)),
237           this, SLOT(addModifChanged(int)));
238
239   // Init section buttons.
240   mySecAddModifBtn->setEnabled(true);
241   mySecRmBtn->setEnabled(false);
242   mySecJoinBtn->setEnabled(false);
243   mySecJoinAllBtn->setEnabled(false);
244   mySecClearBtn->setEnabled(false);
245   mySecUpBtn->setEnabled(false);
246   mySecDownBtn->setEnabled(false);
247
248   connect(mySecAddModifBtn, SIGNAL(clicked()),this, SLOT(sectionAddOrModify()));
249   connect(mySecRmBtn,       SIGNAL(clicked()),this, SLOT(sectionRemove()));
250   connect(mySecJoinBtn,     SIGNAL(clicked()),this, SLOT(sectionJoin()));
251   connect(mySecJoinAllBtn,  SIGNAL(clicked()),this, SLOT(sectionJoinAll()));
252   connect(mySecClearBtn,    SIGNAL(clicked()),this, SLOT(sectionClear()));
253   connect(mySecUpBtn,       SIGNAL(clicked()),this, SLOT(sectionUp()));
254   connect(mySecDownBtn,     SIGNAL(clicked()),this, SLOT(sectionDown()));
255
256   // Init section input fields.
257   mySecCloseChkBox->setChecked(false);
258   mySecTypeCmbBox->addItem(tr("CC_SECTION_TYPE_POLYLINE"));
259   mySecTypeCmbBox->addItem(tr("CC_SECTION_TYPE_BSPLINE"));
260   mySecTypeCmbBox->setCurrentIndex(POLYLINE_INDEX);
261   myEditSecPnts->clear();
262
263   // Init sections list widget.
264   mySecList->setSelectionMode(QAbstractItemView::ExtendedSelection);
265
266   connect(this, SIGNAL(numberOfItemsChanged(QListWidget *)),
267           this, SLOT(onNumberOfItemsChanged(QListWidget *)));
268   initSections();
269   connect(mySecList, SIGNAL(itemSelectionChanged()),
270           this, SLOT(changeSecSelection()));
271
272   // Init points list widget.
273   myPntsGrp->setEnabled(false);
274   myPntsList->clear();
275   myPntsList->setSelectionMode(QAbstractItemView::ExtendedSelection);
276
277   connect(myPntsList, SIGNAL(itemSelectionChanged()),
278           this, SLOT(changePntsSelection()));
279   connect(myPntsList, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
280           this, SLOT(editPnt(QListWidgetItem *)));
281
282   // Init points buttons.
283   connect(myAddPntsBtn,    SIGNAL(clicked()),this, SLOT(pntsAdd()));
284   connect(myInsertPntsBtn, SIGNAL(clicked()),this, SLOT(pntsInsert()));
285   connect(myRmPntsBtn,     SIGNAL(clicked()),this, SLOT(pntsRemove()));
286
287   // Init edit points widgets.
288   myEditSecPnts->setPointsList(myPntsList);
289   myEditPnts->setPointsList(myPntsList);
290
291   // Set tab order
292   setTabOrder();
293 }
294
295 //=======================================================================
296 // function: initSections
297 // purpose:
298 //=======================================================================
299 void CurveCreator_Widget::initSections()
300 {
301   CurveCreator_Curve *aCurve = myEditor.getCurve();
302
303   const int aNbSections = aCurve->getNbSections();
304   int i;
305
306   mySecList->clear();
307
308   for (i = 0; i < aNbSections; i++) {
309     addSectionItem(aCurve->getType(i), aCurve->isClosed(i));
310   }
311
312   emit numberOfItemsChanged(mySecList);
313 }
314
315 //=======================================================================
316 // function: addSectionItem
317 // purpose:
318 //=======================================================================
319 void CurveCreator_Widget::addSectionItem(const CurveCreator::Type theType,
320                                          const bool isClosed)
321 {
322   const int aRow = mySecList->count();
323
324   new QListWidgetItem(mySecList);
325   updateSectionItem(aRow, theType, isClosed);
326   emit numberOfItemsChanged(mySecList);
327 }
328
329 //=======================================================================
330 // function: updateSectionItem
331 // purpose:
332 //=======================================================================
333 void CurveCreator_Widget::updateSectionItem(const int theRow,
334                                             const CurveCreator::Type theType,
335                                             const bool isClosed)
336 {
337   QListWidgetItem *anItem = mySecList->item(theRow);
338   QString          aStrType;
339
340   if (theType == CurveCreator::Polyline) {
341     aStrType = tr("CC_SECTION_ITEM_POLYLINE");
342   } else {
343     aStrType = tr("CC_SECTION_ITEM_BSPLINE");
344   }
345
346   const QString aTrCode =
347     (isClosed ? "CC_SECTION_ITEM_CLOSED" : "CC_SECTION_ITEM");
348
349   anItem->setText(tr(aTrCode.toLatin1().constData()).arg(aStrType));
350 }
351
352 //=======================================================================
353 // function: sectionMove
354 // purpose:
355 //=======================================================================
356 void CurveCreator_Widget::sectionMove(const int theShift)
357 {
358   // Sort list items in ascending or descending order depending on
359   // the sign of theShift.
360   QList<QListWidgetItem *> aListItems = mySecList->selectedItems();
361
362   if (!aListItems.empty() && theShift != 0) {
363     QMap<int, QListWidgetItem *> aMapItems;
364
365     foreach(QListWidgetItem *anItem, aListItems) {
366       int aRow = mySecList->row(anItem);
367
368       if (theShift > 0) {
369         aRow = -aRow;
370       }
371
372       aMapItems.insert(aRow, anItem);
373     }
374
375     // Compute new rows
376     QList<int> aListRows = aMapItems.keys();
377     QList<int> aListNewRows;
378     int i;
379     const int aSize = aListRows.size();
380
381
382     if (theShift < 0) {
383       // Check each row to be positive.
384       int aMinIndex = 0;
385
386       for (i = 0; i < aSize; i++) {
387         int aRow = aListRows[i] + theShift;
388
389         if (aRow < aMinIndex) {
390           aRow = aMinIndex++;
391         }
392
393         aListNewRows.append(aRow);
394       }
395     } else {
396       // Check each row to be not greater then a mySecList's size.
397       int aMaxIndex = mySecList->count() - 1;
398
399       for (i = 0; i < aSize; i++) {
400         int aRow = -aListRows[i] + theShift;
401
402         if (aRow > aMaxIndex) {
403           aRow = aMaxIndex--;
404         }
405
406         aListRows[i] = -aListRows[i];
407         aListNewRows.append(aRow);
408       }
409     }
410
411     // Move each item to another position.
412     for (i = 0; i < aSize; i++) {
413       if (aListRows[i] != aListNewRows[i]) {
414         QListWidgetItem *anItem = mySecList->takeItem(aListRows[i]);
415
416         // Move section.
417         mySecList->insertItem(aListNewRows[i], anItem);
418         myEditor.moveSection(aListRows[i], aListNewRows[i]);
419       }
420     }
421
422     // Select added items.
423     foreach (int anIndex, aListNewRows) {
424       mySecList->item(anIndex)->setSelected(true);
425     }
426
427     // Update undo/redo buttons.
428     updateUndoRedoButtons();
429   }
430 }
431
432 //=======================================================================
433 // function: initPoints
434 // purpose:
435 //=======================================================================
436 void CurveCreator_Widget::initPoints(const int theSectionIndex)
437 {
438   // Clear the points list
439   const int aNbPnts = myPntsList->count();
440
441   myPntsList->clear();
442
443   if (theSectionIndex < 0) {
444     if (aNbPnts > 0) {
445       emit numberOfItemsChanged(myPntsList);
446     }
447   } else {
448     // Fill the points list with the points of the section.
449     const CurveCreator::Coordinates &aPoints =
450         myEditor.getCurve()->getPoints(theSectionIndex);
451     const int aNbCoords = aPoints.size();
452
453     if (aNbCoords % myDimension == 0) {
454       int i = 0;
455
456       while (i < aNbCoords) {
457         const CurveCreator::TypeCoord aX = aPoints[i++];
458         const CurveCreator::TypeCoord aY = aPoints[i++];
459
460         if (myDimension == CurveCreator::Dim3d) {
461           const CurveCreator::TypeCoord aZ = aPoints[i++];
462
463           new CurveCreator_PointItem(aX, aY, aZ, myPntsList);
464         } else {
465           new CurveCreator_PointItem(aX, aY, myPntsList);
466         }
467       }
468     }
469
470     if (aNbPnts != aNbCoords/myDimension) {
471       emit numberOfItemsChanged(myPntsList);
472     }
473   }
474 }
475
476 //=======================================================================
477 // function: getCurrentSectionIndex
478 // purpose:
479 //=======================================================================
480 int CurveCreator_Widget::getCurrentSectionIndex()
481 {
482   int anIndex = -1;
483   QList<QListWidgetItem *> aListSec = mySecList->selectedItems();
484
485   if (aListSec.size() == 1) {
486     anIndex = mySecList->row(aListSec.first());
487   }
488
489   return anIndex;
490 }
491
492 //=======================================================================
493 // function: updateUndoRedo
494 // purpose:
495 //=======================================================================
496 void CurveCreator_Widget::updateUndoRedo()
497 {
498   // Update undo/redo buttons.
499   updateUndoRedoButtons();
500
501   // Update sections.
502   CurveCreator_Curve *aCurve = myEditor.getCurve();
503   const bool isKeepSelection = (mySecList->count() == aCurve->getNbSections());
504   QList<int> aSelectedRows;
505   QList<QListWidgetItem *> aListItems = mySecList->selectedItems();
506
507   if (isKeepSelection) {
508     foreach (QListWidgetItem *anItem, aListItems) {
509       aSelectedRows.append(mySecList->row(anItem));
510     }
511   }
512
513   initSections();
514
515   // Set selection.
516   if (isKeepSelection) {
517     foreach (int aRow, aSelectedRows) {
518       mySecList->item(aRow)->setSelected(true);
519     }
520   }
521
522   changeSecSelection();
523 }
524
525 //=======================================================================
526 // function: updateUndoRedoButtons
527 // purpose:
528 //=======================================================================
529 void CurveCreator_Widget::updateUndoRedoButtons()
530 {
531   // Update undo/redo buttons.
532   const int anUndoDepth = myEditor.getUndoDepth();
533
534   if (anUndoDepth == UNDO_REDO_DISABLED) {
535     myUndoBtn->setEnabled(false);
536     myRedoBtn->setEnabled(false);
537   } else {
538     myUndoBtn->setEnabled(myEditor.getNbUndo() > 0);
539     myRedoBtn->setEnabled(myEditor.getNbRedo() > 0);
540   }
541 }
542
543
544 //=======================================================================
545 // function: setTabOrder
546 // purpose:
547 //=======================================================================
548 void CurveCreator_Widget::setTabOrder()
549 {
550   QWidget::setTabOrder(myUndoBtn, myRedoBtn);
551   QWidget::setTabOrder(myRedoBtn, myUndoOptsBtn);
552   QWidget::setTabOrder(myUndoOptsBtn, mySecBtnGrp->button(SECTION_ADD));
553   QWidget::setTabOrder(mySecBtnGrp->button(SECTION_ADD),
554                        mySecBtnGrp->button(SECTION_MODIFY));
555   QWidget::setTabOrder(mySecBtnGrp->button(SECTION_MODIFY), mySecCloseChkBox);
556   QWidget::setTabOrder(mySecCloseChkBox, mySecTypeCmbBox);
557   QWidget::setTabOrder(mySecTypeCmbBox, myEditSecPnts->getPointsEdit());
558   QWidget::setTabOrder(myEditSecPnts->getPointsEdit(),
559                        myEditSecPnts->getPointsButton());
560   QWidget::setTabOrder(myEditSecPnts->getPointsButton(), mySecAddModifBtn);
561   QWidget::setTabOrder(mySecAddModifBtn, mySecRmBtn);
562   QWidget::setTabOrder(mySecRmBtn, mySecJoinBtn);
563   QWidget::setTabOrder(mySecJoinBtn, mySecJoinAllBtn);
564   QWidget::setTabOrder(mySecJoinAllBtn, mySecClearBtn);
565   QWidget::setTabOrder(mySecClearBtn, mySecList);
566   QWidget::setTabOrder(mySecList, mySecUpBtn);
567   QWidget::setTabOrder(mySecUpBtn, mySecDownBtn);
568   QWidget::setTabOrder(mySecDownBtn, myEditPnts->getPointsEdit());
569   QWidget::setTabOrder(myEditPnts->getPointsEdit(),
570                        myEditPnts->getPointsButton());
571   QWidget::setTabOrder(myEditPnts->getPointsButton(), myAddPntsBtn);
572   QWidget::setTabOrder(myAddPntsBtn, myInsertPntsBtn);
573   QWidget::setTabOrder(myInsertPntsBtn, myRmPntsBtn);
574   QWidget::setTabOrder(myRmPntsBtn, myPntsList);
575 }
576
577 //=======================================================================
578 // function: undoOptionsChanged
579 // purpose:
580 //=======================================================================
581 void CurveCreator_Widget::undoOptionsChanged()
582 {
583   if (myUndoOptsDlg == NULL) {
584     // Create the dialog.
585     myUndoOptsDlg = new CurveCreator_UndoOptsDlg(this);
586   }
587
588   // set undo depth.
589   myUndoOptsDlg->setUndoDepth(myEditor.getUndoDepth());
590
591   const int aResult = myUndoOptsDlg->exec();
592
593   if (aResult == QDialog::Accepted) {
594     // Get undo depth.
595     const int  anUndoDepth = myUndoOptsDlg->getUndoDepth();
596     const bool isEnabled   = myUndoOptsDlg->isEnabled();
597
598     myEditor.setUndoDepth(anUndoDepth);
599
600     // Update options labels.
601     myBufSizeUndoLbl->setVisible(isEnabled);
602
603     if (isEnabled) {
604       QString aSize;
605
606       if (myUndoOptsDlg->isUnlimited()) {
607         aSize = tr("CC_UNDO_REDO_UNLIMITED");
608       } else {
609         aSize = QString::number(anUndoDepth);
610       }
611
612       myEnabledUndoLbl->setText(tr("CC_UNDO_REDO_ENABLED"));
613       myBufSizeUndoLbl->setText(tr("CC_UNDO_REDO_BUFFER_SIZE").arg(aSize));
614     } else {
615       myEnabledUndoLbl->setText(tr("CC_UNDO_REDO_DISABLED"));
616     }
617   }
618
619   // Update Undo Redo buttons.
620   updateUndoRedoButtons();
621 }
622
623 //=======================================================================
624 // function: sectionAddOrModify
625 // purpose:
626 //=======================================================================
627 void CurveCreator_Widget::sectionAddOrModify()
628 {
629   const bool         isClosed = mySecCloseChkBox->isChecked();
630   CurveCreator::Type aType;
631
632   if (mySecTypeCmbBox->currentIndex() == POLYLINE_INDEX) {
633     aType = CurveCreator::Polyline;
634   } else {
635     aType = CurveCreator::BSpline;
636   }
637
638   if (mySecBtnGrp->checkedId() == SECTION_MODIFY) {
639     // Modify section mode.
640     QList<QListWidgetItem *> aListItems = mySecList->selectedItems();
641
642     if (aListItems.size() == 1) {
643       const int           aRow       = mySecList->row(aListItems.first());
644       bool                isModified = false;
645       CurveCreator_Curve *aCurve     = myEditor.getCurve();
646
647
648       if (aCurve->getType(aRow) != aType) {
649         // Set type.
650         isModified = true;
651         myEditor.setType(aType, aRow);
652       }
653
654       if (aCurve->isClosed(aRow) != isClosed) {
655         // Set closed flag.
656         isModified = true;
657         myEditor.setClosed(isClosed, aRow);
658       }
659
660       if (isModified) {
661         updateSectionItem(aRow, aType, isClosed);
662
663         // Update undo/redo buttons.
664         updateUndoRedoButtons();
665       }
666     }
667   } else {
668     // Add section mode. Add section.
669     myEditor.addSection(aType, isClosed, myEditSecPnts->getPoints());
670     addSectionItem(aType, isClosed);
671
672     // Update undo/redo buttons.
673     updateUndoRedoButtons();
674   }
675 }
676
677 //=======================================================================
678 // function: secButtonClicked
679 // purpose:
680 //=======================================================================
681 void CurveCreator_Widget::addModifChanged(int theId)
682 {
683   if (theId == SECTION_ADD) {
684     // Add section
685     myAddSecGrp->setTitle(tr("CC_SECTION_ADD_TITLE"));
686     mySecAddModifBtn->setText(tr("CC_SECTION_NEW"));
687     myEditSecPnts->setEnabled(true);
688     mySecAddModifBtn->setEnabled(true);
689   } else {
690     // Modify section
691     myAddSecGrp->setTitle(tr("CC_SECTION_MODIFICATION_TITLE"));
692     mySecAddModifBtn->setText(tr("CC_SECTION_MODIFY"));
693     myEditSecPnts->setEnabled(false);
694     changeSecSelection();
695   }
696 }
697
698 //=======================================================================
699 // function: changeSecSelection
700 // purpose:
701 //=======================================================================
702 void CurveCreator_Widget::changeSecSelection()
703 {
704   // Update modify button and section data.
705   QList<QListWidgetItem *> aListItems = mySecList->selectedItems();
706   const int aNbItems = aListItems.size();
707
708   if (mySecBtnGrp->checkedId() == SECTION_MODIFY) {
709     // Modify section mode.
710     if (aNbItems == 1) {
711       // Initialize type and closed flags.
712       CurveCreator_Curve *aCurve  = myEditor.getCurve();
713       const int           anIndex = mySecList->row(aListItems.first());
714
715       mySecAddModifBtn->setEnabled(true);
716       mySecCloseChkBox->setChecked(aCurve->isClosed(anIndex));
717
718       if (aCurve->getType(anIndex) == CurveCreator::Polyline) {
719         mySecTypeCmbBox->setCurrentIndex(POLYLINE_INDEX);
720       } else {
721         mySecTypeCmbBox->setCurrentIndex(BSPLINE_INDEX);
722       }
723     } else if (mySecAddModifBtn->isEnabled()) {
724       mySecAddModifBtn->setEnabled(false);
725     }
726   } else {
727     // Add section mode.
728     mySecAddModifBtn->setEnabled(true);
729   }
730
731   // Set enabled remove, up and down points.
732   bool isEnabled = (aNbItems > 0);
733   const int aCount = mySecList->count();
734
735   mySecRmBtn->setEnabled(isEnabled);
736   isEnabled &= (aNbItems < aCount);
737   mySecUpBtn->setEnabled(isEnabled);
738   mySecDownBtn->setEnabled(isEnabled);
739   mySecJoinBtn->setEnabled(aNbItems == 2);
740
741   // Init points.
742   myPntsGrp->setEnabled(aNbItems == 1);
743
744   if (aNbItems == 1) {
745     const int aSecIndex = mySecList->row(aListItems.first());
746
747     initPoints(aSecIndex);
748   } else {
749     initPoints(-1);
750   }
751 }
752
753 //=======================================================================
754 // function: sectionRemove
755 // purpose:
756 //=======================================================================
757 void CurveCreator_Widget::sectionRemove()
758 {
759   QList<QListWidgetItem *> aListItems = mySecList->selectedItems();
760
761   if (!aListItems.empty()) {
762     QList<int> aListRows;
763
764     // Get items rows.
765     foreach(QListWidgetItem *anItem, aListItems) {
766       aListRows.append(mySecList->row(anItem));
767     }
768
769     // Delete items.
770     foreach(QListWidgetItem *anItem, aListItems) {
771       delete anItem;
772     }
773
774     qSort(aListRows);
775
776     // Delete points from curve.
777     const int aNbPnts = aListRows.size();
778     int       i;
779
780     for (i = aNbPnts - 1; i >= 0; i--) {
781       myEditor.removeSection(aListRows[i]);
782     }
783
784     // Set the new selection.
785     int aRow = aListRows[0];
786
787     if (aListRows[0] >= mySecList->count()) {
788       aRow = mySecList->count() - 1;
789     }
790
791     if (aRow >= 0) {
792       mySecList->item(aRow)->setSelected(true);
793     }
794
795     emit numberOfItemsChanged(mySecList);
796
797     // Update undo/redo buttons.
798     updateUndoRedoButtons();
799   }
800 }
801
802 //=======================================================================
803 // function: sectionJoin
804 // purpose:
805 //=======================================================================
806 void CurveCreator_Widget::sectionJoin()
807 {
808   QList<QListWidgetItem *> aListItems = mySecList->selectedItems();
809
810   if (aListItems.size() == 2) {
811     int aRowTo   = mySecList->row(aListItems.first());
812     int aRowFrom = mySecList->row(aListItems.last());
813
814     if (aRowTo > aRowFrom) {
815       // Swap rows.
816       int aTmp = aRowTo;
817
818       aRowTo   = aRowFrom;
819       aRowFrom = aTmp;
820     }
821
822     // Join two sections.
823     myEditor.join(aRowTo, aRowFrom);
824     delete mySecList->takeItem(aRowFrom);
825     emit numberOfItemsChanged(mySecList);
826     // Select the joined item.
827     mySecList->item(aRowTo)->setSelected(true);
828     changeSecSelection();
829
830     // Update undo/redo buttons.
831     updateUndoRedoButtons();
832   }
833 }
834
835 //=======================================================================
836 // function: sectionJoinAll
837 // purpose:
838 //=======================================================================
839 void CurveCreator_Widget::sectionJoinAll()
840 {
841   const int aNbItems = mySecList->count();
842
843   if (aNbItems > 1) {
844     // Join two sections.
845     myEditor.join();
846
847     // Update mySecList.
848     for (int i = 1; i < aNbItems; i++) {
849       delete mySecList->takeItem(1);
850     }
851
852     emit numberOfItemsChanged(mySecList);
853     // Select the joined item.
854     mySecList->item(0)->setSelected(true);
855     changeSecSelection();
856
857     // Update undo/redo buttons.
858     updateUndoRedoButtons();
859   }
860 }
861
862 //=======================================================================
863 // function: sectionClear
864 // purpose:
865 //=======================================================================
866 void CurveCreator_Widget::sectionClear()
867 {
868   bool isEmpty = (mySecList->count() == 0);
869
870   if (!isEmpty) {
871     mySecList->clear();
872     myEditor.clear();
873     emit numberOfItemsChanged(mySecList);
874
875     // Update undo/redo buttons.
876     updateUndoRedoButtons();
877   }
878 }
879
880 //=======================================================================
881 // function: sectionUp
882 // purpose:
883 //=======================================================================
884 void CurveCreator_Widget::sectionUp()
885 {
886   sectionMove(-1);
887 }
888
889 //=======================================================================
890 // function: sectionDown
891 // purpose:
892 //=======================================================================
893 void CurveCreator_Widget::sectionDown()
894 {
895   sectionMove(1);
896 }
897
898 //=======================================================================
899 // function: onNumberOfItemsChanged
900 // purpose:
901 //=======================================================================
902 void CurveCreator_Widget::onNumberOfItemsChanged(QListWidget *theListWidget)
903 {
904   if (theListWidget == mySecList) {
905     // List of sections is modified.
906     mySecJoinAllBtn->setEnabled(mySecList->count() > 1);
907     mySecClearBtn->setEnabled(mySecList->count() > 0);
908   } else {
909     // List of points is modified.
910     QList<QListWidgetItem *> aListItems = myPntsList->selectedItems();
911     const int aNbItems = aListItems.size();
912
913     myRmPntsBtn->setEnabled(aNbItems > 0);
914   }
915 }
916
917 //=======================================================================
918 // function: changePntsSelection
919 // purpose:
920 //=======================================================================
921 void CurveCreator_Widget::changePntsSelection()
922 {
923   // Update modify buttons and section data.
924   QList<QListWidgetItem *> aListItems = myPntsList->selectedItems();
925   const int aNbItems = aListItems.size();
926   const int aCount   = myPntsList->count();
927
928   myRmPntsBtn->setEnabled(aNbItems > 0);
929   myInsertPntsBtn->setEnabled(aCount == 0 || aNbItems == 1);
930 }
931
932 //=======================================================================
933 // function: editPnt
934 // purpose:
935 //=======================================================================
936 void CurveCreator_Widget::editPnt(QListWidgetItem *theItem)
937 {
938   if (theItem != NULL) {
939     if (myPntEditDlg == NULL) {
940       // Create the dialog.
941       myPntEditDlg = new CurveCreator_EditPntDlg(this, myDimension);
942     }
943
944     // Get coordinates.
945     CurveCreator_PointItem    *aPntItem = (CurveCreator_PointItem *)theItem;
946     CurveCreator::Coordinates  aPoint;
947
948     aPoint.push_back(aPntItem->getX());
949     aPoint.push_back(aPntItem->getY());
950
951     if (myDimension == CurveCreator::Dim3d) {
952       aPoint.push_back(aPntItem->getZ());
953     }
954
955     myPntEditDlg->setPoint(aPoint);
956
957     const int aResult = myPntEditDlg->exec();
958
959     if (aResult == QDialog::Accepted) {
960       // Get the section index.
961       const int aSectionIndex = getCurrentSectionIndex();
962
963       if (aSectionIndex >= 0) {
964         // Update the point.
965         const CurveCreator::Coordinates &aNewPoint = myPntEditDlg->getPoint();
966
967         if (myDimension == CurveCreator::Dim3d) {
968           aPntItem->setCoord(aNewPoint[0], aNewPoint[1], aNewPoint[2]);
969         } else {
970           aPntItem->setCoord(aNewPoint[0], aNewPoint[1]);
971         }
972
973         // Update curve
974         const int aPntIndex = myPntsList->row(theItem);
975
976         myEditor.setCoordinates(aNewPoint, aSectionIndex, aPntIndex);
977
978         // Update undo/redo buttons.
979         updateUndoRedoButtons();
980       }
981     }
982   }
983 }
984
985 //=======================================================================
986 // function: pntsAdd
987 // purpose:
988 //=======================================================================
989 void CurveCreator_Widget::pntsAdd()
990 {
991   const CurveCreator::Coordinates &aNewPoints = myEditPnts->getPoints();
992   const int                        aNbCoords  = aNewPoints.size();
993
994   if (aNbCoords > 0 && aNbCoords % myDimension == 0) {
995     // Get the section index.
996     const int aSectionIndex = getCurrentSectionIndex();
997
998     if (aSectionIndex >= 0) {
999       // Update list.
1000       int i = 0;
1001
1002       while (i < aNbCoords) {
1003         const CurveCreator::TypeCoord aX = aNewPoints[i++];
1004         const CurveCreator::TypeCoord aY = aNewPoints[i++];
1005
1006         if (myDimension == CurveCreator::Dim3d) {
1007           const CurveCreator::TypeCoord aZ = aNewPoints[i++];
1008
1009           new CurveCreator_PointItem(aX, aY, aZ, myPntsList);
1010         } else {
1011           new CurveCreator_PointItem(aX, aY, myPntsList);
1012         }
1013       }
1014
1015       // Update curve
1016       myEditor.addPoints(aNewPoints, aSectionIndex);
1017       emit numberOfItemsChanged(myPntsList);
1018
1019       // Update undo/redo buttons.
1020       updateUndoRedoButtons();
1021     }
1022   }
1023 }
1024
1025 //=======================================================================
1026 // function: pntsInsert
1027 // purpose:
1028 //=======================================================================
1029 void CurveCreator_Widget::pntsInsert()
1030 {
1031   const CurveCreator::Coordinates &aNewPoints = myEditPnts->getPoints();
1032   const int                        aNbCoords  = aNewPoints.size();
1033
1034   if (aNbCoords > 0 && aNbCoords % myDimension == 0) {
1035     // Get the section index.
1036     const int aSectionIndex = getCurrentSectionIndex();
1037
1038     if (aSectionIndex >= 0) {
1039       // Get the selected point index.
1040       int aPntIndex = -1;
1041       QList<QListWidgetItem *> aListPnts = myPntsList->selectedItems();
1042
1043       if (aListPnts.size() == 1) {
1044         aPntIndex = myPntsList->row(aListPnts.first());
1045       }
1046
1047       // Update list.
1048       int i = 0;
1049       int aRow = aPntIndex;
1050
1051       while (i < aNbCoords) {
1052         const CurveCreator::TypeCoord  aX       = aNewPoints[i++];
1053         const CurveCreator::TypeCoord  aY       = aNewPoints[i++];
1054         CurveCreator_PointItem        *aNewItem = NULL;
1055
1056         if (myDimension == CurveCreator::Dim3d) {
1057           const CurveCreator::TypeCoord aZ = aNewPoints[i++];
1058
1059           aNewItem = new CurveCreator_PointItem(aX, aY, aZ);
1060         } else {
1061           aNewItem = new CurveCreator_PointItem(aX, aY);
1062         }
1063
1064
1065         if (aPntIndex < 0) {
1066           // Append point.
1067           myPntsList->addItem(aNewItem);
1068         } else {
1069           // Insert point.
1070           myPntsList->insertItem(aRow++, aNewItem);
1071         }
1072       }
1073
1074       // Update curve
1075       myEditor.insertPoints(aNewPoints, aSectionIndex, aPntIndex);
1076       emit numberOfItemsChanged(myPntsList);
1077
1078       // Update undo/redo buttons.
1079       updateUndoRedoButtons();
1080     }
1081   }
1082 }
1083
1084 //=======================================================================
1085 // function: pntsRemove
1086 // purpose:
1087 //=======================================================================
1088 void CurveCreator_Widget::pntsRemove()
1089 {
1090   QList<QListWidgetItem *> aListItems    = myPntsList->selectedItems();
1091   const int                aSectionIndex = getCurrentSectionIndex();
1092
1093   if (aSectionIndex >= 0 && aListItems.size() > 0) {
1094     QList<int> aListRows;
1095
1096     // Get items rows.
1097     foreach(QListWidgetItem *anItem, aListItems) {
1098       aListRows.append(myPntsList->row(anItem));
1099     }
1100
1101     // Delete items.
1102     foreach(QListWidgetItem *anItem, aListItems) {
1103       delete anItem;
1104     }
1105
1106     qSort(aListRows);
1107
1108     // Delete points from curve.
1109     const int aNbPnts   = aListRows.size();
1110     int       aNbPntsRm = 1;
1111     int       aCurRow   = aListRows.last();
1112     int       i;
1113
1114     for (i = aNbPnts - 2; i >= 0; i--) {
1115       if (aListRows[i] == aCurRow - 1) {
1116         // This is the previous index.
1117         aCurRow--;
1118         aNbPntsRm++;
1119       } else {
1120         // This is not the previous index. Remove the current chain of points.
1121         myEditor.removePoints(aSectionIndex, aCurRow, aNbPntsRm);
1122         aCurRow   = aListRows[i];
1123         aNbPntsRm = 1;
1124       }
1125     }
1126
1127     // Remove last points.
1128     myEditor.removePoints(aSectionIndex, aCurRow, aNbPntsRm);
1129
1130     emit numberOfItemsChanged(myPntsList);
1131
1132     // Set the new selection.
1133     int aRow = aListRows.first();
1134
1135     if (aRow >= myPntsList->count()) {
1136       aRow = myPntsList->count() - 1;
1137     }
1138
1139     if (aRow >= 0) {
1140       myPntsList->item(aRow)->setSelected(true);
1141     }
1142
1143     // Update undo/redo buttons.
1144     updateUndoRedoButtons();
1145   }
1146 }
1147
1148 //=======================================================================
1149 // function: undo
1150 // purpose:
1151 //=======================================================================
1152 void CurveCreator_Widget::undo()
1153 {
1154   if (myEditor.getNbUndo() > 0) {
1155     // Perform undo
1156     myEditor.undo();
1157
1158     // Reinitialize required widgets.
1159     updateUndoRedo();
1160   }
1161 }
1162
1163 //=======================================================================
1164 // function: redo
1165 // purpose:
1166 //=======================================================================
1167 void CurveCreator_Widget::redo()
1168 {
1169   if (myEditor.getNbRedo() > 0) {
1170     // Perform undo
1171     myEditor.redo();
1172
1173     // Reinitialize required widgets.
1174     updateUndoRedo();
1175   }
1176 }