Salome HOME
improvement to call destructor of SelectFiled and SelectParams classes
[modules/filter.git] / src / FILTERGUI / SelectParams.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 //
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
8 //
9 // This library is distributed in the hope that it will be useful
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20
21 #include <stdlib.h>
22 #include <math.h>
23 #include "SelectParams.h"
24 #include "utilities.h"
25
26 #include <SUIT_FileDlg.h>
27
28 #include "Utils_SALOME_Exception.hxx"
29 #include <SalomeApp_Tools.h>
30
31 #include <qlabel.h>
32 #include <qgroupbox.h>
33 #include <qframe.h>
34 #include <qlayout.h>
35 #include <qlineedit.h>
36 #include <qbuttongroup.h>
37 #include <qradiobutton.h>
38 #include <qpushbutton.h>
39 #include <qfiledialog.h>
40
41 SelectParams::SelectParams(FilterGUI* theModule,SelectField *sel,
42                            const char* name,
43                            bool modal, WFlags fl)
44   : QDialog(FILTER::GetDesktop( theModule ), name, modal, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu | Qt::WDestructiveClose),  _size(128),
45   _myExpr( 0 ),
46   _myFunc( 0 ),
47   _myFieldB( 0 ),
48   _myLinear( 0 ),
49   _myLog( 0 ),
50   _myHisto( 0 ),
51   _myNbThresh( 0 ),
52   _myCutNeg( 0 ),
53   _myOneThresh( 0 ),
54   _myTwoThresh( 0 ),
55   _myArea( 0 ),
56   _myVThresh( 0 ),
57   _myOutFile( 0 ),
58   _myOFB( 0 ),
59   _myProc( 0 ),
60   _myFScale( 0 ),
61   _myGroupLayout( 0 ),
62   _myGroupLayout2( 0 ),
63   _myPlot( 0 ),
64   _GroupC1( 0 ),
65   _GroupC2( 0 ),
66   _lay( 0 ),
67   _fr( 0 )
68 {
69   // Allocate histogram arrays
70   _x = new double[_size];
71   _y = new double[_size];
72
73   if(sel){
74     // read reference field values
75     ::MEDMEM::MED *med = sel->getMED();
76
77     // Get reference field and time step
78     _inputFile = sel->getFile();
79     _inputMesh = sel->getMesh();
80     _inputField = sel->getField();
81     _inputTS = sel->getTimeStep();
82     // if no reference field selection: throw exception
83     if( _inputMesh.isNull() || _inputField.isNull() ){
84       MESSAGE("Select an input Field in MED file before filtering!!");
85       throw SALOME_Exception("Salome Exception");
86     }
87
88     deque<DT_IT_> myIteration = med->getFieldIteration (_inputField);
89     MEDMEM::FIELD_* field = med->getField(_inputField,myIteration[_inputTS].dt,myIteration[_inputTS].it);
90     if (dynamic_cast<MEDMEM::FIELD<double>*>(field)){
91       _myDField = new MEDMEM::FIELD<double>(MEDMEM::MED_DRIVER,_inputFile,_inputField,myIteration[_inputTS].dt,myIteration[_inputTS].it);
92       _myIField = NULL;
93     }
94     else{
95       _myIField = new MEDMEM::FIELD<int>(MEDMEM::MED_DRIVER,_inputFile,_inputField,myIteration[_inputTS].dt,myIteration[_inputTS].it);
96       _myDField = NULL;
97     }
98     buildFrame();
99   }
100   // if no reference field selection: throw exception
101   else{
102     MESSAGE("Select an input Field in MED file before filtering!!");
103     throw SALOME_Exception("Salome Exception");
104   }
105
106 }
107
108 SelectParams::~SelectParams()
109 {
110   cout << "SelectParams: destructor called" << endl;
111   delete _x;
112   delete _y;
113   if(_myIField) delete _myIField;
114   if(_myDField) delete _myDField;
115 }
116
117 void SelectParams::buildFrame()
118 {
119   // build widgets for select filtering parameters
120   QGridLayout* _lay = new QGridLayout( this, 1, 2 );
121
122   QGroupBox* _GroupC1 = new QGroupBox( this, "GroupC1" );
123   _lay->addWidget( _GroupC1,0,0 );
124
125   _GroupC1->setTitle( tr( "FILTER_PARAMS"  ) );
126   _GroupC1->setColumnLayout(0, Qt::Vertical );
127   _GroupC1->layout()->setSpacing( 0 );
128   _GroupC1->layout()->setMargin( 0 );
129   _myGroupLayout = new QGridLayout( _GroupC1->layout() );
130   _myGroupLayout->setAlignment( Qt::AlignTop );
131   _myGroupLayout->setSpacing( 6 );
132   _myGroupLayout->setMargin( 11 );
133   _myGroupLayout->setColStretch( 0, 0 );
134   _myGroupLayout->setColStretch( 1, 1 );
135
136   int row = 0;
137
138   QString qs1(tr("FILTER_INPUT_FILE"));
139   qs1.append(basename(_inputFile));
140   _myGroupLayout->addWidget( new QLabel( qs1, _GroupC1 ), row, 0 );
141   row++;
142
143   QString qs2(tr("FILTER_INPUT_MESH"));
144   qs2.append(_inputMesh);
145   _myGroupLayout->addWidget( new QLabel( qs2, _GroupC1 ), row, 0 );
146   row++;
147
148   QString qs3(tr("FILTER_INPUT_FIELD"));
149   qs3.append(_inputField);
150   _myGroupLayout->addWidget( new QLabel( qs3, _GroupC1 ), row, 0 );
151   row++;
152
153   QString qs4(tr("FILTER_INPUT_TS"));
154   char strTS[128];
155   sprintf(strTS,"%d\0",_inputTS);
156   qs4.append(strTS);
157   _myGroupLayout->addWidget( new QLabel( qs4, _GroupC1 ), row, 0 );
158   row++;
159
160   // 0)  field function to calculate histogram (radiogroup)
161   _myFunc = new QButtonGroup( tr("FILTER_SELECT_FUNC"), _GroupC1 );
162   _myFunc->setExclusive( true );
163   _myFunc->setColumnLayout( 0, Qt::Horizontal );
164
165   _myFieldB = new QRadioButton( tr("FILTER_FIELD"), _myFunc );
166   _myFieldB->setChecked(true);
167
168   QGridLayout* convLay = new QGridLayout( _myFunc->layout() );
169   convLay->addWidget( _myFieldB, 0, 0 );
170   convLay->addWidget( _myCutNeg = new QRadioButton( tr("FILTER_GRADIENT"), _myFunc ), 0, 1 );
171   _myGroupLayout->addWidget( _myFunc, row, 0 );
172   row++;
173
174   // 1)  display histogram button (pushbutton)
175   _myHisto = new QPushButton( "", _GroupC1 );
176   _myHisto->setText(tr("FILTER_DISPLAY_HISTO"));
177   _myHisto->setAutoDefault(TRUE);
178   _myHisto->setDefault(TRUE);
179   _myGroupLayout->addWidget( _myHisto, row, 0 );
180   row++;
181
182   // 2)  scale of histogram (radiogroup)
183   _myFScale = new QButtonGroup( tr("FILTER_TYPE_DISPLAY"), _GroupC1 );
184   _myFScale->setExclusive( true );
185   _myFScale->setColumnLayout( 0, Qt::Horizontal );
186
187   _myLinear = new QRadioButton( tr("FILTER_LINEAR"), _myFScale );
188   _myLinear->setChecked(true);
189   _myLog = new QRadioButton( tr("FILTER_LOG"), _myFScale );
190   _myFScale->setDisabled(true);
191
192   QGridLayout* scaleLay = new QGridLayout( _myFScale->layout() );
193   scaleLay->addWidget( _myLinear, 0, 0 );
194   scaleLay->addWidget( _myLog, 0, 1 );
195   _myGroupLayout->addWidget( _myFScale, row, 0 );
196   row++;
197
198   // 3)  number of thresholds (radiogroup)
199   _myNbThresh = new QButtonGroup( tr("FILTER_SEL_THRESH"), _GroupC1 );
200   _myNbThresh->setExclusive( true );
201   _myNbThresh->setColumnLayout( 0, Qt::Horizontal );
202   QGridLayout* nbtLay = new QGridLayout( _myNbThresh->layout() );
203   nbtLay->addWidget( _myOneThresh = new QRadioButton( tr("FILTER_ONE_THRESH"), _myNbThresh ), 0, 0 );
204   nbtLay->addWidget( _myTwoThresh = new QRadioButton( tr("FILTER_TWO_THRESH"), _myNbThresh ), 0, 1 );
205   _myGroupLayout->addWidget( _myNbThresh, row, 0 );
206
207   _myOneThresh->setChecked(true);
208   _myNbThresh->setDisabled(true);
209   row++;
210
211   // 4)  reference area on thresholds (radiogroup)
212   _myArea = new QButtonGroup( tr("FILTER_REF_AREA"), _GroupC1 );
213   _myArea->setExclusive( true );
214   _myArea->setColumnLayout( 0, Qt::Horizontal );
215   QGridLayout* areaLay = new QGridLayout( _myArea->layout() );
216   areaLay->addWidget( _myInt = new QRadioButton( tr("FILTER_BOTTOM"), _myArea ), 0, 0 );
217   areaLay->addWidget( _myExt = new QRadioButton( tr("FILTER_UP"), _myArea ), 0, 1 );
218   _myGroupLayout->addWidget( _myArea, row, 0 );
219
220   _myExt->setChecked(true);
221   _myArea->setDisabled(true);
222   row++;
223
224   // 5)  threshold values (line edit)
225   _myVThresh = new QButtonGroup( tr("FILTER_TRESH_VAL"), _GroupC1 );
226   _myVThresh->setExclusive( true );
227   _myVThresh->setColumnLayout( 0, Qt::Horizontal );
228   QGridLayout* ftLay = new QGridLayout( _myVThresh->layout() );
229   ftLay->addWidget( _myLFT = new QLabel( tr("FILTER_VAL_TRESH") , _myVThresh ), 0, 0 );
230   ftLay->addWidget( _myLEFT = new QLineEdit( "", _myVThresh ), 0, 1 );
231   ftLay->addWidget( _myLST = new QLabel( tr("FILTER_VAL_2_TRESH") , _myVThresh ), 1, 0 );
232   ftLay->addWidget( _myLEST = new QLineEdit( "", _myVThresh ), 1, 1 );
233   _myGroupLayout->addWidget( _myVThresh, row, 0 );
234
235   _myVThresh->setDisabled(true);
236   _myLST->hide();
237   _myLEST->hide();
238   row++;
239
240   // 6)  output file name (line edit)
241   _myOutFile = new QButtonGroup( tr("FILTER_OUT_FILE"), _GroupC1 );
242   _myOutFile->setExclusive( true );
243   _myOutFile->setColumnLayout( 0, Qt::Horizontal );
244
245   _myOFB = new QPushButton( "", _myOutFile );
246   _myOFB->setText(tr("FILTER_BROWSE"));
247   _myOFB->setAutoDefault(TRUE);
248
249   QGridLayout* outLay = new QGridLayout( _myOutFile->layout() );
250   outLay->addWidget( _myOFB, 0, 0 );
251   outLay->addWidget( _myOFN = new QLineEdit( "", _myOutFile ), 0, 1 );
252   _myGroupLayout->addWidget( _myOutFile, row, 0 );
253
254   _myOutFile->setDisabled(true);
255   row++;
256
257   // 8)  process button (pushbutton)
258   _myProc = new QPushButton( "", _GroupC1 );
259   _myProc->setText(tr("FILTER_PROCESS"));
260   _myProc->setAutoDefault(TRUE);
261   _myGroupLayout->addWidget( _myProc, row, 0 );
262   _myProc->setDisabled(true);
263   row++;
264
265   _GroupC2 = new QGroupBox( this, "GroupC2" );
266   _lay->addWidget( _GroupC2,0,1 );
267
268   _GroupC2->setTitle( tr( "FILTER_HISTO" ) );
269   _GroupC2->setColumnLayout(0, Qt::Vertical );
270   _GroupC2->layout()->setSpacing( 0 );
271   _GroupC2->layout()->setMargin( 0 );
272   _myGroupLayout2 = new QGridLayout( _GroupC2->layout() );
273
274   // 9)  histogram curve
275   _myPlot = new QwtPlot(_GroupC2);
276   _myHistoCurve = _myPlot->insertCurve( QString() );
277   _myPlot->setCurvePen( _myHistoCurve, QPen( Qt::red, 1 ) );
278   _myPlot->setCurveTitle( _myHistoCurve, "Histogram" );
279
280   _myGroupLayout2->addWidget( _myPlot, 0, 0 );
281
282   // 10)  reduction rate (label)
283   QString qs5(tr("FILTER_RED_RATE"));
284   qs5.append(" = 0.5");
285   _myLRR = new QLabel( qs5, _GroupC2 );
286   _myGroupLayout2->addWidget( _myLRR, 1, 0 );
287
288   _GroupC2->hide();
289
290   _myHistoFThresh = _myPlot->insertCurve( QString() );
291   _myPlot->setCurvePen( _myHistoFThresh, QPen( Qt::black, 1 ) );
292   _myHistoSThresh = _myPlot->insertCurve( QString() );
293   _myPlot->setCurvePen( _myHistoSThresh, QPen( Qt::black, 1 ) );
294
295   connect( _myHisto, SIGNAL(clicked()), this, SLOT(updateHisto()));
296   connect( _myLinear, SIGNAL(clicked()), this, SLOT(scaleSelected()));
297   connect( _myLog, SIGNAL(clicked()), this, SLOT(scaleSelected()));
298   connect( _myOneThresh, SIGNAL(clicked()), this, SLOT(nbThreshSelected()));
299   connect( _myTwoThresh, SIGNAL(clicked()), this, SLOT(nbThreshSelected()));
300   connect( _myInt, SIGNAL(clicked()), this, SLOT(areaSelected()));
301   connect( _myExt, SIGNAL(clicked()), this, SLOT(areaSelected()));
302   connect( _myLEFT, SIGNAL(returnPressed()), this, SLOT(enterFThresh()));
303   connect( _myLEST, SIGNAL(returnPressed()), this, SLOT(enterSThresh()));
304   connect( _myPlot, SIGNAL(plotMouseMoved(const QMouseEvent &)), this, SLOT(moveThresh(const QMouseEvent &)));
305   connect( _myOFB, SIGNAL(clicked()), this, SLOT(getOutFileName()));
306   connect( _myProc, SIGNAL(clicked()), this, SLOT(process()));
307
308   this->show();  /* displays Dialog */
309 }
310
311 void SelectParams::scaleSelected()
312 {
313   // draw linear or log Y scale depend on user
314   if( _myLinear->isChecked() ){
315     _ymin = 0.0;
316     _myPlot->setAxisOptions(_myPlot->curveYAxis( _myHistoCurve ), QwtAutoScale::None );
317   }
318   else{
319     _ymin = 1.0;
320     _myPlot->setAxisOptions(_myPlot->curveYAxis( _myHistoCurve ), QwtAutoScale::Logarithmic );
321   }
322   _myPlot->setAxisScale( _myPlot->curveYAxis( _myHistoCurve ), _ymin, _ymax );
323   _myPlot->replot();
324 }
325
326 void SelectParams::nbThreshSelected()
327 {
328   if( _myOneThresh->isChecked() ){
329     // if one threshold choice between bottom and up for reference area
330     _myInt->setText(tr("FILTER_BOTTOM"));
331     _myExt->setText(tr("FILTER_UP"));
332     _myLFT->setText(tr("FILTER_VAL_TRESH"));
333     _myLST->hide();
334     _myLEST->hide();
335     // draw first threshold
336     displayFThresh();
337     // erase second threshold
338     clearSThresh();
339   }
340   else{
341     // if two thresholds choice between interior and exterior fir reference area
342     _myInt->setText(tr("FILTER_INT"));
343     _myExt->setText(tr("FILTER_EXT"));
344     _myLFT->setText(tr("FILTER_VAL_1_TRESH"));
345     if(_myLST->isHidden())
346       _myLST->show();
347     if(_myLEST->isHidden())
348       _myLEST->show();
349     // draw two thresholds
350     displayFThresh();
351     displaySThresh();
352   }
353   calcRateRed();
354 }
355
356 void SelectParams::areaSelected()
357 {
358   // calculate reduction rate after thresholds selection
359   calcRateRed();
360 }
361
362 void SelectParams::enterFThresh()
363 {
364   displayFThresh();
365   calcRateRed();
366 }
367
368 void SelectParams::enterSThresh()
369 {
370   displaySThresh();
371   calcRateRed();
372 }
373
374 void SelectParams::calcHisto()
375 {
376   char strth[128];
377   vector<int> myh;
378
379   // calculate histogram values
380   if (_myDField){
381     _myDField->getMinMax(_xmin,_xmax);
382     myh = _myDField->getHistogram(_size);
383   }
384   else{
385     int xmin, xmax;
386     _myIField->getMinMax(xmin,xmax);
387     _xmin = (double)xmin;
388     _xmax = (double)xmax;
389     myh = _myIField->getHistogram(_size);
390   }                     
391   _ymin = 0.0;
392   _ymax = 0.0;
393
394   for(int i=0;i<_size;i++){
395     // calculate absisses for histogram values
396     _x[i]=_xmin+(i*(_xmax-_xmin))/_size;
397     _y[i]=(double)myh[i];
398     if( _y[i] > _ymax )
399       _ymax = _y[i];
400   }
401
402   // init thresholds values
403   _fthresh = (_xmin + _xmax)/2.0;
404   _sthresh = (_xmin + 3.*_xmax)/4.0;
405   sprintf(strth,"%g",_fthresh);
406   _myLEFT->setText(QString(strth));
407   sprintf(strth,"%g",_sthresh);
408   _myLEST->setText(QString(strth));
409 }
410
411 void SelectParams::displayHisto()
412 {
413   // give extrema values for each axis
414   _myPlot->setAxisScale( _myPlot->curveXAxis( _myHistoCurve ), _xmin, _xmax );
415   _myPlot->setAxisScale( _myPlot->curveYAxis( _myHistoCurve ), _ymin, _ymax );
416   // associate values to curve
417   _myPlot->setCurveData( _myHistoCurve, _x, _y, _size );
418   if( _myLinear->isChecked() )
419     _myPlot->setAxisOptions(_myPlot->curveYAxis( _myHistoCurve ), QwtAutoScale::None );
420   else
421     _myPlot->setAxisOptions(_myPlot->curveYAxis( _myHistoCurve ), QwtAutoScale::Logarithmic );
422   // associate mapping to plot to move thresholds on display
423   _qmap = _myPlot->canvasMap(_myPlot->curveXAxis( _myHistoCurve ));
424   _qmap.setDblRange(_xmin,_xmax);
425   _myPlot->replot();
426 }
427
428 void SelectParams::enableWidgets()
429 {
430   if(_GroupC2->isHidden()){
431     _myFScale->setEnabled(true);
432     _myNbThresh->setEnabled(true);
433     _myArea->setEnabled(true);
434     _myVThresh->setEnabled(true);
435     _myOutFile->setEnabled(true);
436     _myProc->setEnabled(true);
437     _GroupC2->show();
438   }
439 }
440
441 void SelectParams::updateHisto()
442 {
443   calcHisto();
444   displayHisto();
445   displayFThresh();
446   if( _myTwoThresh->isChecked() )
447     displaySThresh();
448   calcRateRed();
449   enableWidgets();
450 }
451
452 void SelectParams::displayFThresh()
453 {
454   _fthresh = atof(_myLEFT->text());
455
456   // draw first threshold curve
457   for(int i=0;i<100;i++){
458     _xft[i]=_fthresh;
459     _yft[i]=((i-1)*_ymax)/100.0;
460   }
461   _myPlot->setCurveData( _myHistoFThresh, _xft, _yft, 100 );
462   _myPlot->replot();
463 }
464
465 void SelectParams::displaySThresh()
466 {
467   _sthresh = atof(_myLEST->text());
468
469   // draw second threshold curve
470   for(int i=0;i<100;i++){
471     _xst[i]=_sthresh;
472     _yst[i]=((i-1)*_ymax)/100.0;
473   }
474   _myPlot->setCurveData( _myHistoSThresh, _xst, _yst, 100 );
475   _myPlot->replot();
476 }
477
478 void SelectParams::clearSThresh()
479 {
480   _sthresh = atof(_myLEST->text());
481
482   // erase second threshold curve
483   for(int i=0;i<100;i++){
484     _xst[i]=_sthresh;
485     _yst[i]=0.0;
486   }
487   _myPlot->setCurveData( _myHistoSThresh, _xst, _yst, 100 );
488   _myPlot->replot();
489 }
490
491 void SelectParams::moveThresh(const QMouseEvent &e)
492 {
493   char strth[128];
494
495   // move threshold curve with mouse
496   int delta = abs(e.x()-_qmap.transform(_fthresh));
497   if( delta < 5 ){
498     // moving first threshold curve
499     sprintf(strth,"%g",_qmap.invTransform(e.x()));
500     _myLEFT->setText(QString(strth));
501     displayFThresh();
502   }
503   else if( _myTwoThresh->isChecked() ){
504     delta = abs(e.x()-_qmap.transform(_sthresh));
505     if( delta < 5 ){
506       // moving second threshold curve
507       sprintf(strth,"%g",_qmap.invTransform(e.x()));
508       _myLEST->setText(QString(strth));
509       displaySThresh();
510     }
511   }
512   calcRateRed();
513 }
514
515 void SelectParams::getOutFileName()
516 {
517   // get output MED file name
518   QString file = QFileDialog::getSaveFileName("",
519                                               "*.med",
520                                               _myOFB,
521                                               "save file dialog",
522                                               "Choose a file to save" );
523   if(!file.isEmpty())
524     _myOFN->setText(file);
525
526   // Selection du Fichier
527 //   file = SUIT_FileDlg::getFileName(application()->desktop(),
528 //                                 "",
529 //                                 filtersList,
530 //                                 "Output MED file name",
531 //                                 true);
532 }
533
534 void SelectParams::process()
535 {
536   string command;
537
538   // send filtoo command
539   MESSAGE("Input MED File : "<<_inputFile);
540   MESSAGE("Input Mesh : "<<_inputMesh);
541   MESSAGE("Input Field : "<<_inputField);
542   MESSAGE("Input Time Step : "<<_inputTS);
543   MESSAGE("Output file name: " << _myOFN->text() );
544   command = "cd /export/home/secher/filtoo/example;filtoo -f s -o sf > /tmp/filter.log";
545   MESSAGE(command);
546   system(command.c_str());
547 //   delete this;
548 }
549
550 void SelectParams::calcRateRed()
551 {
552   int i1, i2, i;
553   int atot=0, asel=0, atot1;
554   double rateRed=0.0;
555   char strth[128];
556
557   // calculate reduction rate depend on reference area defined by threshold values
558   i1 = (int)((double)_size * ( _fthresh - _xmin ) / ( _xmax - _xmin ));
559   if( _myOneThresh->isChecked() ){
560     for(i=0;i<i1;i++)
561       atot += (int)_y[i];
562     asel = atot;
563     for(i=i1;i<_size;i++)
564       atot += (int)_y[i];
565     if( _myExt->isChecked() )
566       asel = atot - asel;
567   }
568   else{
569     i2 = (int)((double)_size * ( _sthresh - _xmin ) / ( _xmax - _xmin ));
570     if( i2 < i1 ){
571       i=i1;
572       i1=i2;
573       i2=i;
574     }
575     for(i=0;i<i1;i++)
576       atot += (int)_y[i];
577     atot1=atot;
578     for(i=i1;i<i2;i++)
579       atot += (int)_y[i];
580     asel = atot - atot1;
581     for(i=i2;i<_size;i++)
582       atot += (int)_y[i];
583     if( _myExt->isChecked() )
584       asel = atot - asel;
585   }
586   rateRed = (double)asel / (double) atot;
587
588   // display reduction rate value
589   QString qs(tr("FILTER_RED_RATE"));
590   char str[128];
591   sprintf(str," = %4.2g",rateRed);
592   qs.append(str);
593   _myLRR->setText( qs );
594
595 }
596