Salome HOME
Join modifications from branch OCC_development_for_3_2_0a2
[modules/visu.git] / src / VISUGUI / VisuGUI_CutPlanesDlg.cxx
1 //  VISU VISUGUI : GUI of VISU component
2 //
3 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
21 //
22 //
23 //
24 //  File   : VisuGUI_CutPlanesDlg.cxx
25 //  Author : Laurent CORNABE & Hubert ROLLAND
26 //  Module : VISU
27 //  $Header$
28
29 #include "VisuGUI_CutPlanesDlg.h"
30
31 #include "VisuGUI.h"
32 #include "VisuGUI_Tools.h"
33 #include "VisuGUI_ViewTools.h"
34
35 #include "VISU_CutPlanes_i.hh"
36 #include "VISU_CutPlanesPL.hxx"
37
38 #include "OB_Browser.h"
39
40 #include "SVTK_ViewWindow.h"
41
42 #include "SalomeApp_Application.h"
43
44 #include "SUIT_Application.h"
45 #include "SUIT_Desktop.h"
46 #include "SUIT_ViewWindow.h"
47 #include "SUIT_ViewManager.h"
48
49 #include <qlayout.h>
50 #include <qcheckbox.h>
51 #include <qstyle.h>
52 #include <qstring.h>
53 #include <qvalidator.h>
54 #include <qlineedit.h>
55 #include <qtabwidget.h>
56
57 #include <vtkRenderer.h>
58 #include <vtkPolyData.h>
59 #include <vtkAppendPolyData.h>
60 #include <vtkDataSetMapper.h>
61
62 using namespace std;
63
64 //extern VisuGUI *visuGUI;
65
66 VisuGUI_CutPlanesPane::VisuGUI_CutPlanesPane (QWidget* theParent)
67      : QFrame(theParent), myPreviewActor(0)
68 {
69   QGridLayout* TopLayout = new QGridLayout( this );
70   TopLayout->setSpacing( 6 );
71   TopLayout->setMargin( 10 );
72
73   QButtonGroup* SelPlane = new QButtonGroup (tr("TXT_ORIENTATION"), this, "SelPlane");
74   //SelPlane->setTitle(tr("TXT_ORIENTATION"));
75   SelPlane->setColumnLayout(0, Qt::Vertical);
76   SelPlane->layout()->setSpacing( 0 );
77   SelPlane->layout()->setMargin( 0 );
78   QGridLayout* SelPlaneLayout = new QGridLayout( SelPlane->layout() );
79   SelPlaneLayout->setAlignment( Qt::AlignTop );
80   SelPlaneLayout->setSpacing( 6 );
81   SelPlaneLayout->setMargin( 11 );
82
83   RBxy = new QRadioButton (tr("PARALLEL_XOY"), SelPlane, "RBxy");
84   RByz = new QRadioButton (tr("PARALLEL_YOZ"), SelPlane, "RByz");
85   RBzx = new QRadioButton (tr("PARALLEL_ZOX"), SelPlane, "RBzx");
86   SelPlaneLayout->addWidget( RBxy, 0, 0 );
87   SelPlaneLayout->addWidget( RByz, 0, 1 );
88   SelPlaneLayout->addWidget( RBzx, 0, 2 );
89
90   QLabel* LabelPosi_3 = new QLabel (tr("LBL_NB_PLANS"), this, "LabelPosi_3");
91
92   nbPlan = new QSpinBox( 1, 100, 1, this, "nbPlan" );
93   nbPlan->setValue( 1 );
94   nbPlan->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
95
96   myPosTable = new QTable (this, "Positions of planes");
97   myPosTable->setMaximumHeight( 227 );
98   myPosTable->setMinimumWidth( 294 );
99   myPosTable->setNumCols(2);
100   myPosTable->setNumRows(0);
101   connect( myPosTable, SIGNAL(valueChanged(int, int)), this, SLOT(onValueChanged(int, int)) );
102
103   QHeader *th = myPosTable->horizontalHeader();
104   th->setLabel( 0, "Position" );
105   th->setLabel( 1, "Set default" );
106   th->setStyle("QStyle::CE_PushButton");
107
108   QGroupBox* GBrot = new QGroupBox (tr("LBL_ROTATION"), this, "GBrot");
109   GBrot->setColumnLayout(0, Qt::Vertical);
110   GBrot->layout()->setSpacing( 0 );
111   GBrot->layout()->setMargin( 0 );
112   QGridLayout* GBrotLayout = new QGridLayout( GBrot->layout() );
113   GBrotLayout->setAlignment( Qt::AlignTop );
114   GBrotLayout->setSpacing( 6 );
115   GBrotLayout->setMargin( 11 );
116
117   LabelRot1 = new QLabel (tr("LBL_ROT_X"), GBrot, "LabelRot1");
118   GBrotLayout->addWidget( LabelRot1, 0, 0 );
119
120   Rot1 = new QtxDblSpinBox( -180, 180, 10, GBrot );
121   Rot1->setValue( 0 );
122   Rot1->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
123   connect( Rot1, SIGNAL( valueChanged( double )), this, SLOT( onRotation( double ) ) );
124   GBrotLayout->addWidget( Rot1, 0, 1 );
125
126   LabelRot2 = new QLabel (tr("LBL_ROT_Y"), GBrot, "LabelRot2");
127   GBrotLayout->addWidget( LabelRot2, 1, 0 );
128
129   Rot2 = new QtxDblSpinBox( -180, 180, 10, GBrot );
130   Rot2->setValue( 0 );
131   Rot2->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
132   connect( Rot2, SIGNAL( valueChanged( double )), this, SLOT( onRotation( double ) ) );
133   GBrotLayout->addWidget( Rot2, 1, 1 );
134
135   QLabel* aPosLbl = new QLabel(tr( "LBL_POS" ), this);
136   myPosSpn = new QtxDblSpinBox( 0, 1, 0.1, this );
137
138   myPreviewCheck = new QCheckBox(tr("LBL_SHOW_PREVIEW"), this);
139   myPreviewCheck->setChecked(false);
140   connect( myPreviewCheck, SIGNAL( toggled( bool )), this, SLOT( onPreviewCheck( bool ) ) );
141
142   TopLayout->addMultiCellWidget( SelPlane, 0, 0, 0, 1 );
143   TopLayout->addMultiCellWidget( GBrot, 1, 1, 0, 1 );
144   TopLayout->addWidget( LabelPosi_3,   2, 0 );
145   TopLayout->addWidget( nbPlan,        2, 1 );
146   TopLayout->addMultiCellWidget( myPosTable, 3, 3, 0, 1 );
147   TopLayout->setRowStretch ( 3, 3 );
148   TopLayout->addWidget(aPosLbl, 4, 0 );
149   TopLayout->addWidget(myPosSpn, 4, 1 );
150   TopLayout->addMultiCellWidget( myPreviewCheck, 5, 5, 0, 1 );
151
152   // signals and slots connections
153   connect( SelPlane, SIGNAL( clicked( int )), this, SLOT( orientationChanged( int ) ) );
154   connect( nbPlan, SIGNAL( valueChanged( int )), this, SLOT( DrawTable( ) ) );
155   connect( myPosSpn, SIGNAL( valueChanged( double )), this, SLOT( DrawTable( ) ) );
156   connect( th, SIGNAL( clicked(int)), this, SLOT( setDefault(int) ) );
157
158   // default values
159   myCutPlanes = NULL;
160   hasInit = false;
161   X1 = 0; X2 = 0;
162   Y1 = 0; Y2 = 0;
163   Z1 = 0; Z2 = 0;
164   RByz->setChecked( true );
165
166 } // End of Constructor
167
168 VisuGUI_CutPlanesPane::~VisuGUI_CutPlanesPane()
169 {
170   deletePlanes();
171   if (myCutPlanes)
172     myCutPlanes->Destroy();
173   if (SVTK_ViewWindow* vf = VISU::GetActiveViewWindow<SVTK_ViewWindow>())
174     vf->Repaint();
175 }
176
177 void VisuGUI_CutPlanesPane::initFromPrsObject (VISU::CutPlanes_i* thePrs)
178 {
179   setNbPlanes(thePrs->GetNbPlanes());
180   setRotation(thePrs->GetRotateX()*180./PI, thePrs->GetRotateY()*180./PI);
181   setPlanePos(thePrs->GetOrientationType());
182   myPosSpn->setValue(thePrs->GetDisplacement());
183   hasInit = true;
184   // init table
185   myCutPlanes = new VISU::CutPlanes_i(thePrs->GetResult(),false);
186   myCutPlanes->SameAs(thePrs);
187   DrawTable();
188
189   // Draw Preview
190   if (myPreviewCheck->isChecked()) {
191     createPlanes();
192   }
193 }
194
195 void VisuGUI_CutPlanesPane::createPlanes()
196 {
197   if (VISU::GetActiveViewWindow<SVTK_ViewWindow>() == NULL) return;
198   if (myCutPlanes == NULL) return;
199   if (myPreviewActor != 0) return;
200
201   vtkAppendPolyData* aPolyData = myCutPlanes->GetCutPlanesPL()->GetAppendPolyData();
202   if (!aPolyData->GetOutput()->GetNumberOfCells()) {
203     onPreviewCheck(false);
204     return;
205   }
206   vtkDataSetMapper* aPlaneMapper = vtkDataSetMapper::New();
207   aPlaneMapper->SetInput(aPolyData->GetOutput());
208   aPlaneMapper->ScalarVisibilityOff();
209
210   myPreviewActor = SALOME_Actor::New();
211   myPreviewActor->PickableOff();
212   myPreviewActor->SetMapper(aPlaneMapper);
213   aPlaneMapper->Delete();
214   VISU::GetActiveViewWindow<SVTK_ViewWindow>()->AddActor(myPreviewActor);
215 }
216
217 int VisuGUI_CutPlanesPane::storeToPrsObject (VISU::CutPlanes_i* thePrs)
218 {
219   thePrs->SetOrientation(getOrientaion(), getRotation1()*PI/180., getRotation2()*PI/180.);
220   thePrs->SetNbPlanes(getNbPlanes());
221   thePrs->SetDisplacement(myPosSpn->value());
222   for (int i = 0; i < getNbPlanes(); ++i) {
223     QCheckTableItem* anItem = (QCheckTableItem*)myPosTable->item(i, 1);
224     if (!anItem)
225       break;
226     if (!anItem->isChecked())
227       thePrs->SetPlanePosition(i, myPosTable->text(i, 0).toDouble());
228     else
229       thePrs->SetDefault(i);
230   }
231   return 1;
232 }
233
234 /*!
235   Called when orientation is changed
236 */
237 void VisuGUI_CutPlanesPane::orientationChanged (int Id)
238 {
239   if (Id == 0) { // RBxy->isChecked()
240     LabelRot1->setText(tr("LBL_ROT_X"));
241     LabelRot2->setText(tr("LBL_ROT_Y"));
242   } else if (Id == 1) { // RByz->isChecked()
243     LabelRot1->setText(tr("LBL_ROT_Y"));
244     LabelRot2->setText(tr("LBL_ROT_Z"));
245   } else {
246     LabelRot1->setText(tr("LBL_ROT_Z"));
247     LabelRot2->setText(tr("LBL_ROT_X"));
248   }
249   DrawTable();
250 }
251
252 /*!
253   Sets planes orientation and position
254 */
255 void VisuGUI_CutPlanesPane::setPlanePos (const VISU::CutPlanes::Orientation orient)
256 {
257   if (orient == VISU::CutPlanes::XY)           // xy
258     {
259       RBxy->setChecked( true );
260       orientationChanged( 0 );
261     }
262   else if (orient == VISU::CutPlanes::YZ)       // yz
263     {
264       RByz->setChecked( true );
265       orientationChanged( 1 );
266     }
267   else                         // zx
268    {
269      RBzx->setChecked( true );
270      orientationChanged( 2 );
271    }
272
273 }
274
275 /*!
276   Gets planes orientation
277 */
278 VISU::CutPlanes::Orientation VisuGUI_CutPlanesPane::getOrientaion()
279 {
280   VISU::CutPlanes::Orientation orient;
281   if ( RBxy->isChecked() )     // xy
282     orient = VISU::CutPlanes::XY;
283   else if ( RByz->isChecked() )     // yz
284     orient = VISU::CutPlanes::YZ;
285   else if ( RBzx->isChecked() )     // zx
286     orient = VISU::CutPlanes::ZX;
287   return orient;
288 }
289
290 /*!
291   Sets planes rotation
292 */
293 void VisuGUI_CutPlanesPane::setRotation (const double r1, const double r2)
294 {
295   Rot1->setValue( r1 );
296   Rot2->setValue( r2 );
297 }
298
299 /*!
300   Draw the table of planes positions
301 */
302 void VisuGUI_CutPlanesPane::DrawTable()
303 {
304   if (myCutPlanes == NULL) return;
305   if (!hasInit) return;
306
307   int aNbRows = myPosTable->numRows();
308   int aNbPlanes = getNbPlanes();
309
310   myCutPlanes->SetOrientation(getOrientaion(),getRotation1()*PI/180.,getRotation2()*PI/180.);
311   myCutPlanes->SetNbPlanes(aNbPlanes);
312   myCutPlanes->SetDisplacement(myPosSpn->value());
313   if (aNbRows>0)
314     for (int i = 0; i < aNbRows; ++i) {
315       QCheckTableItem* aItem = (QCheckTableItem*)myPosTable->item( i, 1 );
316       if (aItem == 0) break;
317       if (!aItem->isChecked())
318         myCutPlanes->SetPlanePosition(i, myPosTable->text(i, 0).toDouble());
319     }
320
321   if (aNbPlanes > aNbRows)
322     myPosTable->insertRows(aNbRows, aNbPlanes - aNbRows );
323   else if (aNbPlanes < aNbRows)
324     myPosTable->setNumRows(aNbPlanes);
325
326   int aMin = (aNbRows < aNbPlanes)? aNbRows : aNbPlanes;
327   for (int i = 0; i<aMin; i++) {
328     myPosTable->setText(i, 0, QString::number(myCutPlanes->GetPlanePosition(i)));
329     ((QCheckTableItem*)myPosTable->item( i, 1 ))->setChecked(myCutPlanes->IsDefault(i));
330   }
331
332   QHeader *vh = myPosTable->verticalHeader();
333   QString str("Plane# %1");
334   for (int i=aMin; i<aNbPlanes; i++) {
335     VisuGUI_NumEditItem* aEditItem = new VisuGUI_NumEditItem(myPosTable,
336                                                              QTableItem::OnTyping,
337                                                              QString::number(myCutPlanes->GetPlanePosition(i)));
338     aEditItem->setReplaceable(false);
339     aEditItem->setEnabled(!myCutPlanes->IsDefault(i));
340     myPosTable->setItem(i, 0, aEditItem);
341
342     QCheckTableItem* aCheck = new QCheckTableItem(myPosTable, 0);
343     aCheck->setChecked(myCutPlanes->IsDefault(i));
344     aCheck->setReplaceable(false);
345     myPosTable->setItem(i, 1, aCheck);
346
347     vh->setLabel( i, str.arg(i+1) );
348   }
349
350   // Update preview
351   if (myPreviewCheck->isChecked()) {
352     if (SVTK_ViewWindow* vf = VISU::GetActiveViewWindow<SVTK_ViewWindow>()) {
353       myCutPlanes->GetPL()->Update();
354       deletePlanes();
355       createPlanes();
356       vf->Repaint();
357     }
358   }
359 }
360
361 void VisuGUI_CutPlanesPane::setDefault (int all)
362 {
363   myPosTable->setCurrentCell(-1, 1);
364   myPosTable->clearSelection();
365   if (all == 0) return;
366   if (all == 1)
367     for (int i = 0; i < getNbPlanes(); ++i)
368       ((QCheckTableItem*)myPosTable->item( i, 1 ))->setChecked(true);
369
370   for (int i = 0; i < getNbPlanes(); ++i) {
371     if ( ((QCheckTableItem*)myPosTable->item( i, 1 ))->isChecked() ) {
372       myCutPlanes->SetDefault(i);
373       myPosTable->setText( i, 0, QString::number(myCutPlanes->GetPlanePosition(i)));
374       myPosTable->item( i, 0 )->setEnabled(false);
375     } else
376       myPosTable->item( i, 0 )->setEnabled(true);
377   }
378 }
379
380 void VisuGUI_CutPlanesPane::onValueChanged (int theRow, int theCol)
381 {
382   if (theCol == 0) {
383     QString aTxt = myPosTable->text(theRow, 0);
384     bool isChanged = !aTxt.isEmpty();
385     ((QCheckTableItem*)myPosTable->item(theRow, 1))->setChecked(!isChanged);
386
387     if (myPreviewCheck->isChecked()) {
388       //Update Preview
389       if (SVTK_ViewWindow* vf = VISU::GetActiveViewWindow<SVTK_ViewWindow>()) {
390         myCutPlanes->SetPlanePosition( theRow, aTxt.toDouble());
391         myCutPlanes->GetPL()->Update();
392         deletePlanes();
393         createPlanes();
394         vf->Repaint();
395       }
396     }
397   } else {
398     bool isDefault = ((QCheckTableItem*)myPosTable->item(theRow, theCol))->isChecked();
399     if (isDefault) {
400       myCutPlanes->SetDefault(theRow);
401       myPosTable->setText(theRow, 0, QString::number(myCutPlanes->GetPlanePosition(theRow)));
402
403       if (myPreviewCheck->isChecked()) {
404         if (SVTK_ViewWindow* vf = VISU::GetActiveViewWindow<SVTK_ViewWindow>()) {
405           //Update Preview
406           myCutPlanes->GetPL()->Update();
407           deletePlanes();
408           createPlanes();
409           vf->Repaint();
410         }
411       }
412     }
413     myPosTable->item(theRow, 0)->setEnabled(!isDefault);
414   }
415 }
416
417 void VisuGUI_CutPlanesPane::deletePlanes()
418 {
419   if (myPreviewActor == 0) return;
420   if (SVTK_ViewWindow* vf = VISU::GetActiveViewWindow<SVTK_ViewWindow>())
421     vf->RemoveActor(myPreviewActor);
422   myPreviewActor->Delete();
423   myPreviewActor = 0;
424 }
425
426 void VisuGUI_CutPlanesPane::onRotation (double theValue)
427 {
428   if (myCutPlanes == NULL) return;
429   if (myPreviewCheck->isChecked()) {
430     if (SVTK_ViewWindow* vf = VISU::GetActiveViewWindow<SVTK_ViewWindow>()) {
431       myCutPlanes->SetOrientation(getOrientaion(),getRotation1()*PI/180.,getRotation2()*PI/180.);
432       myCutPlanes->GetPL()->Update();
433       deletePlanes();
434       createPlanes();
435       vf->Repaint();
436     }
437   }
438 }
439
440 void VisuGUI_CutPlanesPane::onPreviewCheck (bool thePreview)
441 {
442   if (SVTK_ViewWindow* vf = VISU::GetActiveViewWindow<SVTK_ViewWindow>()) {
443     if (thePreview) {
444       storeToPrsObject(myCutPlanes);
445       myCutPlanes->GetPL()->Update();
446       createPlanes();
447       vf->onFitAll();
448     } else {
449       deletePlanes();
450       vf->Repaint();
451     }
452   }
453 }
454
455 //###################################################################
456
457
458 /*!
459   Constructor
460 */
461 VisuGUI_CutPlanesDlg::VisuGUI_CutPlanesDlg (SalomeApp_Module* theModule)
462      : QDialog(VISU::GetDesktop(theModule), "VisuGUI_CutPlanesDlg", false,
463                WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu)
464 {
465   setCaption("Cut Planes Definition");
466   setSizeGripEnabled(true);
467
468   QVBoxLayout* TopLayout = new QVBoxLayout (this);
469   TopLayout->setSpacing(6);
470   TopLayout->setMargin(11);
471
472   // Tab pane
473   QTabWidget* aTabBox = new QTabWidget(this);
474   myCutPane = new VisuGUI_CutPlanesPane(this/*, myMgr*/);
475   aTabBox->addTab(myCutPane, "Cut Planes");
476   myScalarPane = new VisuGUI_ScalarBarPane(this, false);
477   myScalarPane->setMargin(5);
478   aTabBox->addTab(myScalarPane, "Scalar Bar");
479
480   TopLayout->addWidget(aTabBox);
481
482   QGroupBox* GroupButtons = new QGroupBox(this, "GroupButtons");
483   GroupButtons->setGeometry(QRect(10, 10, 281, 48));
484   GroupButtons->setTitle("");
485   GroupButtons->setColumnLayout(0, Qt::Vertical);
486   GroupButtons->layout()->setSpacing(0);
487   GroupButtons->layout()->setMargin(0);
488   QGridLayout* GroupButtonsLayout = new QGridLayout(GroupButtons->layout());
489   GroupButtonsLayout->setAlignment(Qt::AlignTop);
490   GroupButtonsLayout->setSpacing(6);
491   GroupButtonsLayout->setMargin(11);
492
493   QPushButton* buttonOk = new QPushButton(tr("&OK"), GroupButtons, "buttonOk");
494   buttonOk->setAutoDefault(TRUE);
495   buttonOk->setDefault(TRUE);
496   GroupButtonsLayout->addWidget(buttonOk, 0, 0);
497   GroupButtonsLayout->addItem(new QSpacerItem(5, 5, QSizePolicy::Expanding, QSizePolicy::Minimum), 0, 1);
498
499   QPushButton* buttonCancel = new QPushButton(tr("&Cancel"), GroupButtons, "buttonCancel");
500   buttonCancel->setAutoDefault(TRUE);
501   GroupButtonsLayout->addWidget(buttonCancel, 0, 2);
502
503   TopLayout->addWidget(GroupButtons);
504
505   connect(buttonOk,     SIGNAL(clicked()), this, SLOT(accept()));
506   connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
507   //connect(myMgr, SIGNAL(closeAllViews()), this, SLOT(reject()));
508   //connect(VisuGUI::application()->desktop(),
509   //        SIGNAL(windowActivated(SUIT_ViewWindow*)),
510   //        this, SLOT(onWindowActivated(SUIT_ViewWindow*)));
511 }
512
513 void VisuGUI_CutPlanesDlg::initFromPrsObject (VISU::CutPlanes_i* thePrs)
514 {
515   myPrs = thePrs;
516   myScalarPane->initFromPrsObject(thePrs);
517   myCutPane->initFromPrsObject(thePrs);
518 }
519
520 int VisuGUI_CutPlanesDlg::storeToPrsObject (VISU::CutPlanes_i* thePrs)
521 {
522   return (myScalarPane->storeToPrsObject(thePrs) &&
523           myCutPane->storeToPrsObject(thePrs));
524 }
525
526 void VisuGUI_CutPlanesDlg::accept()
527 {
528   //if ( !VisuGUI::CheckActiveStudyLock() ) {
529   //  reject();
530   //  return;
531   //}
532   if (myScalarPane->check())
533     {
534       myScalarPane->deletePreview();
535       QDialog::accept();
536     }
537 }
538
539 void VisuGUI_CutPlanesDlg::reject() {
540   myScalarPane->deletePreview();
541   QDialog::reject();
542 }
543
544 //void VisuGUI_CutPlanesDlg::onWindowActivated (SUIT_ViewWindow* theWnd)
545 //{
546 //  if (theWnd != myStudyWnd)
547 //    reject();
548 //}
549
550 //###################################################################
551
552 QWidget* VisuGUI_NumEditItem::createEditor() const
553 {
554   QLineEdit *editline = new QLineEdit(text(), table()->viewport());
555   QDoubleValidator *dvalidator = new QDoubleValidator(table()->viewport());
556   dvalidator->setDecimals(32);
557   editline->setValidator(dvalidator);
558   return editline;
559 }