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