Salome HOME
76caaec02e245bdb03c0fe2a9979cfdb847f38b4
[modules/gui.git] / src / Plot2d / Plot2d_ViewFrame.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 #include "Plot2d_ViewFrame.h"
24
25 #include "Plot2d_Prs.h"
26 #include "Plot2d_Curve.h"
27 #include "Plot2d_PlotItems.h"
28 #include "Plot2d_FitDataDlg.h"
29 #ifndef NO_SUIT
30 #include "Plot2d_ViewWindow.h"
31 #endif
32 #include "Plot2d_SetupViewDlg.h"
33 #ifndef NO_ANALYTICAL_CURVES
34 #include "Plot2d_AnalyticalCurveDlg.h"
35 #include "Plot2d_AnalyticalCurve.h"
36 #endif
37 #include "Plot2d_ToolTip.h"
38
39 #ifndef NO_SUIT
40 #include "SUIT_Tools.h"
41 #include "SUIT_Session.h"
42 #include "SUIT_MessageBox.h"
43 #include "SUIT_ResourceMgr.h"
44 #include "SUIT_Application.h"
45 #else
46 #include <QMessageBox>
47 #endif
48
49 #include <QApplication>
50 #include <QToolBar>
51 #include <QToolButton>
52 #include <QCursor>
53 #include <QColorDialog>
54 #include <QLayout>
55 #include <QMap>
56 #include <QPainter>
57 #include <QPaintDevice>
58 #include <QEvent>
59 #include <QMouseEvent>
60 #include <QContextMenuEvent>
61 #include <QPrinter>
62 #include <QPalette>
63 #include <QLocale>
64 #include <QXmlStreamWriter>
65 #include <QXmlStreamReader>
66
67 #include <qwt_math.h>
68 #include <qwt_plot_layout.h>
69 #include <qwt_plot_canvas.h>
70 #include <qwt_scale_div.h>
71 #include <qwt_plot_marker.h>
72 #include <qwt_plot_curve.h>
73 #include <qwt_plot_grid.h>
74 #include <qwt_scale_engine.h>
75 #include <qwt_plot_zoomer.h>
76 #include <qwt_curve_fitter.h>
77
78 #include <stdlib.h>
79 #include <limits>
80 #include <qprinter.h>
81
82 #include <qwt_legend.h>
83 #include <qwt_scale_widget.h>
84
85 #define DEFAULT_LINE_WIDTH     0     // (default) line width
86 #define DEFAULT_MARKER_SIZE    9     // default marker size
87 #define MIN_RECT_SIZE          11    // min sensibility area size
88
89 #define FITALL_EVENT           ( QEvent::User + 9999 )
90
91 const char* imageZoomCursor[] = {
92 "32 32 3 1",
93 ". c None",
94 "a c #000000",
95 "# c #ffffff",
96 "................................",
97 "................................",
98 ".#######........................",
99 "..aaaaaaa.......................",
100 "................................",
101 ".............#####..............",
102 "...........##.aaaa##............",
103 "..........#.aa.....a#...........",
104 ".........#.a.........#..........",
105 ".........#a..........#a.........",
106 "........#.a...........#.........",
107 "........#a............#a........",
108 "........#a............#a........",
109 "........#a............#a........",
110 "........#a............#a........",
111 ".........#...........#.a........",
112 ".........#a..........#a.........",
113 ".........##.........#.a.........",
114 "........#####.....##.a..........",
115 ".......###aaa#####.aa...........",
116 "......###aa...aaaaa.......#.....",
117 ".....###aa................#a....",
118 "....###aa.................#a....",
119 "...###aa...............#######..",
120 "....#aa.................aa#aaaa.",
121 ".....a....................#a....",
122 "..........................#a....",
123 "...........................a....",
124 "................................",
125 "................................",
126 "................................",
127 "................................"};
128
129 const char* imageCrossCursor[] = {
130   "32 32 3 1",
131   ". c None",
132   "a c #000000",
133   "# c #ffffff",
134   "................................",
135   "................................",
136   "................................",
137   "................................",
138   "................................",
139   "................................",
140   "................................",
141   "...............#................",
142   "...............#a...............",
143   "...............#a...............",
144   "...............#a...............",
145   "...............#a...............",
146   "...............#a...............",
147   "...............#a...............",
148   "...............#a...............",
149   ".......#################........",
150   "........aaaaaaa#aaaaaaaaa.......",
151   "...............#a...............",
152   "...............#a...............",
153   "...............#a...............",
154   "...............#a...............",
155   "...............#a...............",
156   "...............#a...............",
157   "...............#a...............",
158   "................a...............",
159   "................................",
160   "................................",
161   "................................",
162   "................................",
163   "................................",
164   "................................",
165   "................................"};
166
167 #ifdef WIN32
168   #ifdef max
169     #undef max
170   #endif
171
172   #ifdef min
173     #undef min
174   #endif
175 #endif
176
177 /*!
178   Constructor
179 */
180 Plot2d_ViewFrame::Plot2d_ViewFrame( QWidget* parent, const QString& title )
181      : QWidget (parent, 0),
182        myOperation( NoOpId ),
183        myCurveType( 1 ),
184        myShowLegend( true ), myLegendPos( 1 ), myLegendFont("Helvetic",12),
185        myLegendColor(Qt::black),
186        myMarkerSize( DEFAULT_MARKER_SIZE ),
187        myBackground( Qt::white ),
188        myTitle( "" ), myXTitle( "" ), myYTitle( "" ), myY2Title( "" ),
189        myTitleEnabled( true ), myXTitleEnabled( true ),
190        myYTitleEnabled( true ), myY2TitleEnabled (true),
191        myXGridMajorEnabled( true ), myYGridMajorEnabled( true ), myY2GridMajorEnabled( true ),
192        myXGridMinorEnabled( false ), myYGridMinorEnabled( false ), myY2GridMinorEnabled( false ),
193        myXGridMaxMajor( 8 ), myYGridMaxMajor( 8 ), myY2GridMaxMajor( 8 ),
194        myXGridMaxMinor( 5 ), myYGridMaxMinor( 5 ), myY2GridMaxMinor( 5 ),
195        myXMode( 0 ), myYMode( 0 ),myNormLMin(false), myNormLMax(false), myNormRMin(false), myNormRMax(false),
196        mySecondY( false ), myIsDefTitle( true )
197 {
198   setObjectName( title );
199   myRNormAlgo = new Plot2d_NormalizeAlgorithm(this);
200   myLNormAlgo = new Plot2d_NormalizeAlgorithm(this);
201   /* Plot 2d View */
202   QVBoxLayout* aLayout = new QVBoxLayout( this );
203   aLayout->setMargin(0);
204   myPlot = new Plot2d_Plot2d( this );
205   new Plot2d_ToolTip( this );
206
207   aLayout->addWidget( myPlot );
208
209   //  createActions();
210   connect( myPlot, SIGNAL( legendClicked( QwtPlotItem* ) ),
211            this, SIGNAL( legendClicked( QwtPlotItem* ) ) );
212
213   // IPAL 21465
214   /*  connect( myPlot->axisWidget( QwtPlot::xBottom ), SIGNAL( scaleDivChanged() ),
215            myPlot, SLOT( onScaleDivChanged() ) );
216   connect( myPlot->axisWidget( QwtPlot::yLeft ), SIGNAL( scaleDivChanged() ),
217            myPlot, SLOT( onScaleDivChanged() ) );
218   if (mySecondY)
219     connect( myPlot->axisWidget( QwtPlot::yRight ), SIGNAL( scaleDivChanged() ),
220     myPlot, SLOT( onScaleDivChanged() ) );*/
221 #ifndef NO_SUIT
222   Init();
223 #endif
224 }
225 /*!
226   Destructor
227 */
228 Plot2d_ViewFrame::~Plot2d_ViewFrame()
229 {
230 }
231 /*!
232   Performs the initial setup.
233 */
234 void Plot2d_ViewFrame::Init()
235 {
236   /* Initial Setup - get from the preferences */
237   readPreferences();
238
239   myPlot->setMargin( 5 );
240   setCurveType( myCurveType, false );
241   setXGrid( myXGridMajorEnabled, myXGridMaxMajor, myXGridMinorEnabled, myXGridMaxMinor, false );
242   setYGrid( myYGridMajorEnabled, myYGridMaxMajor, myYGridMinorEnabled, myYGridMaxMinor,
243             myY2GridMajorEnabled, myY2GridMaxMajor, myY2GridMinorEnabled, myY2GridMaxMinor, false );
244
245   setTitle( myTitleEnabled,  myTitle,  MainTitle, false );
246   setTitle( myXTitleEnabled, myXTitle, XTitle, false );
247   setTitle( myYTitleEnabled, myYTitle, YTitle, false );
248
249   if (mySecondY)
250     setTitle( myY2TitleEnabled, myY2Title, Y2Title, false );
251   setHorScaleMode( myXMode, false );
252   setVerScaleMode( myYMode, false );
253   setBackgroundColor( myBackground );
254   setLegendPos( myLegendPos );
255   setLegendFont( myLegendFont );
256   setLegendFontColor( myLegendColor );
257   showLegend( myShowLegend, false );
258   myPlot->replot();
259
260   QWidget* aParent = parentWidget();
261   if ( aParent ) {
262     resize( (int)(0.8 * aParent->width()), (int)(0.8 * aParent->height()) );
263   }
264   QwtScaleMap xMap = myPlot->canvasMap( QwtPlot::xBottom );
265   QwtScaleMap yMap = myPlot->canvasMap( QwtPlot::yLeft );
266   myXDistance = xMap.s2() - xMap.s1();
267   myYDistance = yMap.s2() - yMap.s1();
268   myYDistance2 = 0;
269   if (mySecondY) {
270     QwtScaleMap yMap2 = myPlot->canvasMap( QwtPlot::yRight );
271     myYDistance2 = yMap2.s2() - yMap2.s1();
272   }
273   myPlot->canvas()->installEventFilter( this );
274 }
275 /*!
276   Gets window's central widget
277 */
278 QWidget* Plot2d_ViewFrame::getViewWidget()
279 {
280   return (QWidget*)myPlot;
281 }
282 /*!
283   Actually this method just re-displays all curves which are presented in the viewer
284 */
285 void Plot2d_ViewFrame::DisplayAll()
286 {
287   objectList olist;
288   getObjects( olist );
289   foreach ( Plot2d_Object* o, olist )
290     updateObject( o, false );
291   myPlot->replot();
292   if ( myPlot->zoomer() ) myPlot->zoomer()->setZoomBase();
293 }
294 /*!
295    Removes all curves from the view
296 */
297 void Plot2d_ViewFrame::EraseAll()
298 {
299   objectList anObjects;
300   getObjects( anObjects );
301   eraseObjects( anObjects, false );
302   myObjects.clear();
303
304   // 1)- Erase all the intermittent segments who connect curves
305
306   int nbSeg = myIntermittentSegmentList.size();
307   if (nbSeg > 0)
308   {
309       for (int iseg=0; iseg < nbSeg; iseg++)
310       {
311           QwtPlotCurve *segment = myIntermittentSegmentList[iseg];
312
313           segment->detach();  // erase in QwtPlot window
314           delete segment;
315       }
316       myIntermittentSegmentList.clear();
317   }
318
319   // 3)- Erase all QwtPlotCurve associated with the Plot2d_Curve
320
321   int nbCur1 = myQwtPlotCurveList.size();
322   if (nbCur1 > 0)
323   {
324       for (int icur=0; icur < nbCur1; icur++)
325       {
326           QwtPlotItem *curve0 = myQwtPlotCurveList[icur];
327           QwtPlotCurve *curve = static_cast<QwtPlotCurve*>(curve0);
328
329           if (curve)
330           {
331               delete curve;
332           }
333       }
334       myQwtPlotCurveList.clear();
335   }
336
337   // 4)- Erase all curves Plot2d_Curve
338
339   int nbCur = myPlot2dCurveList.size();
340   if (nbCur > 0)
341   {
342       for (int icur=0; icur < nbCur; icur++)
343       {
344           Plot2d_Curve *curve = myPlot2dCurveList[icur];
345
346           if (curve)
347           {
348               delete curve;
349           }
350       }
351       myPlot2dCurveList.clear();
352   }
353   myPlot->replot();
354   if ( myPlot->zoomer() ) myPlot->zoomer()->setZoomBase();
355 }
356 /*!
357   Redraws viewframe contents
358 */
359 void Plot2d_ViewFrame::Repaint()
360 {
361   myPlot->replot();
362 }
363 /*!
364   Display presentation
365 */
366 void Plot2d_ViewFrame::Display( const Plot2d_Prs* prs )
367 {
368   if ( !prs || prs->IsNull() )
369     return;
370
371   setEnableAxis( QwtPlot::yRight, prs->isSecondY() ); // VSR: is it correct? maybe we should only enable second Y axis if required
372
373   // display all objects from presentation
374   objectList anObjects = prs->getObjects();
375   displayObjects( anObjects );
376   setXGrid( myXGridMajorEnabled, myXGridMaxMajor, myXGridMinorEnabled, myXGridMaxMinor, true );
377   setYGrid( myYGridMajorEnabled, myYGridMaxMajor, myYGridMinorEnabled, myYGridMaxMinor,
378             myY2GridMajorEnabled, myY2GridMaxMajor, myY2GridMinorEnabled, myY2GridMaxMinor, true );
379   if ( myPlot->zoomer() ) myPlot->zoomer()->setZoomBase();
380 }
381
382 /*!
383   Erase presentation
384 */
385 void Plot2d_ViewFrame::Erase( const Plot2d_Prs* prs, const bool )
386 {
387   if ( !prs || prs->IsNull() )
388     return;
389
390   // erase all objects from presentation
391   objectList anObjects = prs->getObjects();
392   eraseObjects( anObjects );
393   if ( myPlot->zoomer() ) myPlot->zoomer()->setZoomBase();
394 }
395
396 bool Plot2d_ViewFrame::eventFilter( QObject* watched, QEvent* e )
397 {
398   if ( watched == myPlot->canvas() ) {
399     int aType = e->type();
400     switch( aType ) {
401       case QEvent::MouseMove: {
402         QMouseEvent* me = (QMouseEvent*)e;
403         if ( me && ( me->buttons() != 0 || me->button() != 0 ) ) {
404           QMouseEvent m( QEvent::MouseMove, me->pos(), me->button(),
405                          me->buttons(), me->modifiers() );
406           if ( plotMouseMoved( m ) )
407             return true;
408         }
409         break;
410       }
411       case QEvent::MouseButtonPress: {
412         QMouseEvent* me = (QMouseEvent*)e;
413         if ( me && ( me->buttons() != 0 || me->button() != 0 ) ) {
414           QMouseEvent m( QEvent::MouseButtonPress, me->pos(), me->button(),
415                           me->buttons(), me->modifiers() );
416           plotMousePressed( m );
417         }
418         break;
419       }
420       case QEvent::MouseButtonRelease: {
421         QMouseEvent* me = (QMouseEvent*)e;
422         if ( me && ( me->buttons() != 0 || me->button() != 0 ) ) {
423           QMouseEvent m( QEvent::MouseButtonRelease, me->pos(), me->button(),
424                          me->buttons(), me->modifiers() );
425           plotMouseReleased( m );
426         }
427         break;
428       }
429     case QEvent::ContextMenu:
430       // Fix from SLN
431       // Do nothing because context menu is called from MouseRelease
432       return true;
433     }
434   }
435   return QWidget::eventFilter( watched, e );
436 }
437
438 /*!
439   Sets title
440 */
441 void Plot2d_ViewFrame::setTitle( const QString& title )
442 {
443   setTitle( myTitleEnabled, title, MainTitle, true );
444   myIsDefTitle = false;
445 }
446
447 /*!
448   Gets title
449 */
450 QString Plot2d_ViewFrame::getTitle() const
451 {
452   return myTitle;
453 }
454
455 /*!
456   Reads Plot2d view settings from the preferences
457 */
458 void Plot2d_ViewFrame::readPreferences()
459 {
460 #ifndef NO_SUIT
461   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
462
463   myCurveType = resMgr->integerValue( "Plot2d", "CurveType", myCurveType );
464   setCurveType( resMgr->integerValue( "Plot2d", "CurveType", myCurveType ) );
465
466   myShowLegend = resMgr->booleanValue( "Plot2d", "ShowLegend", myShowLegend );
467   myLegendPos = resMgr->integerValue( "Plot2d", "LegendPos", myLegendPos );
468   myLegendFont = resMgr->fontValue( "Plot2d", "LegendFont", myLegendFont );
469   myLegendColor = resMgr->colorValue( "Plot2d", "LegendFontColor", myLegendColor );
470   myMarkerSize = resMgr->integerValue( "Plot2d", "MarkerSize", myMarkerSize );
471   myBackground = resMgr->colorValue( "Plot2d", "Background", myBackground );
472
473   myTitleEnabled = resMgr->booleanValue( "Plot2d", "ShowTitle", myTitleEnabled );
474   myXTitleEnabled = resMgr->booleanValue( "Plot2d", "ShowHorTitle", myXTitleEnabled );
475   myYTitleEnabled = resMgr->booleanValue( "Plot2d", "ShowVerLeftTitle", myYTitleEnabled );
476   myY2TitleEnabled = resMgr->booleanValue( "Plot2d", "ShowVerRightTitle", myY2TitleEnabled );
477
478   myXGridMajorEnabled = resMgr->booleanValue( "Plot2d", "EnableHorMajorGrid", myXGridMajorEnabled );
479   myYGridMajorEnabled = resMgr->booleanValue( "Plot2d", "EnableVerMajorGrid", myYGridMajorEnabled );
480   myY2GridMajorEnabled = resMgr->booleanValue( "Plot2d", "EnableRightVerMajorGrid", myY2GridMajorEnabled );
481
482   myXGridMinorEnabled = resMgr->booleanValue( "Plot2d", "EnableHorMinorGrid", myXGridMinorEnabled );
483   myYGridMinorEnabled = resMgr->booleanValue( "Plot2d", "EnableVerMinorGrid", myYGridMinorEnabled );
484   myY2GridMinorEnabled = resMgr->booleanValue( "Plot2d", "EnableRightVerMinorGrid", myY2GridMinorEnabled );
485
486   myXGridMaxMajor = resMgr->integerValue( "Plot2d", "HorMajorGridMax", myXGridMaxMajor );
487   myYGridMaxMajor = resMgr->integerValue( "Plot2d", "VerMajorGridMax", myYGridMaxMajor );
488   if ( mySecondY )
489     myY2GridMaxMajor = resMgr->integerValue( "Plot2d", "VerMajorRightGridMax", myY2GridMaxMajor );
490
491   myXGridMaxMinor = resMgr->integerValue( "Plot2d", "HorMinorGridMax", myXGridMaxMinor );
492   myYGridMaxMinor = resMgr->integerValue( "Plot2d", "VerMinorGridMax", myYGridMaxMinor );
493   if ( mySecondY )
494     myY2GridMaxMinor = resMgr->integerValue( "Plot2d", "VerMinorGridMax", myY2GridMaxMinor );
495
496   setHorScaleMode( qMax( 0, qMin( 1, resMgr->integerValue( "Plot2d", "HorScaleMode", myXMode ) ) ), false );
497   setVerScaleMode( qMax( 0, qMin( 1, resMgr->integerValue( "Plot2d", "VerScaleMode", myYMode ) ) ), false );
498   setNormLMinMode( resMgr->booleanValue( "Plot2d", "VerNormLMinMode", myNormLMin ) );
499   setNormLMaxMode( resMgr->booleanValue( "Plot2d", "VerNormLMaxMode", myNormLMax ) );
500   setNormRMinMode( resMgr->booleanValue( "Plot2d", "VerNormRMinMode", myNormRMin ) );
501   setNormRMaxMode( resMgr->booleanValue( "Plot2d", "VerNormRMaxMode", myNormRMax ) );
502   QColor c = resMgr->colorValue( "Plot2d", "DeviationMarkerColor", QColor(255,0,0));
503   myPlot->setProperty(PLOT2D_DEVIATION_COLOR, c);
504   myPlot->setProperty(PLOT2D_DEVIATION_LW,
505                       resMgr->integerValue( "Plot2d", "DeviationMarkerLineWidth", 1));
506   myPlot->setProperty(PLOT2D_DEVIATION_TS,
507                       resMgr->integerValue( "Plot2d", "DeviationMarkerTickSize", 2));
508 #endif
509 }
510
511 /*!
512   Writes Plot2d view settings to the preferences
513 */
514 void Plot2d_ViewFrame::writePreferences()
515 {
516 #ifndef NO_SUIT
517   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
518
519   resMgr->setValue( "Plot2d", "CurveType", myCurveType );
520   resMgr->setValue( "Plot2d", "ShowLegend", myShowLegend );
521   resMgr->setValue( "Plot2d", "LegendPos", myLegendPos );
522   resMgr->setValue( "Plot2d", "LegendFont", myLegendFont );
523   resMgr->setValue( "Plot2d", "LegendFontColor", myLegendColor );
524   resMgr->setValue( "Plot2d", "MarkerSize", myMarkerSize );
525   resMgr->setValue( "Plot2d", "Background", myBackground );
526   resMgr->setValue( "Plot2d", "ShowTitle", myTitleEnabled );
527   resMgr->setValue( "Plot2d", "ShowHorTitle", myXTitleEnabled );
528   resMgr->setValue( "Plot2d", "ShowVerLeftTitle", myYTitleEnabled );
529   if ( mySecondY )
530     resMgr->setValue( "Plot2d", "ShowVerRightTitle", myY2TitleEnabled );
531
532   resMgr->setValue( "Plot2d", "EnableHorMajorGrid", myXGridMajorEnabled );
533   resMgr->setValue( "Plot2d", "EnableVerMajorGrid", myYGridMajorEnabled );
534   resMgr->setValue( "Plot2d", "EnableHorMinorGrid", myXGridMinorEnabled );
535   resMgr->setValue( "Plot2d", "EnableVerMinorGrid", myYGridMinorEnabled );
536
537   resMgr->setValue( "Plot2d", "HorMajorGridMax", myXGridMaxMajor );
538   resMgr->setValue( "Plot2d", "VerMajorGridMax", myYGridMaxMajor );
539
540   resMgr->setValue( "Plot2d", "HorMinorGridMax", myXGridMaxMinor );
541   resMgr->setValue( "Plot2d", "VerMinorGridMax", myYGridMaxMinor );
542
543   resMgr->setValue( "Plot2d", "HorScaleMode", myXMode );
544
545   if ( mySecondY )
546   {
547     resMgr->setValue( "Plot2d", "EnableRightVerMajorGrid", myY2GridMajorEnabled );
548     resMgr->setValue( "Plot2d", "EnableRightVerMinorGrid", myY2GridMinorEnabled );
549     resMgr->setValue( "Plot2d", "VerRightMajorGridMax", myY2GridMaxMajor );
550     resMgr->setValue( "Plot2d", "VerRightMinorGridMax", myY2GridMaxMinor );
551   }
552
553   resMgr->setValue( "Plot2d", "VerScaleMode", myYMode );
554   resMgr->setValue( "Plot2d", "VerNormLMinMode", myNormLMin );
555   resMgr->setValue( "Plot2d", "VerNormLMaxMode", myNormLMax );
556   resMgr->setValue( "Plot2d", "VerNormRMinMode", myNormRMin );
557   resMgr->setValue( "Plot2d", "VerNormRMaxMode", myNormRMax );
558 #endif
559 }
560
561 /*!
562   Prints mouse cursor coordinates into string
563 */
564 QString Plot2d_ViewFrame::getInfo( const QPoint& pnt )
565 {
566   int i;
567   QwtValueList aTicks;
568   bool xFound = false, yFound = false;
569   double xCoord, yCoord;
570   const QwtScaleDiv* aXscale = myPlot->axisScaleDiv( QwtPlot::xBottom );
571   aTicks = aXscale->ticks( QwtScaleDiv::MajorTick );
572   for ( i = 0; i < aTicks.count(); i++ ) {
573     double majXmark = aTicks[i];
574     int xmark = myPlot->transform( QwtPlot::xBottom, majXmark );
575     if ( xmark-2 == pnt.x() ) {
576       xCoord = majXmark;
577       xFound = true;
578       break;
579     }
580   }
581   if ( !xFound ) {
582     aTicks = aXscale->ticks( QwtScaleDiv::MinorTick );
583     for ( i = 0; i < aTicks.count(); i++ ) {
584       double minXmark = aTicks[i];
585       int xmark = myPlot->transform( QwtPlot::xBottom, minXmark );
586       if ( xmark-2 == pnt.x() ) {
587         xCoord = minXmark;
588         xFound = true;
589         break;
590       }
591     }
592   }
593   const QwtScaleDiv* aYscale = myPlot->axisScaleDiv( QwtPlot::yLeft );
594   aTicks = aYscale->ticks( QwtScaleDiv::MajorTick );
595   for ( i = 0; i < aTicks.count(); i++ ) {
596     double majYmark = aTicks[i];
597     int ymark = myPlot->transform( QwtPlot::yLeft, majYmark );
598     if ( ymark-2 == pnt.y() ) {
599       yCoord = majYmark;
600       yFound = true;
601       break;
602     }
603   }
604   if ( !yFound ) {
605     aTicks = aYscale->ticks( QwtScaleDiv::MinorTick );
606     for ( i = 0; i < aTicks.count(); i++ ) {
607       double minYmark = aTicks[i];
608       int ymark = myPlot->transform( QwtPlot::yLeft, minYmark );
609       if ( ymark-2 == pnt.y() ) {
610         yCoord = minYmark;
611         yFound = true;
612         break;
613       }
614     }
615   }
616
617   QString strX = QString::number( xFound ? xCoord : myPlot->invTransform( QwtPlot::xBottom, pnt.x() ) ).trimmed();
618   if ( strX == "-0" )
619     strX = "0";
620   QString strY = QString::number( yFound ? yCoord : myPlot->invTransform( QwtPlot::yLeft, pnt.y() ) ).trimmed();
621   if ( strY == "-0" )
622     strY = "0";
623   QString info = "";
624
625   if (mySecondY) {
626     bool yFound2 = false;
627     double yCoord2;
628
629     const QwtScaleDiv* aYscale2 = myPlot->axisScaleDiv( QwtPlot::yRight );
630     aTicks = aYscale2->ticks( QwtScaleDiv::MajorTick );
631     for ( i = 0; i < aTicks.count(); i++ ) {
632       double majYmark = aTicks[i];
633       int ymark = myPlot->transform( QwtPlot::yRight, majYmark );
634       if ( ymark-2 == pnt.y() ) {
635         yCoord2 = majYmark;
636         yFound2 = true;
637         break;
638       }
639     }
640     if ( !yFound2 ) {
641       aTicks = aYscale2->ticks( QwtScaleDiv::MinorTick );
642       for ( i = 0; i < aTicks.count(); i++ ) {
643         double minYmark = aTicks[i];
644         int ymark = myPlot->transform( QwtPlot::yRight, minYmark );
645         if ( ymark-2 == pnt.y() ) {
646           yCoord2 = minYmark;
647           yFound2 = true;
648           break;
649         }
650       }
651     }
652     QString strY2 = QString::number( yFound2 ? yCoord2 :
653                       myPlot->invTransform( QwtPlot::yRight, pnt.y() ) ).trimmed();
654     if ( strY2 == "-0" )
655     strY2 = "0";
656     info = tr("INF_COORDINATES_SOME_Y").arg( strX ).arg( strY ).arg( strY2 );
657   }
658   else
659     info = tr("INF_COORDINATES").arg( strX ).arg( strY );
660
661   return info;
662 }
663
664 /*!
665  * Display curves of the list of lists by systems and components
666  * - the first level list contains NbSytems lists of second level
667  * - a second level list contains NbComponents curves
668  * |         system 1         |         system 2         | ..... |          system N        |
669  * | compo1 compo2 ... compoM | compo1 compo2 ... compoM | ..... | compo1 compo2 ... compoM |
670  *
671  * Draw points markers and create associated tooltips.
672  * Draw connection segments (intermittent line) between all the curves of a component.
673  * \return the list of underlying plot curve that defines the complex cuve at once. In case of success the vector is at least of size 1. The first one is the curve used by the legend.
674  */
675 QVector< QVector<QwtPlotCurve *> > Plot2d_ViewFrame::displayPlot2dCurveList( const QList< QList<Plot2d_Curve*> >& sysCoCurveList,
676                                                                              bool                          displayLegend,
677                                                                              const QList< QList<bool> >&   sides)
678 {
679   //std::cout << "Plot2d_ViewFrame::displayPlot2dCurveList() 1" << std::endl;
680
681   // Systems number
682   int nbSystem = sysCoCurveList.size();
683
684   // Composants number by system
685   int nbComponent = (sysCoCurveList.at(0)).size();
686
687   // Total number of curves
688
689    // 1)- Construction of a list by component and by system
690
691    // |      component 1      |      component 2      | ..... |      component M      |
692    // | syst1 syst2 ... systN | syst1 syst2 ... systN | ..... | syst1 syst2 ... systN |
693
694   QList<Plot2d_Curve*> plot2dCurveCoSysList;
695   QList<bool>          sidesList;
696   for (int icom = 0; icom < nbComponent; icom++)
697   {
698       for (int isys = 0; isys < nbSystem; isys++)
699       {
700           // The system curves list
701           const QList<Plot2d_Curve*>& sysCurveList=sysCoCurveList.at(isys);
702           plot2dCurveCoSysList.append(sysCurveList.at(icom));
703           //
704           const QList<bool>& sysSideList=sides.at(isys);
705           sidesList.append(sysSideList.at(icom));
706       }
707   }
708   // 2)- Display list curves by a component's curves group
709   //     Draw connection segments (intermittent line) between the curves
710   QVector< QVector<QwtPlotCurve *> > ret=displayPlot2dCurveList( plot2dCurveCoSysList, nbSystem, displayLegend, sidesList);
711   // 3)- Size of graduations labels and texts under X axis
712   QwtScaleWidget *wid = myPlot->axisWidget( QwtPlot::xBottom);
713   wid->setTitle("  "); // to make the names readable under X axis.
714   QFont xFont = myPlot->axisFont(QwtPlot::xBottom);
715   xFont.setPointSize(8);
716   myPlot->setAxisFont(QwtPlot::xBottom, xFont);
717   return ret;
718 }
719
720
721 /*!
722  * Display list of curves by group of consecutive curves.
723  *
724  * Draw points markers and create associated tooltips
725  * Draw connection segments (intermittent line) between the curves
726  * \param [in] sides sorted as in \b curveList. If true->right if false->left
727  * \return the list of underlying plot curve that defines the complex cuve at once. In case of success the vector is at least of size 1. The first one is the curve used by the legend.
728  */
729 QVector< QVector<QwtPlotCurve *> > Plot2d_ViewFrame::displayPlot2dCurveList( const QList<Plot2d_Curve*>& curveList,
730                                                                              int  groupSize,
731                                                                              bool  displayLegend, const QList< bool >& sides)
732 {
733   // Consider the new legend's entries
734   // (PB: to update the legend we must remove it and put a new QwtLegend in the QwtPlot)
735   myPlot->insertLegend( (QwtLegend*)NULL); // we remove here, we shall put at the end
736
737   int nbAllCurves = curveList.size();
738   int nbGroups    = nbAllCurves / groupSize;
739   QVector< QVector<QwtPlotCurve *> > vectCurve(nbGroups);
740   int ig, icur;
741   int icur1, icur2;  // curves indices in a group
742
743   // I)- Compute X range and Y range for all the curves' points of all groups
744   //     In the graphic view, set the Y range 's bounds for all groups of curves
745
746   // For all groups of curves
747   double XallGroupMin=std::numeric_limits<double>::max(), XallGroupMax=-std::numeric_limits<double>::max();
748   double YRightallGroupMin=std::numeric_limits<double>::max(), YRightallGroupMax=-std::numeric_limits<double>::max();
749   double YLeftallGroupMin=std::numeric_limits<double>::max(), YLeftallGroupMax=-std::numeric_limits<double>::max();
750   icur1 = 0;
751   for (ig=0; ig < nbGroups; ig++)  //*1*
752   {
753       icur2 = icur1 + groupSize -1;
754
755       // For all curves in one group
756       double XgroupMin, XgroupMax;
757       double YgroupMin, YgroupMax;
758
759       // For one curve
760       double XcurveMin, XcurveMax;
761       double YcurveMin, YcurveMax;
762       double *Xval;
763       double *Yval;
764       int nbPoints;
765
766       // Compute X range and Y range for all the curves' points in the group
767       bool side=false;
768       for (icur=icur1; icur <= icur2; icur++)  //*2*
769       {
770           Plot2d_Curve *plot2dCurve = curveList.at(icur);
771           side=sides.at(icur);
772           // Curve points
773           nbPoints = plot2dCurve->getData( &Xval, &Yval);  // dynamic allocation
774
775           for (int ip=0; ip < nbPoints; ip++)
776           {
777               if (ip == 0)  // first point
778               {
779                   XcurveMin = Xval[ip];  XcurveMax = Xval[ip];
780                   YcurveMin = Yval[ip];  YcurveMax = Yval[ip];
781               }
782               else
783               {
784                   if      (Xval[ip] < XcurveMin)  XcurveMin = Xval[ip];
785                   else if (Xval[ip] > XcurveMax)  XcurveMax = Xval[ip];
786                   if      (Yval[ip] < YcurveMin)  YcurveMin = Yval[ip];
787                   else if (Yval[ip] > YcurveMax)  YcurveMax = Yval[ip];
788               }
789           }
790           delete [] Xval;
791           delete [] Yval;
792
793           if (icur == icur1)  // first curve
794           {
795               XgroupMin = XcurveMin;  XgroupMax = XcurveMax;
796               YgroupMin = YcurveMin;  YgroupMax = YcurveMax;
797           }
798           else
799           {
800               if (XcurveMin < XgroupMin)  XgroupMin = XcurveMin;
801               if (XcurveMax > XgroupMax)  XgroupMax = XcurveMax;
802               if (YcurveMin < YgroupMin)  YgroupMin = YcurveMin;
803               if (YcurveMax > YgroupMax)  YgroupMax = YcurveMax;
804           }
805       } //*2*
806
807       if (XgroupMin < XallGroupMin)  XallGroupMin = XgroupMin;
808       if (XgroupMax > XallGroupMax)  XallGroupMax = XgroupMax;
809       if(side)
810         {
811           if (YgroupMin < YRightallGroupMin)  YRightallGroupMin = YgroupMin;
812           if (YgroupMax > YRightallGroupMax)  YRightallGroupMax = YgroupMax;
813         }
814       else
815         {
816           if (YgroupMin < YLeftallGroupMin)  YLeftallGroupMin = YgroupMin;
817           if (YgroupMax > YLeftallGroupMax)  YLeftallGroupMax = YgroupMax;
818         }
819       // First curve of the following group
820       icur1 = icur2 + 1;
821   } //*1*
822   // Set the XY range 's bounds for all groups of curves
823   if(YRightallGroupMin!=std::numeric_limits<double>::max())
824     {
825       double deltaY = YRightallGroupMax - YRightallGroupMin;
826       YRightallGroupMin-=0.05*deltaY; YRightallGroupMax+= 0.05*deltaY;
827       myPlot->setAxisScale( QwtPlot::yRight, YRightallGroupMin,YRightallGroupMax);
828     }
829   if(YLeftallGroupMin!=std::numeric_limits<double>::max())
830     {
831       double deltaY = YLeftallGroupMax - YLeftallGroupMin;
832       YLeftallGroupMin-=0.05*deltaY; YLeftallGroupMax+= 0.05*deltaY;
833       myPlot->setAxisScale( QwtPlot::yLeft, YLeftallGroupMin, YLeftallGroupMax);
834     }
835   // II)- Drawing curves, points markers and connection segments
836
837   icur1 = 0;
838   for (ig=0; ig < nbGroups; ig++)
839   {
840       // 1)- Graphical attributs of group's curves
841
842       // Graphical attributes of the first group's curve
843       //
844       Plot2d_Curve *plot2dCurve1 = curveList.at(icur1);
845       //
846       QColor color1 = plot2dCurve1->getColor();
847       Plot2d::LineType linetype1 = plot2dCurve1->getLine();
848       int lineWidth1 = plot2dCurve1->getLineWidth();
849       QwtSymbol::Style symbolStyle1 = plot2dCurve1->getMarkerStyle();
850       // We attribute to the current group's curve, the color, the line's kind
851       // and the marker's kind of the first group's curve
852
853       for (icur=icur1+1; icur<icur1+groupSize; icur++)
854         {
855           Plot2d_Curve *plot2dCurve = curveList.at(icur);
856           //
857           plot2dCurve->setColor(color1);
858           plot2dCurve->setLine(linetype1,lineWidth1);
859           plot2dCurve->setMarkerStyle(symbolStyle1);
860         }
861
862       // 2)- Display the group's curves
863
864       for (icur=icur1; icur<icur1+groupSize; icur++)
865       {
866           Plot2d_Curve *plot2dCurve = curveList.at(icur);
867
868           QString title = plot2dCurve->getVerTitle();
869           std::string std_title = title.toStdString();
870           // Create the graphic curve (QwtPlotCurve) et display it in the drawing zone
871           // (Qwtplot)
872           displayCurve(plot2dCurve);
873
874           // Get the graphic curve
875           QwtPlotCurve* plotCurve = dynamic_cast<QwtPlotCurve *>(getPlotObject(plot2dCurve));
876           vectCurve[ig].push_back(plotCurve);
877           // Modify the points' markers
878           QwtSymbol symbol(plotCurve->symbol()) ;
879           symbol.setStyle(symbolStyle1);
880           symbol.setPen(QPen(color1,lineWidth1));
881           //symbol.setBrush( QBrush( color1));
882           //QSize size = 0.5*(symbol.size());
883           //symbol.setSize(size);
884           //
885           plotCurve->setPen(QPen(color1,lineWidth1));
886           plotCurve->setSymbol(symbol);
887
888           if (icur > icur1)
889           {
890               //std::cout << "  courbe d'indice " << icur << " sans entree dans la legende" << std::endl;
891
892               // The curve must not have legend's entry
893               plotCurve->setItemAttribute( QwtPlotItem::Legend, false);
894           }
895           else
896           {
897               plotCurve->setItemAttribute( QwtPlotItem::Legend, true);
898           }
899       }
900
901       // 3)- Intermittent segments to connect all the group's curves
902
903       if (groupSize > 1)
904       {
905           double *Xval;
906           double *Yval;
907           int nbPoints;
908           double Xseg[2], Yseg[2];
909           Plot2d_Curve *plot2dCurve1 = curveList.at(icur1);
910           bool side = sides.at(icur1);
911           // Last point of the first curve
912           nbPoints = plot2dCurve1->getData( &Xval, &Yval);  // dynamic allocation
913           Xseg[0] = Xval[ nbPoints -1];
914           Yseg[0] = Yval[ nbPoints -1];
915           delete [] Xval;
916           delete [] Yval;
917
918           for (icur=icur1+1; icur<icur1+groupSize; icur++)
919           {
920               Plot2d_Curve *plot2dCurve = curveList.at(icur);
921
922               // First curve's point
923               nbPoints = plot2dCurve->getData( &Xval, &Yval);
924               Xseg[1] = Xval[0];
925               Yseg[1] = Yval[0];
926
927               vectCurve[ig].push_back(createSegment(Xseg,Yseg,2,Qt::DotLine,lineWidth1,color1,QwtSymbol::NoSymbol,side));
928
929               // Last curve's point
930               Xseg[0] = Xval[ nbPoints -1];
931               Yseg[0] = Yval[ nbPoints -1];
932               delete [] Xval;
933               delete [] Yval;
934           }
935       }
936       // First curve of the following group
937       icur1 += groupSize;
938   }
939
940   if (displayLegend)
941     {
942       // Consider the new legend's entries
943       if(!curveList.empty())
944         showLegend( true, true);  // show, update
945     }
946   return vectCurve;
947 }
948
949
950 /*!
951  * Create and display an y=f(x) curve of points
952  * Parameters :
953  *   toDraw : true => Display the created curve
954  *                    Draw the points'markers and create associated tooltips
955  */
956 Plot2d_Curve* Plot2d_ViewFrame::createPlot2dCurve( QString & title,
957                                                    QString & unit,
958                                                    QList<double> & xList,
959                                                    QList<double> & yList,
960                                                    QList<QString> & tooltipList,
961                                                    Plot2d::LineType lineKind,
962                                                    int lineWidth,
963                                                    QColor & lineColor,
964                                                    QwtSymbol::Style markerKind,
965                                                    Plot2d_QwtPlotPicker* picker,
966                                                    bool toDraw,
967                                                    bool displayLegend)
968 {
969   //std::cout << "Plot2d_ViewFrame::createPlot2dCurve()" << std::endl;
970
971   // Mathematical curve
972   Plot2d_Curve* plot2dCurve = new Plot2d_Curve();
973
974   // To deallocate in EraseAll()
975   myPlot2dCurveList.append( plot2dCurve);
976
977   int nbPoint = xList.size();
978   double xVal, yVal;
979   QString tooltip;
980
981   for (int ip=0; ip < nbPoint; ip++)
982   {
983       xVal = xList.at(ip);
984       yVal = yList.at(ip);
985       tooltip = tooltipList.at(ip);
986
987       plot2dCurve->addPoint( xVal, yVal, tooltip);
988   }
989
990   plot2dCurve->setVerTitle( title);
991   plot2dCurve->setVerUnits( unit);
992   if (lineColor.isValid())
993   {
994       plot2dCurve->setColor( lineColor);
995   }
996   plot2dCurve->setLine( lineKind, lineWidth);
997   plot2dCurve->setMarkerStyle( markerKind);
998   plot2dCurve->setMarkerSize(1);
999
1000   // Graphical curve (QwtPlotCurve) in the drawing zone (QwtPlot) myPlot
1001   if (toDraw)
1002   {
1003       if (!displayLegend)
1004         {
1005           myPlot->insertLegend( (QwtLegend*)NULL);
1006         }
1007       displayCurve( plot2dCurve);
1008
1009       // Get the graphical curve
1010       QwtPlotCurve* plotCurve = dynamic_cast<QwtPlotCurve *>( getPlotObject( plot2dCurve));
1011
1012       QColor theColor;
1013
1014       if (lineColor.isValid())
1015       {
1016         //std::cout << "  valid color" << std::endl;
1017           theColor = lineColor;
1018       }
1019       else
1020       {
1021         //std::cout << "  valid color" << std::endl;
1022           QPen pen = plotCurve->pen();
1023           theColor = pen.color();
1024       }
1025
1026       // Modify points' markers
1027       QwtSymbol symbol (plotCurve->symbol()) ;
1028       symbol.setStyle( markerKind);
1029       //
1030       if (markerKind != QwtSymbol::NoSymbol)
1031       {
1032           symbol.setPen( QPen( theColor, lineWidth));
1033           symbol.setBrush( QBrush( theColor));
1034           QSize size = 2.0*(symbol.size()); //0.5
1035           symbol.setSize(size);
1036       }
1037
1038       plotCurve->setSymbol( symbol);
1039       plotCurve->setStyle( QwtPlotCurve::Lines);
1040       plotCurve->setPen( QPen( theColor, lineWidth));
1041
1042       // The curve must not have legend's entry
1043       plotCurve->setItemAttribute( QwtPlotItem::Legend, false);
1044   }
1045   return plot2dCurve;
1046 }
1047
1048
1049 /*!
1050  * Get curve's color
1051  */
1052 QColor Plot2d_ViewFrame::getPlot2dCurveColor( Plot2d_Curve* plot2dCurve)
1053 {
1054
1055   // Get graphical curve
1056   QwtPlotCurve* plotCurve = dynamic_cast<QwtPlotCurve *>( getPlotObject( plot2dCurve));
1057
1058   QPen pen = plotCurve->pen();
1059   QColor color = pen.color();
1060
1061   return color;
1062 }
1063
1064
1065 /*!
1066  * Create and display a segment with nbPoint=2 points
1067  */
1068 QwtPlotCurve *Plot2d_ViewFrame::createSegment( double *X, double *Y, int nbPoint,
1069                                                Qt::PenStyle lineKind,
1070                                                int lineWidth,
1071                                                QColor & lineColor,
1072                                                QwtSymbol::Style markerKind, bool side)
1073 {
1074   QwtPlotCurve* aPCurve = new QwtPlotCurve();
1075
1076   aPCurve->setData( X, Y, nbPoint);
1077
1078   aPCurve->setPen( QPen( lineColor, lineWidth, lineKind));
1079   QwtSymbol aSymbol;
1080   aSymbol.setStyle( markerKind);
1081   aPCurve->setSymbol( aSymbol);
1082
1083   // The segment must not have legend's entry
1084   aPCurve->setItemAttribute( QwtPlotItem::Legend, false);
1085
1086   aPCurve->attach(myPlot);
1087   aPCurve->setYAxis(side ? QwtPlot::yRight : QwtPlot::yLeft);
1088   // To deallocate in EraseAll()
1089   myIntermittentSegmentList.append(aPCurve);
1090   return aPCurve;
1091 }
1092
1093 /*!
1094   Adds curve into view
1095 */
1096 void Plot2d_ViewFrame::displayCurve( Plot2d_Curve* curve, bool update )
1097 {
1098   QwtPlotItem* anItem = displayObject( curve, update );
1099   // To deallocate in EraseAll()
1100   myQwtPlotCurveList.append( anItem);
1101 }
1102
1103 /*!
1104   Adds curves into view
1105 */
1106 void Plot2d_ViewFrame::displayCurves( const curveList& curves, bool update )
1107 {
1108   objectList objects;
1109   foreach ( Plot2d_Curve* curve, curves )
1110     objects << curve;
1111   displayObjects( objects, update );
1112 }
1113
1114 /*!
1115   Erases curve
1116 */
1117 void Plot2d_ViewFrame::eraseCurve( Plot2d_Curve* curve, bool update )
1118 {
1119   eraseObject( curve, update );
1120 }
1121
1122 /*!
1123   Erases curves
1124 */
1125 void Plot2d_ViewFrame::eraseCurves( const curveList& curves, bool update )
1126 {
1127   objectList objects;
1128   foreach ( Plot2d_Curve* curve, curves )
1129     objects << curve;
1130   eraseObjects( objects, update );
1131 }
1132
1133 /*!
1134   Updates curves attributes
1135 */
1136 void Plot2d_ViewFrame::updateCurve( Plot2d_Curve* curve, bool update )
1137 {
1138   updateObject( curve, update );
1139 }
1140
1141 void Plot2d_ViewFrame::processFiltering(bool update)
1142 {
1143   CurveDict aCurves = getCurves();
1144   AlgoPlot2dInputData aLData, aRData;
1145   CurveDict::iterator it;
1146   for ( it = aCurves.begin(); it != aCurves.end(); it++ ) {
1147     Plot2d_Object* objItem = it.value();
1148     if (objItem->getYAxis() == QwtPlot::yRight)
1149       aRData.append(objItem);
1150     else
1151       aLData.append(objItem);
1152   }
1153
1154 // Normalization by left Y axis
1155   if (!myNormLMin && !myNormLMax)
1156     myLNormAlgo->setNormalizationMode(Plot2d_NormalizeAlgorithm::NormalizeNone);
1157   if(myNormLMin && myNormLMax)
1158     myLNormAlgo->setNormalizationMode(Plot2d_NormalizeAlgorithm::NormalizeToMinMax);
1159   else if(myNormLMin)
1160     myLNormAlgo->setNormalizationMode(Plot2d_NormalizeAlgorithm::NormalizeToMin);
1161   else if(myNormLMax)
1162     myLNormAlgo->setNormalizationMode(Plot2d_NormalizeAlgorithm::NormalizeToMax);
1163
1164   myLNormAlgo->setInput(aLData);
1165   myLNormAlgo->execute();
1166
1167 // Normalization by right Y axis
1168   if (!myNormRMin && !myNormRMax)
1169     myRNormAlgo->setNormalizationMode(Plot2d_NormalizeAlgorithm::NormalizeNone);
1170   if(myNormRMin && myNormRMax)
1171     myRNormAlgo->setNormalizationMode(Plot2d_NormalizeAlgorithm::NormalizeToMinMax);
1172   else if(myNormRMin)
1173     myRNormAlgo->setNormalizationMode(Plot2d_NormalizeAlgorithm::NormalizeToMin);
1174   else if(myNormRMax)
1175     myRNormAlgo->setNormalizationMode(Plot2d_NormalizeAlgorithm::NormalizeToMax);
1176
1177   myRNormAlgo->setInput(aRData);
1178   myRNormAlgo->execute();
1179
1180   for ( it = aCurves.begin(); it != aCurves.end(); it++) {
1181     QwtPlotCurve* item = it.key();
1182     Plot2d_Object* objItem = it.value();
1183     updatePlotItem(objItem, item);
1184   }
1185   if(update)
1186   myPlot->replot();
1187 }
1188
1189 /*!
1190   Gets lsit of displayed curves
1191 */
1192 int Plot2d_ViewFrame::getCurves( curveList& curves ) const
1193 {
1194   curves.clear();
1195
1196   CurveDict aCurves = getCurves();
1197   CurveDict::iterator it;
1198   for ( it = aCurves.begin(); it != aCurves.end(); it++ )
1199     curves << it.value();
1200   return curves.count();
1201 }
1202
1203 CurveDict Plot2d_ViewFrame::getCurves() const
1204 {
1205   CurveDict curves;
1206   ObjectDict::const_iterator it = myObjects.begin(), aLast = myObjects.end();
1207   for ( ; it != aLast; it++ ) {
1208     QwtPlotItem* anItem = it.key();
1209     if ( anItem && anItem->rtti() == QwtPlotItem::Rtti_PlotCurve ) {
1210       QwtPlotCurve* aPCurve = dynamic_cast<QwtPlotCurve*>( anItem );
1211       Plot2d_Curve* aCurve = dynamic_cast<Plot2d_Curve*>( it.value() );
1212       if ( aPCurve && aCurve )
1213         curves.insert( aPCurve, aCurve );
1214     }
1215   }
1216   return curves;
1217 }
1218
1219 /*!
1220   Adds object into view
1221 */
1222 QwtPlotItem* Plot2d_ViewFrame::displayObject( Plot2d_Object* object, bool update )
1223 {
1224   QwtPlotItem* anItem = 0;
1225   if ( !object )
1226     return anItem;
1227
1228   if ( object->getYAxis() == QwtPlot::yRight )
1229     mySecondY = true;
1230
1231   // san -- Protection against QwtCurve bug in Qwt 0.4.x:
1232   // it crashes if switched to X/Y logarithmic mode, when one or more points have
1233   // non-positive X/Y coordinate
1234   if ( myXMode && object->getMinX() <= 0. )
1235     setHorScaleMode( 0, false );
1236   if ( myYMode && object->getMinY() <= 0. )
1237     setVerScaleMode( 0, false );
1238
1239   if ( object->isAutoAssign() )
1240     object->autoFill( myPlot );
1241
1242   if ( hasPlotObject( object ) ) {
1243     processFiltering(update);
1244     updateObject( object, update );
1245   }
1246   else {
1247     anItem = object->createPlotItem();
1248     anItem->attach( myPlot );
1249     myObjects.insert( anItem, object );
1250     //myPlot->setCurveYAxis(curveKey, curve->getYAxis());
1251
1252     if ( object->rtti() == QwtPlotItem::Rtti_PlotCurve )
1253     {
1254       Plot2d_Curve* aCurve = dynamic_cast<Plot2d_Curve*>( object );
1255       if ( aCurve )
1256       {
1257         //myMarkerSize = 1;
1258         //aCurve->setMarkerSize( myMarkerSize );
1259
1260         if (aCurve->getMarkerSize() == 0)
1261         {
1262             aCurve->setMarkerSize( myMarkerSize );
1263         }
1264
1265         processFiltering(update);
1266         updatePlotItem( aCurve, anItem );
1267         setCurveType( getPlotCurve( aCurve ), myCurveType );
1268       }
1269     }
1270   }
1271   updateTitles( false );
1272   myPlot->updateYAxisIdentifiers();
1273   if ( update ) {
1274     myPlot->replot();
1275     if ( myPlot->zoomer() ) myPlot->zoomer()->setZoomBase(false);
1276   }
1277   return anItem;
1278 }
1279
1280 /*!
1281   Adds objects into view
1282 */
1283 void Plot2d_ViewFrame::displayObjects( const objectList& objects, bool update )
1284 {
1285   //myPlot->setUpdatesEnabled( false ); // call this function deprecate update of legend
1286   foreach ( Plot2d_Object* object, objects )
1287     displayObject( object, false );
1288   fitAll();
1289   //myPlot->setUpdatesEnabled( true );
1290   // update legend
1291   if ( update )
1292     myPlot->replot();
1293 }
1294
1295 /*!
1296   Erases object
1297 */
1298 void Plot2d_ViewFrame::eraseObject( Plot2d_Object* object, bool update )
1299 {
1300   if ( !object )
1301     return;
1302
1303   if ( hasPlotObject( object ) ) {
1304     QwtPlotItem* anObject = getPlotObject( object );
1305     eraseBasicObject(anObject,update);
1306   }
1307   if (update) {
1308     if ( myPlot->zoomer() ) myPlot->zoomer()->setZoomBase();
1309   }
1310 }
1311
1312 void Plot2d_ViewFrame::eraseBasicObject( QwtPlotItem *object, bool update )
1313 {
1314   if(!object)
1315     return;
1316   object->hide();
1317   object->detach();
1318   myObjects.remove(object);
1319   updateTitles(update);
1320   myPlot->updateYAxisIdentifiers();
1321   if ( update )
1322     myPlot->replot();
1323 }
1324
1325 /*!
1326   Erases objects
1327 */
1328 void Plot2d_ViewFrame::eraseObjects( const objectList& objects, bool update )
1329 {
1330   foreach ( Plot2d_Object* object, objects )
1331     eraseObject( object, false );
1332
1333   //  fitAll();
1334   if ( update )
1335     myPlot->replot();
1336   if ( myPlot->zoomer() ) myPlot->zoomer()->setZoomBase();
1337 }
1338
1339 void Plot2d_ViewFrame::eraseBasicObjects( const QList<QwtPlotItem*> &objects, bool update)
1340 {
1341   foreach ( QwtPlotItem* object, objects )
1342     eraseBasicObject( object, false );
1343   //  fitAll();
1344   if ( update )
1345     myPlot->replot();
1346   if ( myPlot->zoomer() ) myPlot->zoomer()->setZoomBase();
1347 }
1348
1349 /*!
1350   Updates objects attributes
1351 */
1352 void Plot2d_ViewFrame::updateObject( Plot2d_Object* object, bool update )
1353 {
1354   if ( !object )
1355     return;
1356   if ( hasPlotObject( object ) ) {
1357     QwtPlotItem* anItem = getPlotObject( object );
1358     if ( !anItem )
1359       return;
1360     updatePlotItem(object, anItem );
1361     anItem->setVisible( true );
1362     if ( update ) {
1363       myPlot->replot();
1364       if ( myPlot->zoomer() ) myPlot->zoomer()->setZoomBase(false);
1365     }
1366   }
1367 }
1368
1369 /*!
1370   Gets lsit of displayed curves
1371 */
1372 int Plot2d_ViewFrame::getObjects( objectList& objects ) const
1373 {
1374   objects.clear();
1375
1376   ObjectDict::const_iterator it;
1377   for ( it = myObjects.begin(); it != myObjects.end(); it++ )
1378     objects << it.value();
1379   return objects.count();
1380 }
1381
1382 /*!
1383   Returns true if the curve is visible
1384 */
1385 bool Plot2d_ViewFrame::isVisible( Plot2d_Object* object ) const
1386 {
1387   return object && hasPlotObject( object ) && getPlotObject( object )->isVisible();
1388 }
1389
1390 /*!
1391   update legend
1392 */
1393 void Plot2d_ViewFrame::updateLegend( const Plot2d_Prs* prs )
1394 {
1395   if ( !prs || prs->IsNull() )
1396     return;
1397
1398   ObjectDict::iterator it = myObjects.begin();
1399   Plot2d_Object* anObj;
1400   for (; it != myObjects.end(); ++it ) {
1401     anObj = *it;
1402     if ( hasPlotObject( anObj ) )
1403       getPlotObject( anObj )->setTitle( !anObj->getName().isEmpty() ?
1404                             anObj->getName() : anObj->getVerTitle() );
1405   }
1406 }
1407
1408 /*!
1409   update legend
1410 */
1411 void Plot2d_ViewFrame::updateLegend() {
1412   if ( myPlot->getLegend() ) {
1413     ObjectDict::iterator it = myObjects.begin();
1414     for( ; it != myObjects.end(); ++it )
1415       it.key()->updateLegend(myPlot->getLegend());
1416   }
1417 }
1418
1419
1420 /*!
1421   Fits the view to see all data
1422 */
1423 void Plot2d_ViewFrame::fitAll()
1424 {
1425   // Postpone fitAll operation until QwtPlot geometry
1426   // has been fully defined
1427   if ( !myPlot->polished() ){
1428     QApplication::postEvent( this, new QEvent( (QEvent::Type)FITALL_EVENT ) );
1429     return;
1430   }
1431
1432   // no need to set auto scaling, it wiil be disabled by setAxisScale() method call
1433   // myPlot->setAxisAutoScale( QwtPlot::yLeft );
1434   // myPlot->setAxisAutoScale( QwtPlot::xBottom );
1435   // myPlot->replot();
1436
1437   double xmin, xmax, y1min, y1max, y2min, y2max;
1438   getFitRangeByCurves(xmin, xmax, y1min, y1max, y2min, y2max);
1439   getFitRangeByMarkers(xmin, xmax, y1min, y1max, y2min, y2max);
1440
1441   myPlot->setAxisScale( QwtPlot::xBottom, xmin, xmax );
1442   myPlot->setAxisScale( QwtPlot::yLeft, y1min, y1max );
1443
1444   if (mySecondY) {
1445     myPlot->setAxisAutoScale( QwtPlot::yRight );
1446     myPlot->replot();
1447     myPlot->setAxisScale( QwtPlot::yRight, y2min, y2max );
1448   }
1449   myPlot->replot();
1450   if ( myPlot->zoomer() ) myPlot->zoomer()->setZoomBase(false);
1451 }
1452
1453 /*!
1454   Fits the view to rectangle area (pixels)
1455 */
1456 void Plot2d_ViewFrame::fitArea( const QRect& area )
1457 {
1458   QRect rect = area.normalized();
1459   if ( rect.width() < MIN_RECT_SIZE ) {
1460     rect.setWidth( MIN_RECT_SIZE );
1461     rect.setLeft( rect.left() - MIN_RECT_SIZE/2 );
1462   }
1463   if ( rect.height() < MIN_RECT_SIZE ) {
1464     rect.setHeight( MIN_RECT_SIZE );
1465     rect.setTop( rect.top() - MIN_RECT_SIZE/2 );
1466   }
1467   myPlot->setAxisScale( QwtPlot::yLeft,
1468             myPlot->invTransform( QwtPlot::yLeft, rect.top() ),
1469             myPlot->invTransform( QwtPlot::yLeft, rect.bottom() ) );
1470   if (mySecondY)
1471     myPlot->setAxisScale( QwtPlot::yRight,
1472             myPlot->invTransform( QwtPlot::yRight, rect.top() ),
1473             myPlot->invTransform( QwtPlot::yRight, rect.bottom() ) );
1474   myPlot->setAxisScale( QwtPlot::xBottom,
1475             myPlot->invTransform( QwtPlot::xBottom, rect.left() ),
1476             myPlot->invTransform( QwtPlot::xBottom, rect.right() ) );
1477   myPlot->replot();
1478   if ( myPlot->zoomer() ) myPlot->zoomer()->setZoomBase();
1479 }
1480
1481 /*!
1482   "Fit Data" command for TUI interface
1483 */
1484 void Plot2d_ViewFrame::fitData(const int mode,
1485                                const double xMin, const double xMax,
1486                                const double yMin, const double yMax,
1487                                double y2Min, double y2Max)
1488 {
1489   if ( mode == 0 || mode == 2 ) {
1490     myPlot->setAxisScale( QwtPlot::yLeft, yMin, yMax );
1491     if (mySecondY)
1492       myPlot->setAxisScale( QwtPlot::yRight, y2Min, y2Max );
1493   }
1494   if ( mode == 0 || mode == 1 )
1495     myPlot->setAxisScale( QwtPlot::xBottom, xMin, xMax );
1496   myPlot->replot();
1497   if ( myPlot->zoomer() ) myPlot->zoomer()->setZoomBase();
1498 }
1499
1500 /*!
1501   Gets current fit ranges for view frame
1502 */
1503 void Plot2d_ViewFrame::getFitRanges(double& xMin,double& xMax,
1504                                     double& yMin, double& yMax,
1505                                     double& y2Min, double& y2Max)
1506 {
1507   int ixMin = myPlot->canvasMap( QwtPlot::xBottom ).transform( myPlot->canvasMap( QwtPlot::xBottom ).s1() );
1508   int ixMax = myPlot->canvasMap( QwtPlot::xBottom ).transform( myPlot->canvasMap( QwtPlot::xBottom ).s2() );
1509   int iyMin = myPlot->canvasMap( QwtPlot::yLeft ).transform( myPlot->canvasMap( QwtPlot::yLeft ).s1() );
1510   int iyMax = myPlot->canvasMap( QwtPlot::yLeft ).transform( myPlot->canvasMap( QwtPlot::yLeft ).s2() );
1511   xMin = myPlot->invTransform(QwtPlot::xBottom, ixMin);
1512   xMax = myPlot->invTransform(QwtPlot::xBottom, ixMax);
1513   yMin = myPlot->invTransform(QwtPlot::yLeft, iyMin);
1514   yMax = myPlot->invTransform(QwtPlot::yLeft, iyMax);
1515   y2Min = 0;
1516   y2Max = 0;
1517   if (mySecondY) {
1518     int iyMin = myPlot->canvasMap( QwtPlot::yRight ).transform( myPlot->canvasMap( QwtPlot::yRight ).s1() );
1519     int iyMax = myPlot->canvasMap( QwtPlot::yRight ).transform( myPlot->canvasMap( QwtPlot::yRight ).s2() );
1520     y2Min = myPlot->invTransform(QwtPlot::yRight, iyMin);
1521     y2Max = myPlot->invTransform(QwtPlot::yRight, iyMax);
1522   }
1523 }
1524
1525 /*!
1526   Gets current fit ranges by Curves
1527 */
1528 void Plot2d_ViewFrame::getFitRangeByCurves(double& xMin,  double& xMax,
1529                                            double& yMin,  double& yMax,
1530                                            double& y2Min, double& y2Max)
1531 {
1532   bool emptyV1 = true, emptyV2 = true;
1533   if ( !myObjects.isEmpty() ) {
1534     ObjectDict::const_iterator it = myObjects.begin();
1535     for ( ; it != myObjects.end(); it++ ) {
1536       bool isV2 = it.value()->getYAxis() == QwtPlot::yRight;
1537       if ( !it.value()->isEmpty() ) {
1538         if ( emptyV1 && emptyV2 ) {
1539           xMin = 1e150;
1540           xMax = -1e150;
1541         }
1542         if ( emptyV1 ) {
1543           yMin = 1e150;
1544           yMax = -1e150;
1545         }
1546         if ( emptyV2 ) {
1547           y2Min = 1e150;
1548           y2Max = -1e150;
1549         }
1550         isV2 ? emptyV2 = false : emptyV1 = false;
1551         xMin = qMin( xMin, it.value()->getMinX() );
1552         xMax = qMax( xMax, it.value()->getMaxX() );
1553         if ( isV2 ) {
1554           y2Min = qMin( y2Min, it.value()->getMinY() );
1555           y2Max = qMax( y2Max, it.value()->getMaxY() );
1556         }
1557         else {
1558           yMin = qMin( yMin, it.value()->getMinY() );
1559           yMax = qMax( yMax, it.value()->getMaxY() );
1560         }
1561       }
1562     }
1563     if ( xMin == xMax ) {
1564       xMin = xMin == 0. ? -1. : xMin - xMin/10.;
1565       xMax = xMax == 0. ?  1. : xMax + xMax/10.;
1566     }
1567     if ( yMin == yMax ) {
1568       yMin = yMin == 0. ? -1. : yMin - yMin/10.;
1569       yMax = yMax == 0. ?  1  : yMax + yMax/10.;
1570     }
1571     if ( y2Min == y2Max ) {
1572       y2Min = y2Min == 0. ? -1. : y2Min - y2Min/10.;
1573       y2Max = y2Max == 0. ?  1  : y2Max + y2Max/10.;
1574     }
1575   }
1576   // default values
1577   if ( emptyV1 && emptyV2 ) {
1578     xMin = isModeHorLinear() ? 0.    : 1.;
1579     xMax = isModeHorLinear() ? 1000. : 1e5;
1580   }
1581   if ( emptyV1  ) {
1582     yMin = isModeVerLinear() ? 0.    : 1.;
1583     yMax = isModeVerLinear() ? 1000. : 1e5;
1584   }
1585   if ( emptyV2  ) {
1586     y2Min = isModeVerLinear() ? 0.    : 1.;
1587     y2Max = isModeVerLinear() ? 1000. : 1e5;
1588   }
1589 }
1590
1591 /*!
1592   Gets current fit ranges by Markers
1593   All parameters are inout.
1594 */
1595 void Plot2d_ViewFrame::getFitRangeByMarkers(double& xMin,  double& xMax,
1596                                             double& yMin,  double& yMax,
1597                                             double& y2Min, double& y2Max)
1598 {
1599   Plot2d_QwtPlotPicker *picker=myPlot->getPicker();
1600   if(!picker)
1601     return;
1602   if(picker->pMarkers.empty())
1603     return;
1604   foreach(QwtPlotMarker *mrker,picker->pMarkers)
1605     {
1606       bool isV2 = mrker->yAxis() == QwtPlot::yRight;
1607       xMin = qMin( xMin, mrker->xValue() );
1608       xMax = qMax( xMax, mrker->xValue() );
1609       if ( isV2 ) {
1610         y2Min = qMin( y2Min, mrker->yValue() );
1611         y2Max = qMax( y2Max, mrker->yValue() );
1612       }
1613       else {
1614         yMin = qMin( yMin, mrker->yValue() );
1615         yMax = qMax( yMax, mrker->yValue() );
1616       }
1617       if ( xMin == xMax ) {
1618         xMin = xMin == 0. ? -1. : xMin - xMin/10.;
1619         xMax = xMax == 0. ?  1. : xMax + xMax/10.;
1620       }
1621       if ( yMin == yMax ) {
1622         yMin = yMin == 0. ? -1. : yMin - yMin/10.;
1623         yMax = yMax == 0. ?  1  : yMax + yMax/10.;
1624       }
1625       if ( y2Min == y2Max ) {
1626         y2Min = y2Min == 0. ? -1. : y2Min - y2Min/10.;
1627         y2Max = y2Max == 0. ?  1  : y2Max + y2Max/10.;
1628       }
1629     }
1630 }
1631
1632 /*!
1633   Tests if it is necessary to start operation on mouse action
1634 */
1635 int Plot2d_ViewFrame::testOperation( const QMouseEvent& me )
1636 {
1637   int btn = me.button() | me.modifiers();
1638   const int zoomBtn = Qt::ControlModifier | Qt::LeftButton;
1639   const int panBtn  = Qt::ControlModifier | Qt::MidButton;
1640   const int fitBtn  = Qt::ControlModifier | Qt::RightButton;
1641
1642   int op = NoOpId;
1643   if ( btn == zoomBtn ) {
1644     QPixmap zoomPixmap (imageZoomCursor);
1645     QCursor zoomCursor (zoomPixmap);
1646     myPlot->canvas()->setCursor( zoomCursor );
1647     op = ZoomId;
1648   }
1649   else if ( btn == panBtn ) {
1650     myPlot->canvas()->setCursor( QCursor( Qt::SizeAllCursor ) );
1651     op = PanId;
1652   }
1653   else if ( btn == fitBtn ) {
1654     myPlot->canvas()->setCursor( QCursor( Qt::PointingHandCursor ) );
1655     op = FitAreaId;
1656   }
1657   return op;
1658 }
1659
1660 /*!
1661   "Settings" toolbar action slot
1662 */
1663 void Plot2d_ViewFrame::onSettings()
1664 {
1665 #ifdef TEST_AUTOASSIGN
1666   typedef QMap<int,int> IList;
1667   typedef QMap<QString,int> SList;
1668   IList mars, lins;
1669   SList cols;
1670   cols[ "red-min" ]   = 1000;
1671   cols[ "red-max" ]   = -1;
1672   cols[ "green-min" ] = 1000;
1673   cols[ "green-max" ] = -1;
1674   cols[ "blue-min" ]  = 1000;
1675   cols[ "blue-max" ]  = -1;
1676   for ( unsigned i = 0; i < 10000; i++ ) {
1677     QwtSymbol::Style typeMarker;
1678     QColor           color;
1679     Qt::PenStyle     typeLine;
1680     myPlot->getNextMarker( typeMarker, color, typeLine );
1681     if ( mars.contains(typeMarker) )
1682       mars[ typeMarker ] = mars[ typeMarker ]+1;
1683     else
1684       mars[ typeMarker ] = 0;
1685     if ( lins.contains(typeLine) )
1686       lins[ typeLine ] = lins[ typeLine ]+1;
1687     else
1688       lins[ typeLine ] = 0;
1689     if ( cols[ "red-max" ] < color.red() )
1690       cols[ "red-max" ] = color.red();
1691     if ( cols[ "red-min" ] > color.red() )
1692       cols[ "red-min" ] = color.red();
1693     if ( cols[ "green-max" ] < color.green() )
1694       cols[ "green-max" ] = color.green();
1695     if ( cols[ "green-min" ] > color.green() )
1696       cols[ "green-min" ] = color.green();
1697     if ( cols[ "blue-max" ] < color.blue() )
1698       cols[ "blue-max" ] = color.blue();
1699     if ( cols[ "blue-min" ] > color.blue() )
1700       cols[ "blue-min" ] = color.blue();
1701   }
1702 #endif
1703
1704   Plot2d_SetupViewDlg* dlg = new Plot2d_SetupViewDlg( this, true, mySecondY );
1705   dlg->setMainTitle( myTitleEnabled, myTitle );
1706   dlg->setXTitle( myXTitleEnabled, myXTitle );
1707   dlg->setYTitle( myYTitleEnabled, myYTitle );
1708   if (mySecondY)
1709     dlg->setY2Title( myY2TitleEnabled, myY2Title );
1710   dlg->setCurveType( myCurveType );
1711   dlg->setLegend( myShowLegend, myLegendPos, myLegendFont, myLegendColor );
1712   dlg->setMarkerSize( myMarkerSize );
1713   dlg->setBackgroundColor( myBackground );
1714   dlg->setScaleMode(myXMode, myYMode);
1715   dlg->setLMinNormMode(myNormLMin);
1716   dlg->setLMaxNormMode(myNormLMax);
1717   dlg->setRMinNormMode(myNormRMin);
1718   dlg->setRMaxNormMode(myNormRMax);
1719
1720   QVariant v = myPlot->property(PLOT2D_DEVIATION_LW);
1721   int lw = v.isValid() ? v.toInt() : 1;
1722
1723   v = myPlot->property(PLOT2D_DEVIATION_TS);
1724   int ts = v.isValid() ? v.toInt() : 2;
1725
1726   v = myPlot->property(PLOT2D_DEVIATION_COLOR);
1727   QColor cl =  v.isValid() ? v.value<QColor>() : QColor(255,0,0);
1728
1729   dlg->setDeviationMarkerLw(lw);
1730   dlg->setDeviationMarkerTs(ts);
1731   dlg->setDeviationMarkerCl(cl);
1732
1733   //
1734   dlg->setMajorGrid( myXGridMajorEnabled, myPlot->axisMaxMajor( QwtPlot::xBottom ),
1735          myYGridMajorEnabled, myPlot->axisMaxMajor( QwtPlot::yLeft ),
1736          myY2GridMajorEnabled, myPlot->axisMaxMajor( QwtPlot::yRight ) );
1737   dlg->setMinorGrid( myXGridMinorEnabled, myPlot->axisMaxMinor( QwtPlot::xBottom ),
1738          myYGridMinorEnabled, myPlot->axisMaxMinor( QwtPlot::yLeft ),
1739          myY2GridMinorEnabled, myPlot->axisMaxMinor( QwtPlot::yRight ) );
1740   if ( dlg->exec() == QDialog::Accepted ) {
1741     // horizontal axis title
1742     setTitle( dlg->isXTitleEnabled(), dlg->getXTitle(), XTitle, false );
1743     // vertical left axis title
1744     setTitle( dlg->isYTitleEnabled(), dlg->getYTitle(), YTitle, false );
1745     if (mySecondY) // vertical right axis title
1746       setTitle( dlg->isY2TitleEnabled(), dlg->getY2Title(), Y2Title, false );
1747
1748     // main title
1749     if( dlg->isMainTitleEnabled() && myTitle != dlg->getMainTitle() )
1750       myIsDefTitle = false;
1751     setTitle( dlg->isMainTitleEnabled(), dlg->getMainTitle(), MainTitle, true );
1752     // curve type
1753     if ( myCurveType != dlg->getCurveType() ) {
1754       setCurveType( dlg->getCurveType(), false );
1755     }
1756     // legend
1757     if ( myShowLegend != dlg->isLegendEnabled() ) {
1758       showLegend( dlg->isLegendEnabled(), false );
1759     }
1760     if ( myLegendPos != dlg->getLegendPos() ) {
1761       setLegendPos( dlg->getLegendPos() );
1762     }
1763         if ( myLegendFont != dlg->getLegendFont() ) {
1764       setLegendFont( dlg->getLegendFont() );
1765     }
1766         if ( myLegendColor != dlg->getLegendColor() ) {
1767       setLegendFontColor( dlg->getLegendColor() );
1768     }
1769
1770     // marker size
1771     if ( myMarkerSize != dlg->getMarkerSize() ) {
1772       setMarkerSize( dlg->getMarkerSize(), false );
1773     }
1774     // background color
1775     if ( myBackground != dlg->getBackgroundColor() ) {
1776       setBackgroundColor( dlg->getBackgroundColor() );
1777     }
1778     // grid
1779     bool aXGridMajorEnabled, aXGridMinorEnabled, aYGridMajorEnabled, aYGridMinorEnabled,
1780          aY2GridMajorEnabled, aY2GridMinorEnabled;
1781     int  aXGridMaxMajor, aXGridMaxMinor, aYGridMaxMajor, aYGridMaxMinor,
1782          aY2GridMaxMajor, aY2GridMaxMinor;
1783     dlg->getMajorGrid( aXGridMajorEnabled, aXGridMaxMajor, aYGridMajorEnabled, aYGridMaxMajor,
1784                        aY2GridMajorEnabled, aY2GridMaxMajor);
1785     dlg->getMinorGrid( aXGridMinorEnabled, aXGridMaxMinor, aYGridMinorEnabled, aYGridMaxMinor,
1786                        aY2GridMinorEnabled, aY2GridMaxMinor);
1787     setXGrid( aXGridMajorEnabled, aXGridMaxMajor, aXGridMinorEnabled, aXGridMaxMinor, false );
1788     setYGrid( aYGridMajorEnabled, aYGridMaxMajor, aYGridMinorEnabled, aYGridMaxMinor,
1789               aY2GridMajorEnabled, aY2GridMaxMajor, aY2GridMinorEnabled, aY2GridMaxMinor, false );
1790     if ( myXMode != dlg->getXScaleMode() ) {
1791       setHorScaleMode( dlg->getXScaleMode() );
1792     }
1793     if ( myYMode != dlg->getYScaleMode() ) {
1794       setVerScaleMode( dlg->getYScaleMode() );
1795     }
1796     if ( myNormLMin != dlg->getLMinNormMode() ) {
1797       setNormLMinMode( dlg->getLMinNormMode() );
1798     }
1799     if ( myNormLMax != dlg->getLMaxNormMode() ) {
1800       setNormLMaxMode( dlg->getLMaxNormMode() );
1801     }
1802     if ( myNormRMin != dlg->getRMinNormMode() ) {
1803       setNormRMinMode( dlg->getRMinNormMode() );
1804     }
1805     if ( myNormRMax != dlg->getRMaxNormMode() ) {
1806       setNormRMaxMode( dlg->getRMaxNormMode() );
1807     }
1808
1809     myPlot->setProperty(PLOT2D_DEVIATION_COLOR,
1810                         dlg->getDeviationMarkerCl());
1811     myPlot->setProperty(PLOT2D_DEVIATION_LW,
1812                         dlg->getDeviationMarkerLw());
1813     myPlot->setProperty(PLOT2D_DEVIATION_TS,
1814                          dlg->getDeviationMarkerTs());
1815
1816
1817     // update view
1818     myPlot->replot();
1819     // update preferences
1820     if ( dlg->isSetAsDefault() )
1821       writePreferences();
1822   }
1823   delete dlg;
1824 }
1825
1826 #ifndef NO_ANALYTICAL_CURVES
1827 /*!
1828   "Analytical Curves" toolbar action slot
1829 */
1830 void Plot2d_ViewFrame::onAnalyticalCurve()
1831 {
1832 #ifndef DISABLE_PYCONSOLE
1833   Plot2d_AnalyticalCurveDlg dlg( this, this );
1834   dlg.exec();
1835   updateAnalyticalCurves();
1836 #endif
1837 }
1838
1839 void Plot2d_ViewFrame::addAnalyticalCurve( Plot2d_AnalyticalCurve* theCurve)
1840 {
1841 #ifndef DISABLE_PYCONSOLE
1842         myAnalyticalCurves.append(theCurve);
1843 #endif
1844 }
1845
1846 void Plot2d_ViewFrame::removeAnalyticalCurve( Plot2d_AnalyticalCurve* theCurve)
1847 {
1848 #ifndef DISABLE_PYCONSOLE
1849         theCurve->setAction(Plot2d_AnalyticalCurve::ActRemoveFromView);
1850 #endif
1851 }
1852
1853 /*
1854   Update Analytical curve
1855 */
1856 void Plot2d_ViewFrame::updateAnalyticalCurve(Plot2d_AnalyticalCurve* c, bool updateView)
1857 {
1858 #ifndef DISABLE_PYCONSOLE
1859   if(!c) return;
1860   QwtScaleDiv* div = myPlot->axisScaleDiv(QwtPlot::xBottom);
1861   c->setRangeBegin(div->lowerBound());
1862   c->setRangeEnd(div->upperBound());
1863   c->calculate();
1864   c->setMarkerSize(myMarkerSize);
1865   QwtPlotItem* item = c->plotItem();
1866
1867   switch( c->getAction() ) {
1868   case Plot2d_AnalyticalCurve::ActAddInView:
1869     if( c->isActive() ) {
1870       c->updatePlotItem();
1871       item->attach( myPlot );
1872       item->show();
1873     }
1874     c->setAction(Plot2d_AnalyticalCurve::ActNothing);
1875     break;
1876
1877   case Plot2d_AnalyticalCurve::ActUpdateInView:
1878     if(c->isActive()) {
1879       c->updatePlotItem();
1880       item->show();
1881     } else {
1882       item->hide();
1883       item->detach();
1884     }
1885
1886     c->setAction(Plot2d_AnalyticalCurve::ActNothing);
1887     break;
1888   case Plot2d_AnalyticalCurve::ActRemoveFromView:
1889     item->hide();
1890     item->detach();
1891     myAnalyticalCurves.removeAll(c);
1892     delete c;
1893     break;
1894   }
1895
1896   if(updateView)
1897     myPlot->replot();
1898 #endif
1899 }
1900
1901 /*
1902   Update Analytical curves
1903 */
1904 void Plot2d_ViewFrame::updateAnalyticalCurves()
1905 {
1906 #ifndef DISABLE_PYCONSOLE
1907   AnalyticalCurveList::iterator it = myAnalyticalCurves.begin();
1908   for( ; it != myAnalyticalCurves.end(); it++) {
1909     updateAnalyticalCurve(*it);
1910   }
1911   myPlot->replot();
1912 #endif
1913 }
1914
1915 /*!
1916   Return list of the alalytical curves.
1917 */
1918 AnalyticalCurveList Plot2d_ViewFrame::getAnalyticalCurves() const
1919 {
1920   return myAnalyticalCurves;
1921 }
1922
1923 /*!
1924   Get analytical curve by plot item.
1925 */
1926 Plot2d_AnalyticalCurve* Plot2d_ViewFrame::getAnalyticalCurve(QwtPlotItem * theItem) {
1927 #ifndef DISABLE_PYCONSOLE
1928   AnalyticalCurveList::iterator it = myAnalyticalCurves.begin();
1929   for( ; it != myAnalyticalCurves.end(); it++) {
1930     if((*it)->plotItem() == theItem);
1931                 return (*it);
1932   }
1933   return 0;
1934 #endif
1935 }
1936 #endif
1937
1938 /*!
1939   "Fit Data" command slot
1940 */
1941 void Plot2d_ViewFrame::onFitData()
1942 {
1943   Plot2d_FitDataDlg* dlg = new Plot2d_FitDataDlg( this, mySecondY );
1944   double xMin,xMax,yMin,yMax,y2Min,y2Max;
1945   getFitRanges(xMin,xMax,yMin,yMax,y2Min,y2Max);
1946
1947   dlg->setRange( xMin, xMax, yMin, yMax, y2Min, y2Max );
1948   if ( dlg->exec() == QDialog::Accepted ) {
1949     int mode = dlg->getRange( xMin, xMax, yMin, yMax, y2Min, y2Max );
1950     fitData(mode,xMin,xMax,yMin,yMax,y2Min,y2Max);
1951   }
1952   delete dlg;
1953 #ifndef NO_ANALYTICAL_CURVES
1954   updateAnalyticalCurves();
1955 #endif
1956 }
1957
1958 /*!
1959   Change background color
1960 */
1961 void Plot2d_ViewFrame::onChangeBackground()
1962 {
1963   QColor selColor = QColorDialog::getColor ( backgroundColor(), this );
1964   if ( selColor.isValid() ) {
1965     setBackgroundColor( selColor );
1966   }
1967 }
1968
1969 /*!
1970   Sets curve type
1971 */
1972 void Plot2d_ViewFrame::setCurveType( int curveType, bool update )
1973 {
1974   myCurveType = curveType;
1975   CurveDict aCurves = getCurves();
1976   CurveDict::iterator it = aCurves.begin();
1977   for ( ; it != aCurves.end(); it++ ) {
1978     QwtPlotCurve* crv = it.key();
1979     if ( crv )
1980       setCurveType( crv, myCurveType );
1981   }
1982   if ( update )
1983     myPlot->replot();
1984   emit vpCurveChanged();
1985 }
1986
1987 /*!
1988   Gets curve type
1989 */
1990 int Plot2d_ViewFrame::getCurveType() const
1991 {
1992   return myCurveType;
1993 }
1994
1995 /*!
1996   Sets curve title
1997   \param curveKey - curve id
1998   \param title - new title
1999 */
2000 void Plot2d_ViewFrame::setCurveTitle( Plot2d_Curve* curve, const QString& title )
2001 {
2002   setObjectTitle( curve, title );
2003 }
2004
2005 /*!
2006   Sets object title
2007   \param object - object id
2008   \param title - new title
2009 */
2010 void Plot2d_ViewFrame::setObjectTitle( Plot2d_Object* object, const QString& title )
2011 {
2012   if ( object && hasPlotObject( object ) )
2013     getPlotObject( object )->setTitle( title );
2014 }
2015
2016 /*!
2017   Shows/hides legend
2018 */
2019 void Plot2d_ViewFrame::showLegend( bool show, bool update )
2020 {
2021   myShowLegend = show;
2022   if ( myShowLegend ) {
2023     QwtLegend* legend = myPlot->legend();
2024     if ( !legend ) {
2025       legend = new QwtLegend( myPlot );
2026       legend->setFrameStyle( QFrame::Box | QFrame::Sunken );
2027     }
2028     legend->setItemMode( QwtLegend::ClickableItem );
2029     myPlot->insertLegend( legend );
2030     setLegendPos( myLegendPos );
2031     setLegendFont( myLegendFont );
2032     setLegendFontColor( myLegendColor );
2033   }
2034   else
2035     myPlot->insertLegend( 0 );
2036   if ( update )
2037     myPlot->replot();
2038 }
2039
2040 /*!
2041   Sets legend position : 0 - left, 1 - right, 2 - top, 3 - bottom
2042 */
2043 void Plot2d_ViewFrame::setLegendPos( int pos )
2044 {
2045   myLegendPos = pos;
2046   QwtLegend* legend = myPlot->legend();
2047   if ( legend ) {
2048     switch( pos ) {
2049     case 0:
2050       myPlot->insertLegend( legend, QwtPlot::LeftLegend );
2051       break;
2052     case 1:
2053       myPlot->insertLegend( legend, QwtPlot::RightLegend );
2054       break;
2055     case 2:
2056       myPlot->insertLegend( legend, QwtPlot::TopLegend );
2057       break;
2058     case 3:
2059       myPlot->insertLegend( legend, QwtPlot::BottomLegend );
2060       break;
2061     }
2062   }
2063 }
2064
2065 /*!
2066   Gets legend position : 0 - left, 1 - right, 2 - top, 3 - bottom
2067 */
2068 int Plot2d_ViewFrame::getLegendPos() const
2069 {
2070   return myLegendPos;
2071 }
2072
2073 /*!
2074   Sets legend font
2075 */
2076 void Plot2d_ViewFrame::setLegendFont( const QFont& fnt )
2077 {
2078   myLegendFont = fnt;
2079   QwtLegend* legend = myPlot->legend();
2080   if ( legend ) {
2081     legend->setFont(fnt);
2082   }
2083 }
2084
2085 /*!
2086   Gets legend font
2087 */
2088 QFont Plot2d_ViewFrame::getLegendFont() const
2089 {
2090   return myLegendFont;
2091 }
2092
2093 /*!
2094   Gets legend font color
2095 */
2096 QColor Plot2d_ViewFrame::getLegendFontColor() const
2097 {
2098   return myLegendColor;
2099 }
2100
2101 /*!
2102   Sets legend font color
2103 */
2104 void Plot2d_ViewFrame::setLegendFontColor( const QColor& col )
2105 {
2106   myLegendColor = col;
2107   QwtLegend* legend = myPlot->legend();
2108   if ( legend ) {
2109     QPalette pal = legend->palette();
2110     pal.setColor( QPalette::Text, col );
2111     legend->setPalette( pal );
2112   }
2113 }
2114
2115 /*!
2116   Sets new marker size
2117 */
2118 void Plot2d_ViewFrame::setMarkerSize( const int size, bool update )
2119 {
2120   if ( myMarkerSize != size )
2121   {
2122     myMarkerSize = size;
2123     CurveDict aCurves = getCurves();
2124     CurveDict::iterator it = aCurves.begin();
2125     for ( ; it != aCurves.end(); it++ ) {
2126       QwtPlotCurve* crv = it.key();
2127       if ( crv )
2128       {
2129         QwtSymbol aSymbol = crv->symbol();
2130         aSymbol.setSize( myMarkerSize, myMarkerSize );
2131         crv->setSymbol( aSymbol );
2132         if(it.value())
2133           it.value()->setMarkerSize( myMarkerSize );
2134       }
2135     }
2136     if ( update )
2137       myPlot->replot();
2138   }
2139 }
2140
2141 /*!
2142   Gets new marker size
2143 */
2144 int Plot2d_ViewFrame::getMarkerSize() const
2145 {
2146   return myMarkerSize;
2147 }
2148
2149 /*!
2150   Sets background color
2151 */
2152 void Plot2d_ViewFrame::setBackgroundColor( const QColor& color )
2153 {
2154   myBackground = color;
2155   myPlot->canvas()->setPalette( myBackground );
2156   myPlot->setPalette( myBackground );
2157   if ( myPlot->getLegend() ) {
2158     QPalette aPal = myPlot->getLegend()->palette();
2159     for ( int i = 0; i < QPalette::NColorGroups; i++ ) {
2160       aPal.setColor( QPalette::Base, myBackground );
2161       aPal.setColor( QPalette::Background, myBackground );
2162     }
2163     myPlot->getLegend()->setPalette( aPal );
2164     updateLegend();
2165   }
2166   Repaint();
2167 }
2168 /*!
2169   Gets background color
2170 */
2171 QColor Plot2d_ViewFrame::backgroundColor() const
2172 {
2173   return myBackground;
2174 }
2175 /*!
2176   Sets hor.axis grid parameters
2177 */
2178 void Plot2d_ViewFrame::setXGrid( bool xMajorEnabled, const int xMajorMax,
2179          bool xMinorEnabled, const int xMinorMax,
2180          bool update )
2181 {
2182   myXGridMajorEnabled = xMajorEnabled;
2183   myXGridMinorEnabled = xMinorEnabled;
2184   myXGridMaxMajor = xMajorMax;
2185   myXGridMaxMinor = xMinorMax;
2186
2187   myPlot->setAxisMaxMajor( QwtPlot::xBottom, myXGridMaxMajor );
2188   myPlot->setAxisMaxMinor( QwtPlot::xBottom, myXGridMaxMinor );
2189
2190   QwtPlotGrid* grid = myPlot->grid();
2191   if ( myPlot->axisScaleDiv( QwtPlot::xBottom ) )
2192     grid->setXDiv( *myPlot->axisScaleDiv( QwtPlot::xBottom ) );
2193   grid->enableX( myXGridMajorEnabled );
2194   grid->enableXMin( myXGridMinorEnabled );
2195
2196   if ( update )
2197     myPlot->replot();
2198 }
2199 /*!
2200   Sets ver.axis grid parameters
2201 */
2202 void Plot2d_ViewFrame::setYGrid( bool yMajorEnabled, const int yMajorMax,
2203                                  bool yMinorEnabled, const int yMinorMax,
2204                                  bool y2MajorEnabled, const int y2MajorMax,
2205                                  bool y2MinorEnabled, const int y2MinorMax,
2206                                  bool update )
2207 {
2208   myYGridMajorEnabled = yMajorEnabled;
2209   myYGridMinorEnabled = yMinorEnabled;
2210   myYGridMaxMajor = yMajorMax;
2211   myYGridMaxMinor = yMinorMax;
2212
2213   if (mySecondY) {
2214     myY2GridMajorEnabled = y2MajorEnabled;
2215     myY2GridMinorEnabled = y2MinorEnabled;
2216     myY2GridMaxMajor = y2MajorMax;
2217     myY2GridMaxMinor = y2MinorMax;
2218   }
2219   myPlot->setAxisMaxMajor( QwtPlot::yLeft, myYGridMaxMajor );
2220   myPlot->setAxisMaxMinor( QwtPlot::yLeft, myYGridMaxMinor );
2221
2222   if (mySecondY) {
2223     myPlot->setAxisMaxMajor( QwtPlot::yRight, myY2GridMaxMajor );
2224     myPlot->setAxisMaxMinor( QwtPlot::yRight, myY2GridMaxMinor );
2225   }
2226
2227   QwtPlotGrid* grid = myPlot->grid();
2228   if ( myPlot->axisScaleDiv( QwtPlot::yLeft ) )
2229     grid->setYDiv( *myPlot->axisScaleDiv( QwtPlot::yLeft ) );
2230
2231   if (mySecondY) {
2232     if (myYGridMajorEnabled) {
2233       grid->enableY( myYGridMajorEnabled );
2234       grid->enableYMin( myYGridMinorEnabled );
2235     }
2236     else if (myY2GridMajorEnabled) {
2237       if ( myPlot->axisScaleDiv( QwtPlot::yRight ) )
2238         grid->setYDiv( *myPlot->axisScaleDiv( QwtPlot::yRight ) );
2239       grid->enableY( myY2GridMajorEnabled );
2240       grid->enableYMin( myY2GridMinorEnabled );
2241     }
2242     else {
2243       grid->enableY( false );
2244       grid->enableYMin( false );
2245     }
2246   }
2247   else {
2248     grid->enableY( myYGridMajorEnabled );
2249     grid->enableYMin( myYGridMinorEnabled );
2250   }
2251   if ( update )
2252     myPlot->replot();
2253 }
2254
2255 /*!
2256   Sets title for some axis
2257 */
2258 void Plot2d_ViewFrame::setTitle( bool enabled, const QString& title,
2259                                  ObjectType type, bool update )
2260 {
2261   switch (type) {
2262     case MainTitle:
2263       myTitleEnabled = enabled;
2264       myTitle = title;
2265       myPlot->setTitle( myTitleEnabled ? myTitle : QString() );
2266       break;
2267     case XTitle:
2268       myXTitleEnabled = enabled;
2269       myXTitle = title;
2270       myPlot->setAxisTitle( QwtPlot::xBottom, myXTitleEnabled ? myXTitle : QString() );
2271       break;
2272     case YTitle:
2273       myYTitleEnabled = enabled;
2274       myYTitle = title;
2275       myPlot->setAxisTitle( QwtPlot::yLeft, myYTitleEnabled ? myYTitle : QString() );
2276       break;
2277     case Y2Title:
2278       myY2TitleEnabled = enabled;
2279       myY2Title = title;
2280       myPlot->setAxisTitle( QwtPlot::yRight, myY2TitleEnabled ? myY2Title : QString() );
2281       break;
2282     default:
2283       break;
2284   }
2285   if ( update )
2286     myPlot->replot();
2287 }
2288 /*!
2289   Sets title for some axis
2290 */
2291 QString Plot2d_ViewFrame::getTitle( ObjectType type ) const
2292 {
2293   QString title = "";
2294   switch (type) {
2295     case MainTitle:
2296       title = myTitle;   break;
2297     case XTitle:
2298       title = myXTitle;  break;
2299     case YTitle:
2300       title = myYTitle;  break;
2301     case Y2Title:
2302       title = myY2Title; break;
2303     default:
2304       break;
2305   }
2306   return title;
2307 }
2308 /*!
2309   Sets font for Plot2d object : title or axis
2310 */
2311 void Plot2d_ViewFrame::setFont( const QFont& font, ObjectType type, bool update)
2312 {
2313   switch (type) {
2314     case MainTitle:
2315       myPlot->title().setFont(font);
2316       break;
2317     case XTitle:
2318        myPlot->axisTitle(QwtPlot::xBottom).setFont(font); break;
2319     case YTitle:
2320       myPlot->axisTitle(QwtPlot::yLeft).setFont(font);    break;
2321     case Y2Title:
2322       myPlot->axisTitle(QwtPlot::yRight).setFont(font);   break;
2323     case XAxis:
2324       myPlot->setAxisFont(QwtPlot::xBottom, font);        break;
2325     case YAxis:
2326       myPlot->setAxisFont(QwtPlot::yLeft, font);          break;
2327     case Y2Axis:
2328       myPlot->setAxisFont(QwtPlot::yRight, font);         break;
2329   }
2330   if ( update )
2331     myPlot->replot();
2332 }
2333
2334 /*!
2335   Sets scale mode for horizontal axis: 0 - linear, 1 - logarithmic
2336 */
2337 void Plot2d_ViewFrame::setHorScaleMode( const int mode, bool update )
2338 {
2339   if ( myXMode == mode )
2340     return;
2341
2342   // san -- Protection against QwtCurve bug in Qwt 0.4.x:
2343   // it crashes if switched to X/Y logarithmic mode, when one or more points have
2344   // non-positive X/Y coordinate
2345   if ( mode && !isXLogEnabled() ){
2346 #ifndef NO_SUIT
2347     SUIT_MessageBox::warning(this, tr("WARNING"), tr("WRN_XLOG_NOT_ALLOWED"));
2348 #else
2349     QMessageBox::warning(this, tr("WARNING"), tr("WRN_XLOG_NOT_ALLOWED"));
2350 #endif
2351     return;
2352   }
2353
2354   myXMode = mode;
2355
2356   myPlot->setLogScale(QwtPlot::xBottom, myXMode != 0);
2357
2358   if ( update )
2359     fitAll();
2360   emit vpModeHorChanged();
2361 }
2362
2363 /*!
2364   Gets scale mode for horizontal axis: 0 - linear, 1 - logarithmic
2365 */
2366 int Plot2d_ViewFrame::getHorScaleMode() const
2367 {
2368   return myXMode;
2369 }
2370
2371 /*!
2372   Sets scale mode for vertical axis: 0 - linear, 1 - logarithmic
2373 */
2374 void Plot2d_ViewFrame::setVerScaleMode( const int mode, bool update )
2375 {
2376   if ( myYMode == mode )
2377     return;
2378
2379   // san -- Protection against QwtCurve bug in Qwt 0.4.x:
2380   // it crashes if switched to X/Y logarithmic mode, when one or more points have
2381   // non-positive X/Y coordinate
2382   if ( mode && !isYLogEnabled() ){
2383 #ifndef NO_SUIT
2384     SUIT_MessageBox::warning(this, tr("WARNING"), tr("WRN_YLOG_NOT_ALLOWED"));
2385 #else
2386     QMessageBox::warning(this, tr("WARNING"), tr("WRN_YLOG_NOT_ALLOWED"));
2387 #endif
2388     return;
2389   }
2390
2391   myYMode = mode;
2392   myPlot->setLogScale(QwtPlot::yLeft, myYMode != 0);
2393   if (mySecondY)
2394     myPlot->setLogScale( QwtPlot::yRight, myYMode != 0 );
2395
2396   if ( update )
2397     fitAll();
2398   emit vpModeVerChanged();
2399 }
2400
2401 /*!
2402   Gets scale mode for vertical axis: 0 - linear, 1 - logarithmic
2403 */
2404 int Plot2d_ViewFrame::getVerScaleMode() const
2405 {
2406   return myYMode;
2407 }
2408
2409 /*!
2410   Sets normalization mode to the global maximum by left Y axis
2411 */
2412 void Plot2d_ViewFrame::setNormLMaxMode( bool mode, bool update )
2413 {
2414   if ( myNormLMax == mode )
2415     return;
2416
2417   myNormLMax = mode;
2418   processFiltering(true);
2419   if ( update )
2420     fitAll();
2421   emit vpNormLModeChanged();
2422 }
2423
2424 /*!
2425   Gets normalization mode to the global maximum by left Y axis
2426 */
2427 bool Plot2d_ViewFrame::getNormLMaxMode() const
2428 {
2429   return myNormLMax;
2430 }
2431
2432 /*!
2433   Sets normalization mode to the global minimum by left Y axis
2434 */
2435 void Plot2d_ViewFrame::setNormLMinMode( bool mode, bool update )
2436 {
2437   if ( myNormLMin == mode )
2438     return;
2439
2440   myNormLMin = mode;
2441   processFiltering(true);
2442   if ( update )
2443     fitAll();
2444   emit vpNormLModeChanged();
2445 }
2446
2447 /*!
2448   Gets normalization mode to the global minimum by left Y axis
2449 */
2450 bool Plot2d_ViewFrame::getNormLMinMode() const
2451 {
2452   return myNormLMax;
2453 }
2454
2455 /*!
2456   Sets normalization mode to the global maximum by right Y axis
2457 */
2458 void Plot2d_ViewFrame::setNormRMaxMode( bool mode, bool update )
2459 {
2460   if ( myNormRMax == mode )
2461     return;
2462
2463   myNormRMax = mode;
2464   processFiltering(true);
2465   if ( update )
2466     fitAll();
2467   emit vpNormRModeChanged();
2468 }
2469
2470 /*!
2471   Gets normalization mode to the global maximum by right Y axis
2472 */
2473 bool Plot2d_ViewFrame::getNormRMaxMode() const
2474 {
2475   return myNormRMax;
2476 }
2477
2478 /*!
2479   Sets normalization mode to the global minimum by right Y axis
2480 */
2481 void Plot2d_ViewFrame::setNormRMinMode( bool mode, bool update )
2482 {
2483   if ( myNormRMin == mode )
2484     return;
2485
2486   myNormRMin = mode;
2487   processFiltering(true);
2488   if ( update )
2489     fitAll();
2490   emit vpNormRModeChanged();
2491 }
2492
2493 /*!
2494   Gets normalization mode to the global minimum by right Y axis
2495 */
2496 bool Plot2d_ViewFrame::getNormRMinMode() const
2497 {
2498   return myNormRMax;
2499 }
2500
2501 /*!
2502   Return, scale mode for horizontal axis
2503 */
2504 bool Plot2d_ViewFrame::isModeHorLinear()
2505 {
2506   return (myXMode == 0 ? true : false);
2507 }
2508
2509 /*!
2510   Return, scale mode for vertical axis
2511 */
2512 bool Plot2d_ViewFrame::isModeVerLinear()
2513 {
2514   return (myYMode == 0 ? true : false);
2515 }
2516
2517 /*!
2518   Return \c True if curves are normalize to the global maximum by left Y axis
2519 */
2520 bool Plot2d_ViewFrame::isNormLMaxMode()
2521 {
2522   return (myNormLMax ? true : false);
2523 }
2524
2525 /*!
2526   Return \c True if curves are normalize to the global minimum by left Y axis
2527 */
2528 bool Plot2d_ViewFrame::isNormLMinMode()
2529 {
2530   return (myNormLMin ? true : false);
2531 }
2532
2533 /*!
2534   Return \c True if curves are normalize to the global maximum by right Y axis
2535 */
2536 bool Plot2d_ViewFrame::isNormRMaxMode()
2537 {
2538   return (myNormRMax ? true : false);
2539 }
2540
2541 /*!
2542   Return \c True if curves are normalize to the global minimum by right Y axis
2543 */
2544 bool Plot2d_ViewFrame::isNormRMinMode()
2545 {
2546   return (myNormRMin ? true : false);
2547 }
2548
2549 /*!
2550   Return \c True if legend is shown
2551 */
2552 bool Plot2d_ViewFrame::isLegendShow() const
2553 {
2554   return myShowLegend;
2555 }
2556
2557 /*!
2558   Slot, called when user presses mouse button
2559 */
2560 void Plot2d_ViewFrame::plotMousePressed( const QMouseEvent& me )
2561 {
2562 #ifndef NO_SUIT
2563   Plot2d_ViewWindow* aParent = dynamic_cast<Plot2d_ViewWindow*>(parent());
2564   if (aParent)
2565      aParent->putInfo(getInfo(me.pos()));
2566 #endif
2567   if ( myOperation == NoOpId )
2568     myOperation = testOperation( me );
2569   if ( myOperation != NoOpId ) {
2570     myPnt = me.pos();
2571     if ( myOperation == GlPanId ) {
2572       myPlot->setAxisScale( QwtPlot::yLeft,
2573           myPlot->invTransform( QwtPlot::yLeft, myPnt.y() ) - myYDistance/2,
2574           myPlot->invTransform( QwtPlot::yLeft, myPnt.y() ) + myYDistance/2 );
2575       myPlot->setAxisScale( QwtPlot::xBottom,
2576           myPlot->invTransform( QwtPlot::xBottom, myPnt.x() ) - myXDistance/2,
2577           myPlot->invTransform( QwtPlot::xBottom, myPnt.x() ) + myXDistance/2 );
2578       if (mySecondY)
2579         myPlot->setAxisScale( QwtPlot::yRight,
2580           myPlot->invTransform( QwtPlot::yRight, myPnt.y() ) - myYDistance2/2,
2581           myPlot->invTransform( QwtPlot::yRight, myPnt.y() ) + myYDistance2/2 );
2582       myPlot->replot();
2583     }
2584   }
2585   else {
2586     int btn = me.button() | me.modifiers();
2587     if (btn == Qt::RightButton) {
2588       QMouseEvent* aEvent = new QMouseEvent(QEvent::MouseButtonPress,
2589                                             me.pos(), me.button(), me.buttons(), me.modifiers() );
2590       // QMouseEvent 'me' has the 'MouseButtonDblClick' type. In this case we create new event 'aEvent'.
2591       parent()->eventFilter(this, aEvent);
2592     }
2593   }
2594   setFocus();
2595 }
2596 /*!
2597   Slot, called when user moves mouse
2598 */
2599 bool Plot2d_ViewFrame::plotMouseMoved( const QMouseEvent& me )
2600 {
2601   int    dx = me.pos().x() - myPnt.x();
2602   int    dy = me.pos().y() - myPnt.y();
2603
2604   bool aRes = false;
2605   if ( myOperation != NoOpId) {
2606     if ( myOperation == ZoomId ) {
2607       this->incrementalZoom( dx, dy );
2608       myPnt = me.pos();
2609       aRes = true;
2610     }
2611     else if ( myOperation == PanId ) {
2612       this->incrementalPan( dx, dy );
2613       myPnt = me.pos();
2614       aRes = true;
2615     }
2616   }
2617   else {
2618 #ifndef NO_SUIT
2619      Plot2d_ViewWindow* aParent = dynamic_cast<Plot2d_ViewWindow*>(parent());
2620      if (aParent)
2621        aParent->putInfo(getInfo(me.pos()));
2622 #endif
2623   }
2624   return aRes;
2625 }
2626 /*!
2627   Slot, called when user releases mouse
2628 */
2629 void Plot2d_ViewFrame::plotMouseReleased( const QMouseEvent& me )
2630 {
2631   if ( myOperation == NoOpId && me.button() == Qt::RightButton && me.modifiers() != Qt::ControlModifier )
2632   {
2633     QContextMenuEvent aEvent( QContextMenuEvent::Mouse,
2634                               me.pos(), me.globalPos() );
2635     emit contextMenuRequested( &aEvent );
2636   }
2637   else {
2638 #ifndef NO_ANALYTICAL_CURVES
2639     updateAnalyticalCurves();
2640 #endif
2641   }
2642   myPlot->canvas()->setCursor( QCursor( Qt::CrossCursor ) );
2643   myPlot->defaultPicker();
2644
2645 #ifndef NO_SUIT
2646   Plot2d_ViewWindow* aParent = dynamic_cast<Plot2d_ViewWindow*>(parent());
2647    if (aParent)
2648      aParent->putInfo(tr("INF_READY"));
2649 #endif
2650   myOperation = NoOpId;
2651 }
2652 /*!
2653   Slot, called when user wheeling mouse
2654 */
2655 void Plot2d_ViewFrame::wheelEvent(QWheelEvent* event)
2656 {
2657   QwtPlotLayout* pl = myPlot->plotLayout();
2658
2659   // compute zooming factor
2660   double aDelta = event->delta();
2661   double aScale = (aDelta < 0) ? 100./(-aDelta) : aDelta/100.;
2662
2663   bool scaleXBottom = pl->scaleRect(QwtPlot::xBottom).contains( event->pos() ) ||
2664                       pl->canvasRect().contains( event->pos() );
2665   bool scaleYLeft   = pl->scaleRect(QwtPlot::yLeft).contains( event->pos() ) ||
2666                       pl->canvasRect().contains( event->pos() );
2667   bool scaleYRight  = mySecondY && ( pl->scaleRect(QwtPlot::yRight).contains( event->pos() ) ||
2668                                      pl->canvasRect().contains( event->pos() ) );
2669
2670   // scale x bottom axis
2671   if ( scaleXBottom ) {
2672     QwtScaleMap xMap = myPlot->canvasMap( QwtPlot::xBottom );
2673     if ( xMap.s2() - xMap.s1() > 1.0e-12 || aScale > 1 )
2674       myPlot->setAxisScale( QwtPlot::xBottom, xMap.s1(), xMap.s1() + aScale*(xMap.s2() - xMap.s1()) );
2675   }
2676
2677   // scale y left axis
2678   if ( scaleYLeft ) {
2679     QwtScaleMap yMap = myPlot->canvasMap( QwtPlot::yLeft );
2680     if ( yMap.s2() - yMap.s1() > 1.0e-12 || aScale > 1 )
2681       myPlot->setAxisScale( QwtPlot::yLeft, yMap.s1(), yMap.s1() + aScale*(yMap.s2() - yMap.s1()) );
2682   }
2683
2684   // scale y right axis (note: mySecondY value is checked above)
2685   if ( scaleYRight ) {
2686     QwtScaleMap yMap = myPlot->canvasMap( QwtPlot::yRight );
2687     if ( yMap.s2() - yMap.s1() > 10e-12 || aScale > 1 )
2688       myPlot->setAxisScale( QwtPlot::yRight, yMap.s1(), yMap.s1() + aScale*(yMap.s2() - yMap.s1()) );
2689   }
2690
2691   // redraw
2692   myPlot->replot();
2693   // update zoomer
2694   if ( myPlot->zoomer() ) myPlot->zoomer()->setZoomBase();
2695   // store current mouse position
2696   myPnt = event->pos();
2697 #ifndef NO_ANALYTICAL_CURVES
2698   // update analytical curves
2699   updateAnalyticalCurves();
2700 #endif
2701 }
2702
2703 /*!
2704   Returns qwt plot curve if it is existed in map of curves and 0 otherwise
2705 */
2706 QwtPlotCurve* Plot2d_ViewFrame::getPlotCurve( Plot2d_Curve* curve ) const
2707 {
2708   return dynamic_cast<QwtPlotCurve*>( getPlotObject( curve ) );
2709 }
2710 /*!
2711   Returns true if qwt plot curve is existed in map of curves and false otherwise
2712 */
2713 bool Plot2d_ViewFrame::hasPlotCurve( Plot2d_Curve* curve ) const
2714 {
2715   return hasPlotObject( curve );
2716 }
2717
2718 /*!
2719   Returns qwt plot curve if it is existed in map of curves and 0 otherwise
2720 */
2721 QwtPlotItem* Plot2d_ViewFrame::getPlotObject( Plot2d_Object* object ) const
2722 {
2723   ObjectDict::const_iterator it = myObjects.begin();
2724   for ( ; it != myObjects.end(); it++ ) {
2725     if ( it.value() == object )
2726       return it.key();
2727   }
2728   return 0;
2729 }
2730 /*!
2731   Returns true if qwt plot curve is existed in map of curves and false otherwise
2732 */
2733 bool Plot2d_ViewFrame::hasPlotObject( Plot2d_Object* object ) const
2734 {
2735   ObjectDict::const_iterator it = myObjects.begin();
2736   for ( ; it != myObjects.end(); it++ ) {
2737     if ( it.value() == object )
2738       return true;
2739   }
2740   return false;
2741 }
2742
2743 /*!
2744   Sets curve type
2745 */
2746 void Plot2d_ViewFrame::setCurveType( QwtPlotCurve* curve, int curveType )
2747 {
2748   if ( !curve )
2749     return;
2750   if ( myCurveType == 0 )
2751     curve->setStyle( QwtPlotCurve::Dots );//QwtCurve::NoCurve
2752   else if ( myCurveType == 1 ) {
2753     curve->setStyle( QwtPlotCurve::Lines );
2754     curve->setCurveAttribute( QwtPlotCurve::Fitted, false );
2755   }
2756   else if ( myCurveType == 2 ) {
2757     curve->setStyle( QwtPlotCurve::Lines );
2758     QwtSplineCurveFitter* fitter = new QwtSplineCurveFitter();
2759     fitter->setSplineSize( 250 );
2760     curve->setCurveAttribute( QwtPlotCurve::Fitted, true );
2761     curve->setCurveFitter( fitter );
2762   }
2763 }
2764
2765 /*!
2766   View operations : Pan view
2767 */
2768 void Plot2d_ViewFrame::onViewPan()
2769 {
2770   // reset the previous operation
2771   myPlot->defaultPicker();
2772
2773   QCursor panCursor (Qt::SizeAllCursor);
2774   myPlot->canvas()->setCursor( panCursor );
2775   myOperation = PanId;
2776 }
2777 /*!
2778   View operations : Zoom view
2779 */
2780 void Plot2d_ViewFrame::onViewZoom()
2781 {
2782   // reset the previous operation
2783   myPlot->defaultPicker();
2784
2785   QPixmap zoomPixmap (imageZoomCursor);
2786   QCursor zoomCursor (zoomPixmap);
2787   myPlot->canvas()->setCursor( zoomCursor );
2788   myOperation = ZoomId;
2789 }
2790 /*!
2791   View operations : Fit All
2792 */
2793 void Plot2d_ViewFrame::onViewFitAll()
2794 {
2795   fitAll();
2796
2797   // reset the previous operation
2798   myPlot->defaultPicker();
2799   myPlot->canvas()->setCursor( QCursor(Qt::CrossCursor) );
2800   myOperation = NoOpId;
2801 }
2802 /*!
2803   View operations : Fit Area
2804 */
2805 void Plot2d_ViewFrame::onViewFitArea()
2806 {
2807   myPlot->canvas()->setCursor( QCursor( Qt::PointingHandCursor ) );
2808   myOperation = FitAreaId;
2809   myPlot->setPickerMousePattern( Qt::LeftButton );
2810 }
2811 /*!
2812   View operations : Global panning
2813 */
2814 void Plot2d_ViewFrame::onViewGlobalPan()
2815 {
2816   // reset the previous operation
2817   myPlot->defaultPicker();
2818
2819   QPixmap globalPanPixmap (imageCrossCursor);
2820   QCursor glPanCursor (globalPanPixmap);
2821   myPlot->canvas()->setCursor( glPanCursor );
2822   myPlot->setLogScale(QwtPlot::xBottom, false);
2823   myPlot->setLogScale(QwtPlot::yLeft, false);
2824   if (mySecondY)
2825     myPlot->setLogScale(QwtPlot::yRight, false);
2826   myPlot->replot();
2827   QwtScaleMap xMap = myPlot->canvasMap( QwtPlot::xBottom );
2828   QwtScaleMap yMap = myPlot->canvasMap( QwtPlot::yLeft );
2829
2830   myXDistance = xMap.s2() - xMap.s1();
2831   myYDistance = yMap.s2() - yMap.s1();
2832
2833   if (mySecondY) {
2834     QwtScaleMap yMap2 = myPlot->canvasMap( QwtPlot::yRight );
2835     myYDistance2 = yMap2.s2() - yMap2.s1();
2836   }
2837   // don't make fit all
2838   // fitAll();
2839   myOperation = GlPanId;
2840 }
2841
2842 /*!
2843   Precaution for logarithmic X scale
2844 */
2845 bool Plot2d_ViewFrame::isXLogEnabled() const
2846 {
2847   bool allPositive = true;
2848   ObjectDict::const_iterator it = myObjects.begin();
2849   for ( ; allPositive && it != myObjects.end(); it++ )
2850     allPositive = ( it.value()->getMinX() > 0. );
2851   return allPositive;
2852 }
2853
2854 /*!
2855   Precaution for logarithmic Y scale
2856 */
2857 bool Plot2d_ViewFrame::isYLogEnabled() const
2858 {
2859   bool allPositive = true;
2860   ObjectDict::const_iterator it = myObjects.begin();
2861   for ( ; allPositive && it != myObjects.end(); it++ )
2862     allPositive = ( it.value()->getMinY() > 0. );
2863   return allPositive;
2864 }
2865
2866 /**
2867  *
2868  */
2869 void Plot2d_ViewFrame::setEnableAxis( QwtPlot::Axis theAxis, bool isEnable )
2870 {
2871   if ( myPlot->axisEnabled( theAxis ) == isEnable )
2872     return;
2873   myPlot->enableAxis( theAxis, isEnable );
2874   if ( theAxis == QwtPlot::yRight )
2875     mySecondY = isEnable;
2876 }
2877
2878 class Plot2d_QwtPlotZoomer : public QwtPlotZoomer
2879 {
2880 public:
2881   Plot2d_QwtPlotZoomer( int xAxis, int yAxis, QwtPlotCanvas* canvas )
2882   : QwtPlotZoomer( xAxis, yAxis, canvas )
2883   {
2884     qApp->installEventFilter( this );
2885     // now picker working after only a button pick.
2886     // after click on button FitArea in toolbar of the ViewFrame.
2887   };
2888   ~Plot2d_QwtPlotZoomer() {};
2889 };
2890
2891 /*!
2892   Constructor
2893 */
2894 Plot2d_Plot2d::Plot2d_Plot2d( QWidget* parent )
2895   : QwtPlot( parent ),
2896     myIsPolished( false ),
2897     myPicker( 0 )
2898 {
2899   // Create alternative scales
2900   setAxisScaleDraw( QwtPlot::yLeft,   new Plot2d_ScaleDraw() );
2901   setAxisScaleDraw( QwtPlot::xBottom, new Plot2d_ScaleDraw() );
2902   setAxisScaleDraw( QwtPlot::yRight,  new Plot2d_ScaleDraw() );
2903
2904   myPlotZoomer = new Plot2d_QwtPlotZoomer( QwtPlot::xBottom, QwtPlot::yLeft, canvas() );
2905   myPlotZoomer->setSelectionFlags( QwtPicker::DragSelection | QwtPicker::CornerToCorner );
2906   myPlotZoomer->setTrackerMode( QwtPicker::AlwaysOff );
2907   myPlotZoomer->setRubberBand( QwtPicker::RectRubberBand );
2908   myPlotZoomer->setRubberBandPen( QColor( Qt::green ) );
2909
2910   defaultPicker();
2911
2912   // auto scaling by default
2913   setAxisAutoScale( QwtPlot::yLeft );
2914   setAxisAutoScale( QwtPlot::yRight );
2915   setAxisAutoScale( QwtPlot::xBottom );
2916
2917   myScaleDraw = NULL;
2918 // grid
2919   myGrid = new QwtPlotGrid();
2920   QPen aMajPen = myGrid->majPen();
2921   aMajPen.setStyle( Qt::DashLine );
2922   myGrid->setPen( aMajPen );
2923
2924   myGrid->enableX( false );
2925   myGrid->enableXMin( false );
2926   myGrid->enableY( false );
2927   myGrid->enableYMin( false );
2928
2929   myGrid->attach( this );
2930
2931   setMouseTracking( false );
2932   canvas()->setMouseTracking( true );
2933
2934   myPlotZoomer->setEnabled( true );
2935   myPlotZoomer->setZoomBase();
2936
2937   setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
2938 }
2939
2940 Plot2d_Plot2d::~Plot2d_Plot2d()
2941 {
2942 }
2943
2944 /*!
2945   \set axis scale engine - linear or log10
2946 */
2947 void Plot2d_Plot2d::setLogScale( int axisId, bool log10 )
2948 {
2949   if ( log10 )
2950     setAxisScaleEngine( axisId, new QwtLog10ScaleEngine() );
2951   else
2952     setAxisScaleEngine( axisId, new QwtLinearScaleEngine() );
2953 }
2954
2955 /*!
2956   Recalculates and redraws Plot 2d view
2957 */
2958 void Plot2d_Plot2d::replot()
2959 {
2960   // the following code is intended to enable only axes
2961   // that are really used by displayed objects
2962   bool enableXBottom = false, enableXTop   = false;
2963   bool enableYLeft   = false, enableYRight = false;
2964   const QwtPlotItemList& items = itemList();
2965   QwtPlotItemIterator it;
2966   for ( it = items.begin(); it != items.end(); it++ ) {
2967     QwtPlotItem* item = *it;
2968     if ( item ) {
2969       enableXBottom |= item->xAxis() == QwtPlot::xBottom;
2970       enableXTop    |= item->xAxis() == QwtPlot::xTop;
2971       enableYLeft   |= item->yAxis() == QwtPlot::yLeft;
2972       enableYRight  |= item->yAxis() == QwtPlot::yRight;
2973     }
2974   }
2975   enableAxis( QwtPlot::xBottom, enableXBottom );
2976   enableAxis( QwtPlot::xTop,    enableXTop );
2977   enableAxis( QwtPlot::yLeft,   enableYLeft );
2978   enableAxis( QwtPlot::yRight,  enableYRight );
2979
2980   updateLayout();  // to fix bug(?) of Qwt - view is not updated when title is changed
2981   QwtPlot::replot();
2982 }
2983
2984 /*!
2985   Get legend
2986 */
2987 QwtLegend* Plot2d_Plot2d::getLegend()
2988 {
2989 #if QWT_VERSION < 0x040200
2990   return d_legend;
2991 #else
2992   return legend(); /* mpv: porting to the Qwt 4.2.0 */
2993 #endif
2994 }
2995
2996 /*!
2997   \return the recommended size for the widget
2998 */
2999 QSize Plot2d_Plot2d::sizeHint() const
3000 {
3001   return QwtPlot::minimumSizeHint();
3002 }
3003
3004 /*!
3005   return minimum size for qwt plot
3006 */
3007 QSize Plot2d_Plot2d::minimumSizeHint() const
3008 {
3009   return QSize( 0, 0 );
3010 //  QSize aSize = QwtPlot::minimumSizeHint();
3011 //  return QSize(aSize.width()*3/4, aSize.height());
3012 }
3013
3014 void Plot2d_Plot2d::defaultPicker()
3015 {
3016   myPlotZoomer->setMousePattern( QwtEventPattern::MouseSelect1,
3017                                  Qt::RightButton, Qt::ControlModifier ); // zooming button
3018   for ( int i = QwtEventPattern::MouseSelect2; i < QwtEventPattern::MouseSelect6; i++ )
3019     myPlotZoomer->setMousePattern( i, Qt::NoButton, Qt::NoButton );
3020 }
3021
3022 void Plot2d_Plot2d::setPickerMousePattern( int button, int state )
3023 {
3024   myPlotZoomer->setMousePattern( QwtEventPattern::MouseSelect1, button, state );
3025 }
3026
3027 /*!
3028  * Set the point picker associated with a graphic view
3029  */
3030 void Plot2d_Plot2d::setPicker( Plot2d_QwtPlotPicker *picker)
3031 {
3032   myPicker = picker;
3033 }
3034
3035 /*!
3036  * Create marker and tooltip associed with a point
3037  */
3038 QwtPlotMarker* Plot2d_Plot2d::createMarkerAndTooltip( QwtSymbol symbol,
3039                                             double    X,
3040                                             double    Y,
3041                                             QString & tooltip,
3042                                             Plot2d_QwtPlotPicker *picker)
3043 {
3044   QwtPlotMarker* aPlotMarker = new QwtPlotMarker();
3045
3046   aPlotMarker->setSymbol( symbol );  // symbol must have a color
3047   aPlotMarker->setLabelAlignment( Qt::AlignTop);
3048   aPlotMarker->setXValue(X);
3049   aPlotMarker->setYValue(Y);
3050   //
3051   aPlotMarker->attach(this);
3052
3053   // Associate a tooltip with the point's marker
3054   // PB: how to obtain a tooltip with a rectangular frame ?
3055   //QwtText tooltip ("X=" + QString::number(X) + " Y=" + QString::number(Y) );
3056
3057   QwtText text (tooltip);
3058   //QColor tooltipColor( 245, 222, 179);            // Wheat  -RGB (0 a 255)
3059   QColor tooltipColor( 253, 245, 230);            // OldLace
3060   text.setBackgroundBrush( QBrush(tooltipColor)); //, Qt::SolidPattern));
3061   //
3062   if ( picker ) {
3063     picker->pMarkers.append( aPlotMarker);
3064     picker->pMarkersToolTip[ aPlotMarker] = text;
3065   }
3066   return aPlotMarker;
3067 }
3068
3069 bool Plot2d_Plot2d::polished() const
3070 {
3071   return myIsPolished;
3072 }
3073
3074 QwtPlotGrid* Plot2d_Plot2d::grid() const
3075 {
3076   return myGrid;
3077 };
3078
3079 QwtPlotZoomer* Plot2d_Plot2d::zoomer() const
3080 {
3081   return myPlotZoomer;
3082 }
3083
3084 /*!
3085   Slot: checks the current labels format and change it if needed
3086 */
3087 void Plot2d_Plot2d::onScaleDivChanged()
3088 {
3089   QwtScaleWidget* aSW = 0;
3090   if ( ( aSW = dynamic_cast<QwtScaleWidget*>(sender()) ) ) {
3091     int axisId = -1;
3092     switch ( aSW->alignment() ) {
3093     case QwtScaleDraw::BottomScale:
3094       axisId = QwtPlot::xBottom;
3095       break;
3096     case QwtScaleDraw::LeftScale:
3097       axisId = QwtPlot::yLeft;
3098       break;
3099     case QwtScaleDraw::RightScale:
3100       axisId = QwtPlot::yRight;
3101       break;
3102     default:
3103       break;
3104     }
3105
3106     if ( axisId >= 0 ) {
3107       QwtScaleMap map = canvasMap(axisId);
3108       double aDist = fabs(map.s2()-map.s1()) / (axisMaxMajor(axisId)*axisMaxMinor(axisId));
3109
3110       QString aDistStr;
3111       aDistStr.sprintf("%e",aDist);
3112       int aPrecision = aDistStr.right(aDistStr.length()-aDistStr.indexOf('e')-2).toInt();
3113
3114       QwtScaleDraw* aQwtSD = axisScaleDraw(axisId);
3115       Plot2d_ScaleDraw* aPlot2dSD = dynamic_cast<Plot2d_ScaleDraw*>(aQwtSD);
3116       if ( ( !aPlot2dSD && aPrecision > 6 ) || ( aPlot2dSD && aPlot2dSD->precision() != aPrecision ) )
3117         setAxisScaleDraw( axisId, new Plot2d_ScaleDraw(*aQwtSD, 'f', aPrecision) );
3118     }
3119   }
3120 }
3121
3122 /*!
3123   Updates identifiers of Y axis type in the legend.
3124 */
3125 void Plot2d_Plot2d::updateYAxisIdentifiers()
3126 {
3127   bool enableYLeft = false, enableYRight = false;
3128   const QwtPlotItemList& items = itemList();
3129   QwtPlotItemIterator it;
3130   for ( it = items.begin(); it != items.end(); it++ ) {
3131     QwtPlotItem* item = *it;
3132     if ( item ) {
3133       enableYLeft  |= item->yAxis() == QwtPlot::yLeft;
3134       enableYRight |= item->yAxis() == QwtPlot::yRight;
3135     }
3136   }
3137
3138   // if several curves are attached to different axes
3139   // display corresponding identifiers in the legend,
3140   // otherwise hide them
3141   for ( it = items.begin(); it != items.end(); it++ ) {
3142     QwtPlotItem* item = *it;
3143     if ( Plot2d_QwtPlotCurve* aPCurve = dynamic_cast<Plot2d_QwtPlotCurve*>( item ) )
3144       aPCurve->setYAxisIdentifierEnabled( enableYLeft && enableYRight );
3145     if ( item && item->isVisible() && legend() )
3146       item->updateLegend( legend() );
3147   }
3148 }
3149
3150 /*!
3151   Sets the flag saying that QwtPlot geometry has been fully defined.
3152 */
3153 void Plot2d_Plot2d::polish()
3154 {
3155   QwtPlot::polish();
3156   myIsPolished = true;
3157 }
3158
3159 // Methods to manage axis graduations
3160
3161 /* Create definition and graduations of axes
3162  */
3163 void Plot2d_Plot2d::createAxisScaleDraw()
3164 {
3165   myScaleDraw = new Plot2d_AxisScaleDraw( this);
3166 }
3167
3168
3169 /* Stock X axis's ticks in the drawing zone
3170 */
3171 void Plot2d_Plot2d::applyTicks()
3172 {
3173   myScaleDraw->applyTicks();
3174 }
3175
3176
3177 /* Unactivate automatic ticks drawing (call to method Plot2d_AxisScaleDraw::draw() )
3178  * Parameters :
3179  * - number call to ticks drawing (for information) : numcall
3180  */
3181 void Plot2d_Plot2d::unactivAxisScaleDraw( int numcall)
3182 {
3183   // Memorize X axis (myScaleDraw already exists) in the drawing zone
3184   //setAxisScaleDraw( QwtPlot::xBottom, myScaleDraw);  // heritage of QwtPlot
3185
3186   myScaleDraw->unactivTicksDrawing( numcall);
3187 }
3188
3189
3190 /* Draw ticks and labels on X axis of the drawing zone
3191  * Draw systems' names under the X axis of the drawing zone
3192  * Draw vertical segments between X axis's intervals of the systems
3193  * Parameters :
3194  * - left and right margins for ticks : XLeftMargin, XRightMargin
3195  * - for each named system :
3196  *     positions and labels for ticks on X axis : devicesPosLabelTicks
3197  *
3198  * The true drawings will be realized by the method Plot2d_AxisScaleDraw::draw()
3199  * PB: who call il ?
3200  */
3201 void Plot2d_Plot2d::displayXTicksAndLabels(
3202                       double XLeftMargin, double XRightMargin,
3203                       const QList< QPair< QString, QMap<double, QString> > > & devicesPosLabelTicks)
3204                       //                    name        position  label
3205                       //                   system         tick    tick
3206 {
3207   //std::cout << "Plot2d_Plot2d::displayXTicksAndLabels() 1" << std::endl;
3208
3209   int nbDevices = devicesPosLabelTicks.size();
3210   //
3211   //std::cout << "  Nombre de systemes = " << nbDevices << std::endl;
3212   if (nbDevices == 0)  return;
3213
3214   // For drawing systems' names, their positions must be in the allTicks list
3215   // (cf class Plot2d_AxisScaleDraw)
3216
3217   // Liste of ticks' positions and systems' names
3218   QList<double> allTicks;
3219
3220   double devXmin, devXmax;  // X interval of a system
3221   double gapXmin, gapXmax;  // X interval between two systems
3222   double devLabPos;         // Label's position of a system
3223   double segmentPos;  // Position of the vertical segment between current system and the next
3224
3225   // 1)- Search for the system whose X interval is the most to the left
3226
3227   int ileftDev = 0;
3228   double XminMin = 1.e+12;
3229
3230   if (nbDevices > 1)
3231   {
3232       for (int idev=0; idev < nbDevices; idev++)
3233       {
3234           QPair< QString, QMap<double,QString> > paire = devicesPosLabelTicks.at(idev);
3235
3236           QString deviceLabel = paire.first;
3237
3238           // Ticks' map of the system
3239           QMap<double,QString> devPosLabelTicks = paire.second;
3240
3241           QList<double> posTicks = devPosLabelTicks.keys();
3242
3243           // List's items increasing sorting
3244           qSort( posTicks.begin(), posTicks.end() );  // iterators
3245
3246           // X interval for the system
3247           devXmin = posTicks.first();
3248           devXmax = posTicks.last();
3249
3250           if (devXmin < XminMin)
3251           {
3252               XminMin = devXmin;
3253               ileftDev = idev;
3254           }
3255       }
3256   }
3257
3258   // 2)- Ticks, systems' names, verticals segments
3259
3260   for (int idev=0; idev < nbDevices; idev++)
3261   {
3262       QPair< QString, QMap<double,QString> > paire = devicesPosLabelTicks.at(idev);
3263
3264       QString deviceLabel = paire.first;
3265
3266       std::string std_label = deviceLabel.toStdString();
3267       //const char *c_label = std_label.c_str();
3268       //std::cout << "  deviceLabel: |" << c_label << "|" << std::endl;
3269
3270       // Ticks' map of the system
3271       QMap<double,QString> devPosLabelTicks = paire.second;
3272
3273       int nbTicks = devPosLabelTicks.size();
3274
3275       QList<double> posTicks = devPosLabelTicks.keys();
3276
3277       // List's items increasing sorting
3278       qSort( posTicks.begin(), posTicks.end() );  // iterators
3279
3280       // X interval for the system
3281       devXmin = posTicks.first();
3282       devXmax = posTicks.last();
3283
3284       // Stock ticks' positions and labels on X axis
3285       double pos;
3286       QString label;
3287       //
3288       for (int itic=0; itic < nbTicks; itic++)
3289       {
3290           pos   = posTicks.at(itic);
3291           label = devPosLabelTicks[pos];
3292
3293           myScaleDraw->setLabelTick( pos, label, false);
3294
3295           std::string std_label = label.toStdString();
3296           //const char *c_label = std_label.c_str();
3297           //std::cout << "    tick " << itic << " : pos= " << pos << ", label= |" << c_label << "|" << std::endl;
3298       }
3299       allTicks.append( posTicks);
3300
3301       // Compute the position of the system's label
3302       if (idev == ileftDev)
3303       {
3304           devLabPos = devXmin + 0.25*(devXmax - devXmin);
3305       }
3306       else
3307       {
3308           devLabPos = devXmin + 0.50*(devXmax - devXmin);
3309       }
3310       allTicks.append( devLabPos);
3311
3312       // Stock position and name of the system under X axis
3313       myScaleDraw->setLabelTick( devLabPos, deviceLabel, true);
3314
3315       if (idev > 0)
3316       {
3317           // Create the vertical segment between the current system and the next
3318           gapXmax = devXmin;
3319           segmentPos = gapXmin + 0.5*(gapXmax - gapXmin);
3320
3321           createSeparationLine( segmentPos);
3322       }
3323       gapXmin = devXmax;
3324   }
3325
3326   // List's items increasing sorting
3327   qSort( allTicks.begin(), allTicks.end() );  // iterators
3328
3329   // Stock the interval of X's values
3330   double lowerBound = allTicks.first() - XLeftMargin;
3331   double upperBound = allTicks.last() + XRightMargin;
3332   myScaleDraw->setInterval( lowerBound, upperBound);
3333
3334   // For each system, stock the position of the X's ticks and those of the name
3335   myScaleDraw->setTicks( allTicks);  // do not draw the ticks
3336
3337   // Memorize the X axis in the drawing zone
3338   setAxisScaleDraw( QwtPlot::xBottom, myScaleDraw);  // heritage of QwtPlot
3339
3340   //std::cout << "Plot2d_Plot2d::displayXTicksAndLabels() 1" << std::endl;
3341 }
3342
3343
3344 /* Create vertical segment between two curves
3345  */
3346 void Plot2d_Plot2d::createSeparationLine( double Xpos)
3347 {
3348   QwtPlotMarker* aPlotMarker = new QwtPlotMarker();
3349
3350   aPlotMarker->setLineStyle( QwtPlotMarker::VLine);
3351   aPlotMarker->setXValue( Xpos);
3352   aPlotMarker->setLinePen( QPen(Qt::black));
3353   aPlotMarker->attach(this);  // Add to drawing zone
3354   // To deallocate in EraseAll()
3355   mySeparationLineList.append( aPlotMarker);
3356 }
3357
3358 void Plot2d_Plot2d::clearSeparationLineList()
3359 {
3360   mySeparationLineList.clear();
3361 }
3362
3363 /*!
3364   Creates presentation of object
3365   Default implementation is empty
3366 */
3367 Plot2d_Prs* Plot2d_ViewFrame::CreatePrs( const char* /*entry*/ )
3368 {
3369   return 0;
3370 }
3371
3372 /*!
3373   Copies preferences from other viewframe
3374   \param vf - other view frame
3375 */
3376 void Plot2d_ViewFrame::copyPreferences( Plot2d_ViewFrame* vf )
3377 {
3378   if( !vf )
3379     return;
3380
3381   myCurveType = vf->myCurveType;
3382   myShowLegend = vf->myShowLegend;
3383   myLegendPos = vf->myLegendPos;
3384   myMarkerSize = vf->myMarkerSize;
3385   myBackground = vf->myBackground;
3386   myTitle = vf->myTitle;
3387   myXTitle = vf->myXTitle;
3388   myYTitle = vf->myYTitle;
3389   myY2Title = vf->myY2Title;
3390   myTitleEnabled = vf->myTitleEnabled;
3391   myXTitleEnabled = vf->myXTitleEnabled;
3392   myYTitleEnabled = vf->myYTitleEnabled;
3393   myY2TitleEnabled = vf->myY2TitleEnabled;
3394   myXGridMajorEnabled = vf->myXGridMajorEnabled;
3395   myYGridMajorEnabled = vf->myYGridMajorEnabled;
3396   myY2GridMajorEnabled = vf->myY2GridMajorEnabled;
3397   myXGridMinorEnabled = vf->myXGridMinorEnabled;
3398   myYGridMinorEnabled = vf->myYGridMinorEnabled;
3399   myY2GridMinorEnabled = vf->myY2GridMinorEnabled;
3400   myXGridMaxMajor = vf->myXGridMaxMajor;
3401   myYGridMaxMajor = vf->myYGridMaxMajor;
3402   myY2GridMaxMajor = vf->myY2GridMaxMajor;
3403   myXGridMaxMinor = vf->myXGridMaxMinor;
3404   myYGridMaxMinor = vf->myYGridMaxMinor;
3405   myY2GridMaxMinor = vf->myY2GridMaxMinor;
3406   myXMode = vf->myXMode;
3407   myYMode = vf->myYMode;
3408   mySecondY = vf->mySecondY;
3409 }
3410
3411 /*!
3412   Updates titles according to curves
3413 */
3414 #define BRACKETIZE(x) QString( "[ " ) + x + QString( " ]" )
3415 void Plot2d_ViewFrame::updateTitles( const bool update )
3416 {
3417   ObjectDict::iterator it = myObjects.begin();
3418   QStringList aXTitles;
3419   QStringList aYTitles;
3420   QStringList aY2Titles;
3421   QStringList aXUnits;
3422   QStringList aYUnits;
3423   QStringList aY2Units;
3424   QStringList aTables;
3425   int i = 0;
3426
3427   Plot2d_Object* anObject;
3428   for ( ; it != myObjects.end(); it++ ) {
3429     // collect titles and units from all curves...
3430     anObject = it.value();
3431     QString xTitle = anObject->getHorTitle().trimmed();
3432     QString yTitle = anObject->getVerTitle().trimmed();
3433     QString xUnits = anObject->getHorUnits().trimmed();
3434     QString yUnits = anObject->getVerUnits().trimmed();
3435
3436     if ( anObject->getYAxis() == QwtPlot::yLeft ) {
3437       if ( !aYTitles.contains( yTitle ) )
3438         aYTitles.append( yTitle );
3439       if ( !aYUnits.contains( yUnits ) )
3440         aYUnits.append( yUnits );
3441     }
3442     else {
3443       if ( !aY2Titles.contains( yTitle ) )
3444         aY2Titles.append( yTitle );
3445       if ( !aY2Units.contains( yUnits ) )
3446         aY2Units.append( yUnits );
3447     }
3448     if ( !aXTitles.contains( xTitle ) )
3449       aXTitles.append( xTitle );
3450     if ( !aXUnits.contains( xUnits ) )
3451       aXUnits.append( xUnits );
3452
3453     QString aName = anObject->getTableTitle();
3454     if( !aName.isEmpty() && !aTables.contains( aName ) )
3455       aTables.append( aName );
3456     ++i;
3457   }
3458   // ... and update plot 2d view
3459   QString xUnits, yUnits, y2Units;
3460   if ( aXUnits.count() == 1 && !aXUnits[0].isEmpty() )
3461     xUnits = BRACKETIZE( aXUnits[0] );
3462   if ( aYUnits.count() == 1 && !aYUnits[0].isEmpty())
3463     yUnits = BRACKETIZE( aYUnits[0] );
3464   if ( aY2Units.count() == 1 && !aY2Units[0].isEmpty())
3465     y2Units = BRACKETIZE( aY2Units[0] );
3466   QString xTitle, yTitle, y2Title;
3467   if ( aXTitles.count() == 1 && aXUnits.count() == 1 )
3468     xTitle = aXTitles[0];
3469   if ( aYTitles.count() == 1 )
3470     yTitle = aYTitles[0];
3471   if ( mySecondY && aY2Titles.count() == 1 )
3472     y2Title = aY2Titles[0];
3473
3474   if ( !xTitle.isEmpty() && !xUnits.isEmpty() )
3475     xTitle += " ";
3476   if ( !yTitle.isEmpty() && !yUnits.isEmpty() )
3477     yTitle += " ";
3478   if ( !y2Title.isEmpty() && !y2Units.isEmpty() )
3479     y2Title += " ";
3480
3481   setTitle( myXTitleEnabled, xTitle + xUnits, XTitle, false );
3482   setTitle( myYTitleEnabled, yTitle + yUnits, YTitle, false );
3483   if ( mySecondY )
3484     setTitle( myY2TitleEnabled, y2Title + y2Units, Y2Title, false );
3485   if( myIsDefTitle )
3486     setTitle( true, aTables.join("; "), MainTitle, false );
3487
3488   // do update if necessary
3489   if ( update ) {
3490     myPlot->replot();
3491   }
3492 }
3493
3494 /*!
3495   Outputs content of viewframe to file
3496   \param file - file name
3497   \param format - file format
3498 */
3499 bool Plot2d_ViewFrame::print( const QString& file, const QString& format ) const
3500 {
3501 #ifdef WIN32
3502   return false;
3503
3504 #else
3505   bool res = false;
3506   if( myPlot )
3507   {
3508     QPaintDevice* pd = 0;
3509     if( format=="PS" || format=="EPS" || format == "PDF" )
3510     {
3511       QPrinter* pr = new QPrinter( QPrinter::HighResolution );
3512       if(format == "PDF")
3513           pr->setOutputFormat(QPrinter::PdfFormat);
3514       pr->setPageSize( QPrinter::A4 );
3515       pr->setOutputFileName( file );
3516       pr->setPrintProgram( "" );
3517       pd = pr;
3518     }
3519
3520     if( pd )
3521     {
3522       myPlot->print( *pd );
3523       res = true;
3524       delete pd;
3525     }
3526   }
3527   return res;
3528 #endif
3529 }
3530
3531 /**
3532  * Print Plot2d window
3533  */
3534 void Plot2d_ViewFrame::printPlot( QPainter* p, const QRect& rect,
3535                                   const QwtPlotPrintFilter& filter ) const
3536 {
3537   myPlot->print( p, rect, filter );
3538 }
3539
3540 /*!
3541   \return string with all visual parameters
3542 */
3543 QString Plot2d_ViewFrame::getVisualParameters()
3544 {
3545
3546   return getXmlVisualParameters();
3547
3548   /*
3549   RNV: Old case, now visual parameters stored in the XML format.
3550   //
3551   double xmin, xmax, ymin, ymax, y2min, y2max;
3552   getFitRanges( xmin, xmax, ymin, ymax, y2min, y2max );
3553   QString retStr;
3554   //Store font in the visual parameters string as:
3555   //
3556   // ...*FontFamily|FontSize|B|I|U|r:g:b*...
3557
3558   retStr.sprintf( "%d*%d*%d*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%s|%i|%i|%i|%i|%i:%i:%i",
3559                   myXMode, myYMode, mySecondY, xmin, xmax, ymin, ymax, y2min, y2max,
3560                   qPrintable(myLegendFont.family()), myLegendFont.pointSize(),myLegendFont.bold(),
3561                   myLegendFont.italic(), myLegendFont.underline(),myLegendColor.red(),
3562                   myLegendColor.green(), myLegendColor.blue());
3563
3564  //store all Analytical curves
3565   //store each curve in the following format
3566   // ...*Name|isActive|Expresion|NbInervals|isAutoAssign[|MarkerType|LineType|LineWidth|r:g:b]
3567   // parameters in the [ ] is optional in case if isAutoAssign == true
3568   AnalyticalCurveList::iterator it = myAnalyticalCurves.begin();
3569   Plot2d_AnalyticalCurve* c = 0;
3570   bool isAuto;
3571   for( ; it != myAnalyticalCurves.end(); it++) {
3572     c = (*it);
3573     if(!c) continue;
3574     QString curveString("");
3575     isAuto = c->isAutoAssign();
3576     curveString.sprintf("*%s|%i|%s|%i|%i",
3577                         qPrintable(c->getName()),
3578                         c->isActive(),
3579                         qPrintable(c->getExpression()),
3580                         c->getNbIntervals(),
3581                         isAuto);
3582
3583     retStr+=curveString;
3584     if(!isAuto) {
3585       QString optCurveString("");
3586       optCurveString.sprintf("|%i|%i|%i|%i:%i:%i",
3587                              (int)c->getMarker(),
3588                              (int)c->getLine(),
3589                              c->getLineWidth(),
3590                              c->getColor().red(),
3591                              c->getColor().green(),
3592                              c->getColor().blue());
3593       retStr+=optCurveString;
3594     }
3595   }
3596   retStr += QString( "*%1" ).arg( Qtx::colorToString( backgroundColor() ) );
3597   return retStr;
3598   */
3599 }
3600
3601 /*!
3602   Restores all visual parameters from string
3603 */
3604 void Plot2d_ViewFrame::setVisualParameters( const QString& parameters )
3605 {
3606   if(setXmlVisualParameters(parameters))
3607     return;
3608
3609   double xmin, xmax;
3610   QStringList paramsLst = parameters.split( '*' );
3611   if ( paramsLst.size() >= 9 ) {
3612     double ymin, ymax, y2min, y2max;
3613     myXMode = paramsLst[0].toInt();
3614     myYMode = paramsLst[1].toInt();
3615     mySecondY = (bool)paramsLst[2].toInt();
3616     xmin =  paramsLst[3].toDouble();
3617     xmax =  paramsLst[4].toDouble();
3618     ymin =  paramsLst[5].toDouble();
3619     ymax =  paramsLst[6].toDouble();
3620     y2min = paramsLst[7].toDouble();
3621     y2max = paramsLst[8].toDouble();
3622
3623     if (mySecondY)
3624       setTitle( myY2TitleEnabled, myY2Title, Y2Title, false );
3625     setHorScaleMode( myXMode, /*update=*/false );
3626     setVerScaleMode( myYMode, /*update=*/false );
3627
3628     if (mySecondY) {
3629       QwtScaleMap yMap2 = myPlot->canvasMap( QwtPlot::yRight );
3630       myYDistance2 = yMap2.s2() - yMap2.s1();
3631     }
3632
3633     fitData( 0, xmin, xmax, ymin, ymax, y2min, y2max );
3634     fitData( 0, xmin, xmax, ymin, ymax, y2min, y2max );
3635   }
3636
3637   //Restore legend font
3638   if(paramsLst.size() >= 10) {
3639     QStringList fontList = paramsLst[9].split( '|' );
3640     if(fontList.size() == 6) {
3641       myLegendFont = QFont(fontList[0]);
3642       myLegendFont.setPointSize(fontList[1].toInt());
3643       myLegendFont.setBold(fontList[2].toInt());
3644       myLegendFont.setItalic(fontList[3].toInt());
3645       myLegendFont.setUnderline(fontList[4].toInt());
3646       QStringList colorList = fontList[5].split(":");
3647       setLegendFont( myLegendFont );
3648
3649       if(colorList.size() == 3) {
3650               myLegendColor = QColor(colorList[0].toInt(),
3651                                                  colorList[1].toInt(),
3652                                                  colorList[2].toInt());
3653               setLegendFontColor( myLegendColor );
3654       }
3655     }
3656   }
3657
3658 #ifndef NO_ANALYTICAL_CURVES
3659   //Restore all Analytical curves
3660   int startCurveIndex = 10;
3661   if( paramsLst.size() >= startCurveIndex+1 ) {
3662     for( int i=startCurveIndex; i<paramsLst.size() ; i++ ) {
3663       QStringList curveLst = paramsLst[i].split("|");
3664       if( curveLst.size() == 5 || curveLst.size() == 9 ) {
3665         Plot2d_AnalyticalCurve* c = new Plot2d_AnalyticalCurve();
3666         c->setName(curveLst[0]);
3667         c->setActive(curveLst[1].toInt());
3668         c->setExpression(curveLst[2]);
3669         c->setNbIntervals(curveLst[3].toLong());
3670         c->setAutoAssign(curveLst[4].toInt());
3671         if( !c->isAutoAssign() ) {
3672           c->setMarker((Plot2d::MarkerType)curveLst[5].toInt());
3673           c->setLine((Plot2d::LineType)curveLst[6].toInt());
3674           c->setLineWidth(curveLst[7].toInt());
3675           QStringList colorList = curveLst[8].split(":");
3676           if( colorList.size() == 3 ) {
3677             c->setColor(QColor(colorList[0].toInt(),
3678                                colorList[1].toInt(),
3679                                colorList[2].toInt()));
3680           }
3681         } else {
3682           c->autoFill( myPlot );
3683         }
3684         addAnalyticalCurve(c);
3685         updateAnalyticalCurve(c);
3686       }
3687       else if( curveLst.size() == 1 ) {
3688         // background color can be set here
3689         QColor c;
3690         if ( Qtx::stringToColor( paramsLst[i], c ) )
3691           setBackgroundColor( c );
3692       }
3693     }
3694     myPlot->replot();
3695   }
3696 #endif
3697 }
3698
3699 /*!
3700   Store visual parameters in xml format.
3701 */
3702 QString Plot2d_ViewFrame::getXmlVisualParameters() {
3703   QString retStr;
3704   QXmlStreamWriter aWriter(&retStr);
3705   aWriter.setAutoFormatting(true);
3706
3707   //Ranges
3708   aWriter.writeStartDocument();
3709   aWriter.writeStartElement("ViewState");
3710   aWriter.writeStartElement("Range");
3711   double xmin, xmax, ymin, ymax, y2min, y2max;
3712   getFitRanges( xmin, xmax, ymin, ymax, y2min, y2max );
3713   aWriter.writeAttribute("Xmin", QString("").sprintf("%.12e",xmin));
3714   aWriter.writeAttribute("Xmax", QString("").sprintf("%.12e",xmax));
3715   aWriter.writeAttribute("Ymin", QString("").sprintf("%.12e",ymin));
3716   aWriter.writeAttribute("Ymax", QString("").sprintf("%.12e",ymax));
3717   aWriter.writeAttribute("Y2min", QString("").sprintf("%.12e",y2min));
3718   aWriter.writeAttribute("Y2max", QString("").sprintf("%.12e",y2max));
3719   aWriter.writeEndElement();
3720
3721   //Display mode
3722   aWriter.writeStartElement("DisplayMode");
3723   aWriter.writeAttribute("SecondAxis", QString("").sprintf("%d",mySecondY));
3724   aWriter.writeStartElement("ScaleMode");
3725   aWriter.writeAttribute("Xscale", QString("").sprintf("%d",myXMode));
3726   aWriter.writeAttribute("Yscale", QString("").sprintf("%d",myYMode));
3727   aWriter.writeEndElement();
3728   aWriter.writeStartElement("NormalizationMode");
3729   aWriter.writeAttribute("LeftMin", QString("").sprintf("%d",myNormLMin));
3730   aWriter.writeAttribute("LeftMax", QString("").sprintf("%d",myNormLMax));
3731   aWriter.writeAttribute("RightMin", QString("").sprintf("%d",myNormRMin));
3732   aWriter.writeAttribute("RightMax", QString("").sprintf("%d",myNormRMax));
3733   aWriter.writeEndElement();
3734   aWriter.writeEndElement();
3735
3736   //Legend
3737   aWriter.writeStartElement("Legend");
3738   aWriter.writeAttribute("Visibility", QString("").sprintf("%d", myShowLegend));
3739   aWriter.writeStartElement("LegendFont");
3740   aWriter.writeAttribute("Family", myLegendFont.family());
3741   aWriter.writeAttribute("Size", QString("").sprintf("%d",myLegendFont.pointSize()));
3742   aWriter.writeAttribute("Bold", QString("").sprintf("%d",myLegendFont.bold()));
3743   aWriter.writeAttribute("Italic", QString("").sprintf("%d",myLegendFont.italic()));
3744   aWriter.writeAttribute("Underline", QString("").sprintf("%d",myLegendFont.underline()));
3745   aWriter.writeAttribute("R", QString("").sprintf("%d",myLegendColor.red()));
3746   aWriter.writeAttribute("G", QString("").sprintf("%d",myLegendColor.green()));
3747   aWriter.writeAttribute("B", QString("").sprintf("%d",myLegendColor.blue()));
3748   aWriter.writeEndElement();
3749   aWriter.writeEndElement();
3750
3751 #ifndef NO_ANALYTICAL_CURVES
3752   //AnalyticalCurve
3753   aWriter.writeStartElement("AnalyticalCurves");
3754   AnalyticalCurveList::iterator it = myAnalyticalCurves.begin();
3755   Plot2d_AnalyticalCurve* c = 0;
3756   bool isAuto;
3757   int id = 1;
3758   for( ; it != myAnalyticalCurves.end(); it++) {
3759     c = (*it);
3760     if(!c) continue;
3761     aWriter.writeStartElement(QString("AnalyticalCurve_%1").arg(id));
3762     isAuto = c->isAutoAssign();
3763     aWriter.writeAttribute("Name",c->getName());
3764     aWriter.writeAttribute("IsActive", QString("").sprintf("%d",        c->isActive()));
3765                 aWriter.writeAttribute("Expression", c->getExpression());
3766     aWriter.writeAttribute("NbIntervals", QString("").sprintf("%d",     c->getNbIntervals()));
3767     aWriter.writeAttribute("isAuto", QString("").sprintf("%d",isAuto));
3768     if(!isAuto) {
3769       aWriter.writeAttribute("Marker", QString("").sprintf("%d",(int)c->getMarker()));
3770       aWriter.writeAttribute("Line", QString("").sprintf("%d",(int)c->getLine()));
3771       aWriter.writeAttribute("LineWidth", QString("").sprintf("%d",c->getLineWidth()));
3772       aWriter.writeAttribute("R", QString("").sprintf("%d",c->getColor().red()));
3773       aWriter.writeAttribute("G", QString("").sprintf("%d",c->getColor().green()));
3774       aWriter.writeAttribute("B", QString("").sprintf("%d",c->getColor().blue()));
3775     }
3776     aWriter.writeEndElement();
3777     id++;
3778   }
3779   aWriter.writeEndElement(); //AnalyticalCurve
3780 #endif
3781
3782   //Background
3783   aWriter.writeStartElement(QString("Background"));
3784   aWriter.writeStartElement(QString("BackgroundColor"));
3785   aWriter.writeAttribute("R", QString("").sprintf("%d",backgroundColor().red()));
3786   aWriter.writeAttribute("G", QString("").sprintf("%d",backgroundColor().green()));
3787   aWriter.writeAttribute("B", QString("").sprintf("%d",backgroundColor().blue()));
3788   aWriter.writeEndElement();
3789   aWriter.writeEndElement();
3790
3791
3792   aWriter.writeEndDocument();
3793   return retStr;
3794 }
3795 /*!
3796   Restore visual parameters from xml format.
3797 */
3798 bool Plot2d_ViewFrame::setXmlVisualParameters(const QString& parameters) {
3799   QXmlStreamReader aReader(parameters);
3800   double xmin, xmax, ymin, ymax, y2min, y2max;
3801   bool leftMin,leftMax,rightMin,rightMax;
3802   leftMin = leftMax = rightMin = rightMax = false;
3803   while(!aReader.atEnd()) {
3804       aReader.readNext();
3805       if (aReader.isStartElement()) {
3806       QXmlStreamAttributes aAttr = aReader.attributes();
3807         if(aReader.name() == "Range") {
3808           xmin = aAttr.value("Xmin").toString().toDouble();
3809           xmax = aAttr.value("Xmax").toString().toDouble();
3810           ymin = aAttr.value("Ymin").toString().toDouble();
3811           ymax = aAttr.value("Ymax").toString().toDouble();
3812           y2min = aAttr.value("Y2min").toString().toDouble();
3813           y2max = aAttr.value("Y2max").toString().toDouble();
3814         } else if(aReader.name() == "DisplayMode") {
3815           mySecondY = aAttr.value("Y2max").toString().toDouble();
3816         } else if(aReader.name() == "ScaleMode") {
3817            myXMode = aAttr.value("Xscale").toString().toInt();
3818            myYMode = aAttr.value("Yscale").toString().toInt();
3819         } else if(aReader.name() == "NormalizationMode") {
3820             leftMin = (bool)aAttr.value("LeftMin").toString().toInt();
3821             leftMax = (bool)aAttr.value("LeftMax").toString().toInt();
3822             rightMin = (bool)aAttr.value("RightMin").toString().toInt();
3823             rightMax = (bool)aAttr.value("RightMax").toString().toInt();
3824         } else if(aReader.name() == "Legend") {
3825           myShowLegend = (bool)aAttr.value("Visibility").toString().toInt();
3826         } else if (aReader.name() == "LegendFont") {
3827             myLegendFont = QFont(aAttr.value("Family").toString());
3828             myLegendFont.setPointSize(aAttr.value("Size").toString().toInt());
3829             myLegendFont.setBold((bool)aAttr.value("Bold").toString().toInt());
3830             myLegendFont.setItalic((bool)aAttr.value("Italic").toString().toInt());
3831             myLegendFont.setUnderline((bool)aAttr.value("Underline").toString().toInt());
3832               myLegendColor = QColor(aAttr.value("R").toString().toInt(),
3833                                                      aAttr.value("G").toString().toInt(),
3834                                                      aAttr.value("B").toString().toInt());
3835                   setLegendFontColor( myLegendColor );
3836             setLegendFont(myLegendFont);
3837         } else if(aReader.name().toString().indexOf("AnalyticalCurve_") >= 0) {
3838 #ifndef NO_ANALYTICAL_CURVES
3839             Plot2d_AnalyticalCurve* c = new Plot2d_AnalyticalCurve();
3840                   c->setName(aAttr.value("Name").toString());
3841                   c->setActive((bool)aAttr.value("IsActive").toString().toInt());
3842                   c->setExpression(aAttr.value("Expression").toString());
3843                   c->setNbIntervals(aAttr.value("NbIntervals").toString().toLong());
3844                   c->setAutoAssign((bool)aAttr.value("isAuto").toString().toInt());
3845                   if( !c->isAutoAssign() ) {
3846                     c->setMarker((Plot2d::MarkerType)aAttr.value("Marker").toString().toInt());
3847                     c->setLine((Plot2d::LineType)aAttr.value("Line").toString().toInt());
3848                     c->setLineWidth(aAttr.value("LineWidth").toString().toInt());
3849                     c->setColor(QColor(aAttr.value("R").toString().toInt(),
3850                                                    aAttr.value("G").toString().toInt(),
3851                                                    aAttr.value("B").toString().toInt()));
3852             } else {
3853                     c->autoFill( myPlot );
3854                   }
3855                   addAnalyticalCurve(c);
3856                   updateAnalyticalCurve(c);
3857 #endif
3858         } else if(aReader.name().toString() == "BackgroundColor") {
3859           setBackgroundColor(QColor(aAttr.value("R").toString().toInt(),
3860                                                       aAttr.value("G").toString().toInt(),
3861                                                       aAttr.value("B").toString().toInt()));
3862         }
3863       }
3864   }
3865
3866   if(aReader.hasError())
3867     return false;
3868
3869   if (mySecondY)
3870     setTitle( myY2TitleEnabled, myY2Title, Y2Title, false );
3871   setHorScaleMode( myXMode, /*update=*/false );
3872   setVerScaleMode( myYMode, /*update=*/false );
3873   if (mySecondY) {
3874     QwtScaleMap yMap2 = myPlot->canvasMap( QwtPlot::yRight );
3875     myYDistance2 = yMap2.s2() - yMap2.s1();
3876   }
3877   setNormLMinMode(leftMin);
3878   setNormLMaxMode(leftMax);
3879   setNormRMinMode(rightMin);
3880   setNormRMaxMode(rightMax);
3881
3882   showLegend( myShowLegend, false );
3883
3884   fitData( 0, xmin, xmax, ymin, ymax, y2min, y2max );
3885   return true;
3886 }
3887
3888 /*!
3889   Incremental zooming operation
3890 */
3891 void Plot2d_ViewFrame::incrementalPan( const int incrX, const int incrY ) {
3892   QwtScaleMap xMap = myPlot->canvasMap( QwtPlot::xBottom );
3893   QwtScaleMap yMap = myPlot->canvasMap( QwtPlot::yLeft );
3894
3895   myPlot->setAxisScale( QwtPlot::yLeft,
3896                         myPlot->invTransform( QwtPlot::yLeft, yMap.transform( yMap.s1() )-incrY ),
3897                         myPlot->invTransform( QwtPlot::yLeft, yMap.transform( yMap.s2() )-incrY ) );
3898   myPlot->setAxisScale( QwtPlot::xBottom,
3899                         myPlot->invTransform( QwtPlot::xBottom, xMap.transform( xMap.s1() )-incrX ),
3900                         myPlot->invTransform( QwtPlot::xBottom, xMap.transform( xMap.s2() )-incrX ) );
3901   if (mySecondY) {
3902     QwtScaleMap y2Map = myPlot->canvasMap( QwtPlot::yRight );
3903     myPlot->setAxisScale( QwtPlot::yRight,
3904                           myPlot->invTransform( QwtPlot::yRight, y2Map.transform( y2Map.s1() )-incrY ),
3905                           myPlot->invTransform( QwtPlot::yRight, y2Map.transform( y2Map.s2() )-incrY ) );
3906   }
3907   myPlot->replot();
3908 }
3909
3910 /*!
3911   Incremental panning operation
3912 */
3913 void Plot2d_ViewFrame::incrementalZoom( const int incrX, const int incrY ) {
3914   QwtScaleMap xMap = myPlot->canvasMap( QwtPlot::xBottom );
3915   QwtScaleMap yMap = myPlot->canvasMap( QwtPlot::yLeft );
3916
3917   myPlot->setAxisScale( QwtPlot::yLeft, yMap.s1(),
3918                         myPlot->invTransform( QwtPlot::yLeft, yMap.transform( yMap.s2() ) + incrY ) );
3919   myPlot->setAxisScale( QwtPlot::xBottom, xMap.s1(),
3920                         myPlot->invTransform( QwtPlot::xBottom, xMap.transform( xMap.s2() ) - incrX ) );
3921   if (mySecondY) {
3922     QwtScaleMap y2Map = myPlot->canvasMap( QwtPlot::yRight );
3923     myPlot->setAxisScale( QwtPlot::yRight, y2Map.s1(),
3924                           myPlot->invTransform( QwtPlot::yRight, y2Map.transform( y2Map.s2() ) + incrY ) );
3925   }
3926   myPlot->replot();
3927 }
3928
3929 /*
3930   Update plot item
3931 */
3932 void Plot2d_ViewFrame::updatePlotItem(Plot2d_Object* theObject, QwtPlotItem* theItem) {
3933   theObject->updatePlotItem( theItem );
3934   Plot2d_Curve* c = dynamic_cast<Plot2d_Curve*>(theObject);
3935   QwtPlotCurve* cu = dynamic_cast<QwtPlotCurve*>(theItem);
3936   Plot2d_NormalizeAlgorithm* aNormAlgo;
3937   if(c && cu) {
3938     if(c->getYAxis() == QwtPlot::yRight)
3939       aNormAlgo = myRNormAlgo;
3940     else
3941       aNormAlgo = myLNormAlgo;
3942     if(aNormAlgo->getNormalizationMode() != Plot2d_NormalizeAlgorithm::NormalizeNone) {
3943       AlgoPlot2dOutputData aResultData =  aNormAlgo->getOutput();
3944       AlgoPlot2dOutputData::iterator itTmp = aResultData.find(theObject);
3945       double *xNew,*yNew;
3946       int size = itTmp.value().size();
3947       xNew = new double[size];
3948       yNew = new double[size];
3949       int j = 0;
3950       for (; j < size; ++j) {
3951         xNew[j] = itTmp.value().at(j).first;
3952         yNew[j] = itTmp.value().at(j).second;
3953       }
3954       cu->setData(xNew, yNew,j);
3955       delete [] xNew;
3956       delete [] yNew;
3957       if(aNormAlgo->getNormalizationMode() != Plot2d_NormalizeAlgorithm::NormalizeNone) {
3958         QString name = c->getName().isEmpty() ? c->getVerTitle() : c->getName();
3959         name = name + QString("(B=%1, K=%2)");
3960         name = name.arg(aNormAlgo->getBkoef(c)).arg(aNormAlgo->getKkoef(c));
3961         cu->setTitle(name);
3962       }
3963     }
3964   }
3965 }
3966
3967 /**
3968  *
3969  */
3970 QwtPlotCanvas* Plot2d_ViewFrame::getPlotCanvas() const
3971 {
3972   return myPlot ? myPlot->canvas() : 0;
3973 }
3974
3975 /*!
3976   return closest curve if it exist, else 0
3977 */
3978 Plot2d_Curve* Plot2d_ViewFrame::getClosestCurve( QPoint p, double& distance, int& index ) const
3979 {
3980   CurveDict aCurves = getCurves();
3981   CurveDict::iterator it = aCurves.begin();
3982   Plot2d_Curve* pCurve = 0;
3983   distance = -1.;
3984   for ( ; it != aCurves.end(); it++ ) {
3985     QwtPlotCurve* aCurve = it.key();
3986     if ( !aCurve )
3987       continue;
3988     double d;
3989     int i = aCurve->closestPoint( p, &d );
3990     if ( i > -1 && ( distance < 0 || d < distance ) ) {
3991       pCurve = it.value();
3992       distance = d;
3993       index = i;
3994     }
3995   }
3996   return pCurve;
3997 }
3998
3999 #ifndef NO_ANALYTICAL_CURVES
4000 /*!
4001  \brief  Deselect all analytical curves.
4002 */
4003 void Plot2d_ViewFrame::deselectAnalyticalCurves() {
4004   foreach(Plot2d_AnalyticalCurve* c, myAnalyticalCurves) {
4005    c->setSelected(false);
4006   }
4007 }
4008 #endif
4009
4010 /*!
4011  \brief  Deselect all objects, except analytical curves.
4012 */
4013 void Plot2d_ViewFrame::deselectObjects() {
4014   ObjectDict::const_iterator it = myObjects.begin(), aLast = myObjects.end();
4015   for ( ; it != aLast; it++ ) {
4016           it.value()->setSelected(false);
4017    }
4018 }
4019
4020 #define INCREMENT_FOR_OP 10
4021
4022 /*!
4023   Performs incremental panning to the left
4024 */
4025 void Plot2d_ViewFrame::onPanLeft()
4026 {
4027   this->incrementalPan( -INCREMENT_FOR_OP, 0 );
4028 #ifndef NO_ANALYTICAL_CURVES
4029   updateAnalyticalCurves();
4030 #endif
4031 }
4032
4033 /*!
4034   Performs incremental panning to the right
4035 */
4036 void Plot2d_ViewFrame::onPanRight()
4037 {
4038   this->incrementalPan( INCREMENT_FOR_OP, 0 );
4039 #ifndef NO_ANALYTICAL_CURVES
4040   updateAnalyticalCurves();
4041 #endif
4042 }
4043
4044 /*!
4045   Performs incremental panning to the top
4046 */
4047 void Plot2d_ViewFrame::onPanUp()
4048 {
4049   this->incrementalPan( 0, -INCREMENT_FOR_OP );
4050 #ifndef NO_ANALYTICAL_CURVES
4051   updateAnalyticalCurves();
4052 #endif
4053 }
4054
4055 /*!
4056   Performs incremental panning to the bottom
4057 */
4058 void Plot2d_ViewFrame::onPanDown()
4059 {
4060   this->incrementalPan( 0, INCREMENT_FOR_OP );
4061 #ifndef NO_ANALYTICAL_CURVES
4062   updateAnalyticalCurves();
4063 #endif
4064 }
4065
4066 /*!
4067   Performs incremental zooming in
4068 */
4069 void Plot2d_ViewFrame::onZoomIn()
4070 {
4071   this->incrementalZoom( INCREMENT_FOR_OP, INCREMENT_FOR_OP );
4072 #ifndef NO_ANALYTICAL_CURVES
4073   updateAnalyticalCurves();
4074 #endif
4075 }
4076
4077 /*!
4078   Performs incremental zooming out
4079 */
4080 void Plot2d_ViewFrame::onZoomOut()
4081 {
4082   this->incrementalZoom( -INCREMENT_FOR_OP, -INCREMENT_FOR_OP );
4083 #ifndef NO_ANALYTICAL_CURVES
4084   updateAnalyticalCurves();
4085 #endif
4086 }
4087
4088 /*!
4089   Schedules a FitAll operation by putting it to the application's
4090   event queue. This ensures that other important events (show, resize, etc.)
4091   are processed first.
4092 */
4093 void Plot2d_ViewFrame::customEvent( QEvent* ce )
4094 {
4095   if ( ce->type() == FITALL_EVENT )
4096     fitAll();
4097 }
4098
4099
4100 /*!
4101  * Return Plot2d_Object by the QwtPlotItem
4102  *
4103 */
4104 Plot2d_Object* Plot2d_ViewFrame::getPlotObject( QwtPlotItem* plotItem ) const {
4105
4106   ObjectDict::const_iterator it = myObjects.begin();
4107   for( ; it != myObjects.end(); ++it ) {
4108     if ( it.key() == plotItem ) {
4109       return it.value();
4110     }
4111   }
4112   return 0;
4113 }
4114
4115 Plot2d_ScaleDraw::Plot2d_ScaleDraw( char f, int prec )
4116   : QwtScaleDraw(),
4117     myFormat(f),
4118     myPrecision(prec)
4119 {
4120   invalidateCache();
4121 }
4122
4123 Plot2d_ScaleDraw::Plot2d_ScaleDraw( const QwtScaleDraw& scaleDraw, char f, int prec )
4124   : QwtScaleDraw(scaleDraw),
4125     myFormat(f),
4126     myPrecision(prec)
4127 {
4128   invalidateCache();
4129 }
4130
4131 QwtText Plot2d_ScaleDraw::label( double value ) const
4132 {
4133   QwtScaleMap m = map();
4134   QString str1 = QwtScaleDraw::label( m.s1() ).text();
4135   QString str2 = QwtScaleDraw::label( m.s2() ).text();
4136   if ( str1 == str2 ) {
4137     double aDist = fabs(map().s2()-map().s1())/5;
4138     int precision = 0;
4139     while (aDist < 1 ) {
4140       precision++;
4141       aDist *= 10.;
4142     }
4143     if ( precision > 0 && value > 0 )
4144       return QLocale::system().toString( value,'f', precision );
4145   }
4146
4147   return QwtScaleDraw::label( value );
4148 }
4149
4150 Plot2d_YScaleDraw::Plot2d_YScaleDraw()
4151   : QwtScaleDraw()
4152 {
4153 }
4154
4155 QwtText Plot2d_YScaleDraw::label( double value ) const
4156 {
4157   // Axis labels format
4158   QString strD = QString( "%1").arg( value, 10, 'e', 3); // format 10.3e
4159
4160   return QwtText( strD);
4161 }
4162
4163 /* Definition of X axis graduations
4164  */
4165 const QString Plot2d_AxisScaleDraw::DEVICE_FONT = QString("Times");
4166 const int     Plot2d_AxisScaleDraw::DEVICE_FONT_SIZE = 12;
4167 const int     Plot2d_AxisScaleDraw::DEVICE_BY = 40;
4168
4169 Plot2d_AxisScaleDraw::Plot2d_AxisScaleDraw( Plot2d_Plot2d* plot)
4170 : myPlot(plot)
4171 {
4172   myLowerBound = -1;
4173   myUpperBound = -1;
4174   setLabelAlignment(Qt::AlignRight);
4175   setLabelRotation(45.);
4176
4177   applyTicks();
4178
4179   myActivTicksDrawing   = true;
4180   myNumTicksDrawingCall = 1;
4181 }
4182
4183
4184 Plot2d_AxisScaleDraw::~Plot2d_AxisScaleDraw()
4185 {
4186 }
4187
4188
4189 /* Unactivate automatic ticks drawing
4190  */
4191 void Plot2d_AxisScaleDraw::unactivTicksDrawing( int numcall)
4192 {
4193   myActivTicksDrawing   = false;
4194   myNumTicksDrawingCall = numcall;
4195 }
4196
4197
4198 /* Draw X ticks and labels.
4199  * Draw systems names under X axis.
4200  * Overload the same name QwtScaleDraw method.
4201  * (PB: who call automaticaly this method)
4202  */
4203 void Plot2d_AxisScaleDraw::draw( QPainter* painter, const QPalette & palette) const
4204 {
4205   //std::cout << "Plot2d_AxisScaleDraw::draw() : activ= " << myActivTicksDrawing
4206   //                           << "  numcall= " << myNumTicksDrawingCall << std::endl;
4207
4208   if (!myActivTicksDrawing)  return;
4209
4210   //std::cout << "Plot2d_AxisScaleDraw::draw()" << std::endl;
4211
4212   QList<double> major_ticks  = scaleDiv().ticks(QwtScaleDiv::MajorTick);
4213   QList<double> medium_ticks = scaleDiv().ticks(QwtScaleDiv::MediumTick);
4214   QList<double> minor_ticks  = scaleDiv().ticks(QwtScaleDiv::MinorTick);
4215
4216   medium_ticks.clear();
4217   minor_ticks.clear();
4218   major_ticks.clear();
4219
4220   major_ticks.append( myTicks);
4221   myPlot->axisScaleDiv(QwtPlot::xBottom)->setTicks(QwtScaleDiv::MajorTick,  major_ticks);
4222   myPlot->axisScaleDiv(QwtPlot::xBottom)->setTicks(QwtScaleDiv::MediumTick, medium_ticks);
4223   myPlot->axisScaleDiv(QwtPlot::xBottom)->setTicks(QwtScaleDiv::MinorTick,  minor_ticks);
4224   QwtScaleDraw *scale = myPlot->axisScaleDraw(QwtPlot::xBottom);
4225   ((Plot2d_AxisScaleDraw*)(scale))->applyTicks();
4226
4227   QwtScaleDraw::draw( painter, palette);
4228
4229   for (int i = 0; i < myTicks.size(); i++)
4230   {
4231       drawLabel( painter, myTicks[i]);
4232   }
4233
4234   //std::cout << "Ok for Plot2d_AxisScaleDraw::draw()" << std::endl;
4235 }
4236
4237
4238 QwtText Plot2d_AxisScaleDraw::label( double value) const
4239 {
4240   if (myLabelX.contains(value))
4241           return myLabelX[value];
4242
4243   return QwtText(QString::number(value, 'f', 1));
4244 }
4245
4246
4247 /* Stock position and label of a X tick
4248  */
4249 void Plot2d_AxisScaleDraw::setLabelTick( double value, QString label, bool isDevice)
4250 {
4251   //qDebug()<< "setLabelTick ( " << value << ","<< label <<" )";
4252   if ( isDevice )
4253   {
4254       // For systems names under X axis
4255       myLabelDevice[value] = label;
4256   }
4257   else
4258   {
4259       // For X axis graduations
4260       myLabelX[value] = label;
4261   }
4262 }
4263
4264
4265 /* Stock ticks positions of a system, and draw them
4266  */
4267 void Plot2d_AxisScaleDraw::setTicks(const QList<double> aTicks)
4268 {
4269   //std::cout << "  Plot2d_AxisScaleDraw::setTicks()" << std::endl;
4270   myTicks = aTicks;
4271
4272   applyTicks();
4273 }
4274
4275
4276 void Plot2d_AxisScaleDraw::setInterval(double lowerBound, double upperBound)
4277 {
4278   myLowerBound = lowerBound;
4279   myUpperBound = upperBound;
4280   myPlot->setAxisScale( QwtPlot::xBottom, myLowerBound, myUpperBound );
4281 }
4282
4283
4284 /* Stock X ticks in drawing zone
4285  */
4286 void Plot2d_AxisScaleDraw::applyTicks()
4287 {
4288   //std::cout << "  Plot2d_AxisScaleDraw::applyTicks()" << std::endl;
4289
4290   QList<double> major_ticks = scaleDiv().ticks(QwtScaleDiv::MajorTick);
4291   QList<double> medium_ticks = scaleDiv().ticks(QwtScaleDiv::MediumTick);
4292   QList<double> minor_ticks = scaleDiv().ticks(QwtScaleDiv::MinorTick);
4293
4294   medium_ticks.clear();
4295   minor_ticks.clear();
4296
4297   myPlot->axisScaleDiv(QwtPlot::xBottom)->setTicks(QwtScaleDiv::MajorTick, myTicks);
4298   myPlot->axisScaleDiv(QwtPlot::xBottom)->setTicks(QwtScaleDiv::MediumTick, medium_ticks);
4299   myPlot->axisScaleDiv(QwtPlot::xBottom)->setTicks(QwtScaleDiv::MinorTick, minor_ticks);
4300
4301   QwtScaleDiv* aScaleDiv = (QwtScaleDiv*) &scaleDiv();
4302
4303   aScaleDiv->setTicks(QwtScaleDiv::MajorTick, myTicks);
4304   aScaleDiv->setTicks(QwtScaleDiv::MediumTick, medium_ticks);
4305   aScaleDiv->setTicks(QwtScaleDiv::MinorTick, minor_ticks);
4306
4307   if (myLowerBound != -1 && myUpperBound != -1)
4308               aScaleDiv->setInterval(myLowerBound, myUpperBound);
4309
4310   //for (int i = 0; i < myTicks.size(); i++){
4311   //  QPoint p = labelPosition( i );
4312   //  qDebug() << i<< ") applyTicks -> LABEL" <<p;
4313   //}
4314 }
4315
4316
4317 void Plot2d_AxisScaleDraw::drawLabel( QPainter* painter, double value) const
4318 {
4319   //std::cout << "  Plot2d_AxisScaleDraw::drawLabel( " << value << " ) : "; //<< std::endl;
4320
4321   //qDebug() << "drawLabel  ( " <<value<<" )";
4322   if ( myLabelDevice.contains(value) )
4323   {
4324       QString deviceLabel = myLabelDevice[value];
4325       //
4326       std::string std_label = deviceLabel.toStdString();
4327       //const char *c_label = std_label.c_str();
4328       //std::cout << "    deviceLabel= |" << c_label << "|" << std::endl;
4329
4330       QPoint p = labelPosition( value );
4331       p += QPoint(0, DEVICE_BY);
4332       QFont  prevf = painter->font();
4333       //QColor prevc = (painter->pen()).color();
4334
4335       QFont devicef( DEVICE_FONT, DEVICE_FONT_SIZE, QFont::Bold);
4336       //
4337       //painter->setPen( QColor("blue") );
4338       painter->setFont( devicef );
4339       painter->drawText( p, myLabelDevice[value] );
4340       //painter->setPen( prevc );
4341       painter->setFont( prevf );
4342   }
4343   if ( myLabelX.contains(value) )
4344   {
4345       QString xLabel = myLabelX[value];
4346       //
4347       std::string std_label = xLabel.toStdString();
4348       //const char *c_label = std_label.c_str();
4349       //std::cout << "    xLabel= |" << c_label << "|" << std::endl;
4350
4351       QwtScaleDraw::drawLabel( painter, value );
4352   }
4353 }
4354
4355
4356 void Plot2d_AxisScaleDraw::drawTick( QPainter* painter, double value, int len) const
4357 {
4358   //qDebug() << "drawTick  ( " <<value<<" , "<<len<<" )  " ;
4359   //qDebug() << "myLabelX" << myLabelX;
4360   //
4361   if ( myLabelX.contains(value) )
4362   {
4363       QwtScaleDraw::drawTick( painter, value, len);
4364   }
4365 }
4366
4367
4368 /* Management of tooltips associated with markers for curves points or others points
4369  */
4370 const double Plot2d_QwtPlotPicker::BOUND_HV_SIZE = 0.2;
4371
4372 Plot2d_QwtPlotPicker::Plot2d_QwtPlotPicker( int            xAxis,
4373                                             int            yAxis,
4374                                             int            selectionFlags,
4375                                             RubberBand     rubberBand,
4376                                             DisplayMode    trackerMode,
4377                                             QwtPlotCanvas *canvas)
4378 : QwtPlotPicker( xAxis,
4379                  yAxis,
4380                  selectionFlags,
4381                  rubberBand,
4382                  trackerMode,
4383                  canvas)    // of drawing zone QwtPlot
4384 {
4385 }
4386
4387 Plot2d_QwtPlotPicker::Plot2d_QwtPlotPicker( int            xAxis,
4388                                             int            yAxis,
4389                                             QwtPlotCanvas *canvas)
4390 : QwtPlotPicker( xAxis,
4391                  yAxis,
4392                  canvas)
4393 {
4394 }
4395
4396 Plot2d_QwtPlotPicker::~Plot2d_QwtPlotPicker()
4397 {
4398 }
4399 // http://www.qtcentre.org/threads/22751-How-do-i-select-a-QwtPlotMarker-using-a-QPlotPicker
4400
4401 /* Return the tooltip associated with a point when the mouse cursor pass near
4402  */
4403 QwtText Plot2d_QwtPlotPicker::trackerText( const QwtDoublePoint & pos ) const
4404 {
4405   for (QList<QwtPlotMarker* >::const_iterator pMarkerIt = pMarkers.begin();pMarkerIt != pMarkers.end(); ++pMarkerIt )
4406     {
4407       QwtPlotMarker* pMarker = *pMarkerIt;
4408       if ( pMarker != NULL )
4409         {
4410           const QwtSymbol &symb=pMarker->symbol();
4411           const QSize& sz=symb.size();
4412           const QwtScaleMap yMapRef=plot()->canvasMap(QwtPlot::yLeft);
4413           const QwtScaleMap xMap=plot()->canvasMap(pMarker->xAxis());
4414           const QwtScaleMap yMap=plot()->canvasMap(pMarker->yAxis());
4415           QwtDoubleRect  bound0=pMarker->boundingRect();
4416           QRect bound00=pMarker->transform(xMap,yMap,bound0);
4417           QPoint toto(xMap.transform(pos.x()),yMapRef.transform(pos.y()));
4418           bound00.setX(bound00.x()-sz.width());
4419           bound00.setY(bound00.y()-sz.height());
4420           bound00.setWidth(bound00.width()+sz.width());
4421           bound00.setHeight(bound00.height()+sz.height());
4422           if( bound00.contains(toto) )
4423             {
4424               return pMarkersToolTip[pMarker];
4425             }
4426         }
4427   }
4428   return QwtText();
4429 }