Salome HOME
updated copyright message
[modules/gui.git] / src / Plot2d / Plot2d_ViewFrame.cxx
1 // Copyright (C) 2007-2023  CEA, EDF, 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 = 0., XgroupMax = 0.;
771       double YgroupMin = 0., YgroupMax = 0.;
772
773       // For one curve
774       double XcurveMin = 0., XcurveMax = 0.;
775       double YcurveMin = 0., YcurveMax = 0.;
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     break;
1904   }
1905
1906   if(updateView)
1907     myPlot->replot();
1908 }
1909
1910 /*
1911   Update Analytical curves
1912 */
1913 void Plot2d_ViewFrame::updateAnalyticalCurves()
1914 {
1915   AnalyticalCurveList::iterator it = myAnalyticalCurves.begin();
1916   AnalyticalCurveList toDelete;
1917   for( ; it != myAnalyticalCurves.end(); it++) {
1918     Plot2d_AnalyticalCurve* c = (*it);
1919     updateAnalyticalCurve(c);
1920     if(c && c->getAction() == Plot2d_AnalyticalCurve::ActRemoveFromView)
1921       toDelete.push_back(c);
1922   }
1923   it = toDelete.begin();
1924   for( ; it != toDelete.end(); it++) {
1925     Plot2d_AnalyticalCurve* c = (*it);
1926     myAnalyticalCurves.removeAll(c);
1927     delete c;
1928     c = NULL;
1929   }
1930   myPlot->replot();
1931 }
1932
1933 /*!
1934   Return list of the alalytical curves.
1935 */
1936 AnalyticalCurveList Plot2d_ViewFrame::getAnalyticalCurves() const
1937 {
1938   return myAnalyticalCurves  ;
1939 }
1940
1941 /*!
1942   Get analytical curve by plot item.
1943 */
1944 Plot2d_AnalyticalCurve* Plot2d_ViewFrame::getAnalyticalCurve(QwtPlotItem * theItem) {
1945   AnalyticalCurveList::iterator it = myAnalyticalCurves.begin();
1946   for( ; it != myAnalyticalCurves.end(); it++) {
1947     if((*it)->plotItem() == theItem)
1948       return (*it);
1949   }
1950   return 0;
1951 }
1952 #endif
1953
1954 /*!
1955   "Fit Data" command slot
1956 */
1957 void Plot2d_ViewFrame::onFitData()
1958 {
1959   Plot2d_FitDataDlg* dlg = new Plot2d_FitDataDlg( this, mySecondY );
1960   double xMin,xMax,yMin,yMax,y2Min,y2Max;
1961   getFitRanges(xMin,xMax,yMin,yMax,y2Min,y2Max);
1962
1963   dlg->setRange( xMin, xMax, yMin, yMax, y2Min, y2Max );
1964   if ( dlg->exec() == QDialog::Accepted ) {
1965     int mode = dlg->getRange( xMin, xMax, yMin, yMax, y2Min, y2Max );
1966     fitData(mode,xMin,xMax,yMin,yMax,y2Min,y2Max);
1967   }
1968   delete dlg;
1969 #ifndef NO_ANALYTICAL_CURVES
1970   updateAnalyticalCurves();
1971 #endif
1972 }
1973
1974 /*!
1975   Change background color
1976 */
1977 void Plot2d_ViewFrame::onChangeBackground()
1978 {
1979   QColor selColor = QColorDialog::getColor ( backgroundColor(), this );
1980   if ( selColor.isValid() ) {
1981     setBackgroundColor( selColor );
1982   }
1983 }
1984
1985 /*!
1986   Sets curve type
1987 */
1988 void Plot2d_ViewFrame::setCurveType( int curveType, bool update )
1989 {
1990   myCurveType = curveType;
1991   CurveDict aCurves = getCurves();
1992   CurveDict::iterator it = aCurves.begin();
1993   for ( ; it != aCurves.end(); it++ ) {
1994     QwtPlotCurve* crv = it.key();
1995     if ( crv )
1996       setCurveType( crv, myCurveType );
1997   }
1998   for(int i=0 ; i < myAnalyticalCurves.count(); i++) {
1999     QwtPlotCurve* aPCurve = dynamic_cast<QwtPlotCurve*>( myAnalyticalCurves[i]->plotItem() );
2000     Plot2d_AnalyticalCurve* aCurve = dynamic_cast<Plot2d_AnalyticalCurve*>( myAnalyticalCurves[i] );
2001     if ( aPCurve && aCurve ) {
2002       setCurveType( aPCurve, myCurveType );
2003     }
2004   }
2005   if ( update )
2006     myPlot->replot();
2007   emit vpCurveChanged();
2008 }
2009
2010 /*!
2011   Gets curve type
2012 */
2013 int Plot2d_ViewFrame::getCurveType() const
2014 {
2015   return myCurveType;
2016 }
2017
2018 /*!
2019   Sets curve title
2020   \param curveKey - curve id
2021   \param title - new title
2022 */
2023 void Plot2d_ViewFrame::setCurveTitle( Plot2d_Curve* curve, const QString& title )
2024 {
2025   setObjectTitle( curve, title );
2026 }
2027
2028 /*!
2029   Sets object title
2030   \param object - object id
2031   \param title - new title
2032 */
2033 void Plot2d_ViewFrame::setObjectTitle( Plot2d_Object* object, const QString& title )
2034 {
2035   if ( object && hasPlotObject( object ) )
2036     getPlotObject( object )->setTitle( title );
2037 }
2038
2039 /*!
2040   Shows/hides legend
2041 */
2042 void Plot2d_ViewFrame::showLegend( bool show, bool update )
2043 {
2044   myShowLegend = show;
2045   if ( myShowLegend ) {
2046     QwtAbstractLegend* absLegend = myPlot->legend();
2047     QwtLegend* legend = 0;
2048     if ( !absLegend ) {
2049       legend = new Plot2d_QwtLegend( myPlot );
2050       legend->setDefaultItemMode(QwtLegendData::Clickable);
2051       connect( legend, SIGNAL( clicked (const QVariant&, int) ),
2052                this, SIGNAL( clicked (const QVariant&, int) ) );
2053       legend->setFrameStyle( QFrame::Box | QFrame::Sunken );
2054     }
2055     else {
2056       legend = dynamic_cast<QwtLegend*>(absLegend);
2057     }
2058     if(legend) {
2059       myPlot->insertLegend( legend );
2060       setLegendPos( myLegendPos );
2061       setLegendFont( myLegendFont );
2062       setLegendFontColor( myLegendColor );
2063     }
2064   }
2065   else
2066     myPlot->insertLegend( 0 );
2067
2068   if( show && update )
2069     updateLegend();
2070
2071   if ( update )
2072     myPlot->replot();
2073 }
2074
2075 /*!
2076   Sets legend position : 0 - left, 1 - right, 2 - top, 3 - bottom
2077 */
2078 void Plot2d_ViewFrame::setLegendPos( int pos )
2079 {
2080   myLegendPos = pos;
2081   QwtAbstractLegend* legend = myPlot->legend();
2082   if ( legend ) {
2083     switch( pos ) {
2084     case 0:
2085       myPlot->insertLegend( legend, QwtPlot::LeftLegend );
2086       break;
2087     case 1:
2088       myPlot->insertLegend( legend, QwtPlot::RightLegend );
2089       break;
2090     case 2:
2091       myPlot->insertLegend( legend, QwtPlot::TopLegend );
2092       break;
2093     case 3:
2094       myPlot->insertLegend( legend, QwtPlot::BottomLegend );
2095       break;
2096     }
2097   }
2098 }
2099
2100 /*!
2101   Gets legend position : 0 - left, 1 - right, 2 - top, 3 - bottom
2102 */
2103 int Plot2d_ViewFrame::getLegendPos() const
2104 {
2105   return myLegendPos;
2106 }
2107
2108 /*!
2109   Sets legend symbol type : 0 - marker on line, 1 - marker above line
2110 */
2111 void Plot2d_ViewFrame::setLegendSymbolType( int type )
2112 {
2113   myLegendSymbolType = type;
2114   myPlot->setLegendSymbolType( type );
2115   updateLegend();
2116 }
2117
2118 /*!
2119   Gets legend symbol type : 0 - marker on line, 1 - marker above line
2120 */
2121 int Plot2d_ViewFrame::getLegendSymbolType() const
2122 {
2123   return myLegendSymbolType;
2124 }
2125
2126 /*!
2127   Sets legend font
2128 */
2129 void Plot2d_ViewFrame::setLegendFont( const QFont& fnt )
2130 {
2131   myLegendFont = fnt;
2132   QwtAbstractLegend* legend = myPlot->legend();
2133   if ( legend ) {
2134     legend->setFont(fnt);
2135   }
2136 }
2137
2138 /*!
2139   Gets legend font
2140 */
2141 QFont Plot2d_ViewFrame::getLegendFont() const
2142 {
2143   return myLegendFont;
2144 }
2145
2146 /*!
2147   Sets legend font color
2148 */
2149 void Plot2d_ViewFrame::setLegendFontColor( const QColor& col )
2150 {
2151   myLegendColor = col;
2152   QwtAbstractLegend* legend = myPlot->legend();
2153   if ( legend ) {
2154     QPalette pal = legend->palette();
2155     pal.setColor( QPalette::Text, col );
2156     legend->setPalette( pal );
2157   }
2158 }
2159
2160 /*!
2161   Gets legend font color
2162 */
2163 QColor Plot2d_ViewFrame::getLegendFontColor() const
2164 {
2165   return myLegendColor;
2166 }
2167
2168 /*!
2169   Sets selected legend font color
2170 */
2171 void Plot2d_ViewFrame::setSelectedLegendFontColor( const QColor& col )
2172 {
2173   mySelectedLegendFontColor = col;
2174   Plot2d_Object::setHighlightedLegendTextColor( col );
2175 }
2176
2177 /*!
2178   Gets selected legend font color
2179 */
2180 QColor Plot2d_ViewFrame::getSelectedLegendFontColor() const
2181 {
2182   return mySelectedLegendFontColor;
2183 }
2184
2185 /*!
2186   Sets new marker size
2187 */
2188 void Plot2d_ViewFrame::setMarkerSize( const int size, bool update )
2189 {
2190   if ( myMarkerSize != size )
2191   {
2192     myMarkerSize = size;
2193     CurveDict aCurves = getCurves();
2194     CurveDict::iterator it = aCurves.begin();
2195     for ( ; it != aCurves.end(); it++ ) {
2196       QwtPlotCurve* crv = it.key();
2197       if ( crv )
2198       {
2199         QwtSymbol* aSymbol = new QwtSymbol( crv->symbol()->style(), crv->symbol()->brush(),
2200                                                     crv->symbol()->pen(), QSize( myMarkerSize, myMarkerSize ) );
2201         crv->setSymbol( aSymbol );
2202         if( it.value() )
2203               it.value()->setMarkerSize( myMarkerSize );
2204       }
2205     }
2206     if ( update )
2207       myPlot->replot();
2208   }
2209 }
2210
2211 /*!
2212   Gets new marker size
2213 */
2214 int Plot2d_ViewFrame::getMarkerSize() const
2215 {
2216   return myMarkerSize;
2217 }
2218
2219 /*!
2220   Sets background color
2221 */
2222 void Plot2d_ViewFrame::setBackgroundColor( const QColor& color )
2223 {
2224   myBackground = color;
2225   myPlot->canvas()->setPalette( myBackground );
2226   myPlot->setPalette( myBackground );
2227   if ( myPlot->getLegend() ) {
2228     QPalette aPal = myPlot->getLegend()->palette();
2229     for ( int i = 0; i < QPalette::NColorGroups; i++ ) {
2230       aPal.setColor( QPalette::Base, myBackground );
2231       aPal.setColor( QPalette::Background, myBackground );
2232     }
2233     myPlot->getLegend()->setPalette( aPal );
2234     updateLegend();
2235   }
2236   Repaint();
2237 }
2238
2239 /*!
2240   Gets background color
2241 */
2242 QColor Plot2d_ViewFrame::backgroundColor() const
2243 {
2244   return myBackground;
2245 }
2246
2247 /*!
2248   Sets selection color
2249 */
2250 void Plot2d_ViewFrame::setSelectionColor( const QColor& color )
2251 {
2252   mySelectionColor = color;
2253   Plot2d_Object::setSelectionColor( color );
2254 }
2255
2256 /*!
2257   Gets selection color
2258 */
2259 QColor Plot2d_ViewFrame::selectionColor() const
2260 {
2261   return mySelectionColor;
2262 }
2263
2264 /*!
2265   Sets hor.axis grid parameters
2266 */
2267 void Plot2d_ViewFrame::setXGrid( bool xMajorEnabled, const int xMajorMax,
2268          bool xMinorEnabled, const int xMinorMax,
2269          bool update )
2270 {
2271   myXGridMajorEnabled = xMajorEnabled;
2272   myXGridMinorEnabled = xMinorEnabled;
2273   myXGridMaxMajor = xMajorMax;
2274   myXGridMaxMinor = xMinorMax;
2275
2276   myPlot->setAxisMaxMajor( QwtPlot::xBottom, myXGridMaxMajor );
2277   myPlot->setAxisMaxMinor( QwtPlot::xBottom, myXGridMaxMinor );
2278
2279   QwtPlotGrid* grid = myPlot->grid();
2280   if ( !myPlot->axisScaleDiv( QwtPlot::xBottom ).isEmpty() )
2281     grid->setXDiv( myPlot->axisScaleDiv( QwtPlot::xBottom ) );
2282   grid->enableX( myXGridMajorEnabled );
2283   grid->enableXMin( myXGridMinorEnabled );
2284
2285   if ( update )
2286     myPlot->replot();
2287 }
2288 /*!
2289   Sets ver.axis grid parameters
2290 */
2291 void Plot2d_ViewFrame::setYGrid( bool yMajorEnabled, const int yMajorMax,
2292                                  bool yMinorEnabled, const int yMinorMax,
2293                                  bool y2MajorEnabled, const int y2MajorMax,
2294                                  bool y2MinorEnabled, const int y2MinorMax,
2295                                  bool update )
2296 {
2297   myYGridMajorEnabled = yMajorEnabled;
2298   myYGridMinorEnabled = yMinorEnabled;
2299   myYGridMaxMajor = yMajorMax;
2300   myYGridMaxMinor = yMinorMax;
2301
2302   if (mySecondY) {
2303     myY2GridMajorEnabled = y2MajorEnabled;
2304     myY2GridMinorEnabled = y2MinorEnabled;
2305     myY2GridMaxMajor = y2MajorMax;
2306     myY2GridMaxMinor = y2MinorMax;
2307   }
2308   myPlot->setAxisMaxMajor( QwtPlot::yLeft, myYGridMaxMajor );
2309   myPlot->setAxisMaxMinor( QwtPlot::yLeft, myYGridMaxMinor );
2310
2311   if (mySecondY) {
2312     myPlot->setAxisMaxMajor( QwtPlot::yRight, myY2GridMaxMajor );
2313     myPlot->setAxisMaxMinor( QwtPlot::yRight, myY2GridMaxMinor );
2314   }
2315
2316   QwtPlotGrid* grid = myPlot->grid();
2317   if ( !myPlot->axisScaleDiv( QwtPlot::yLeft ).isEmpty() )
2318     grid->setYDiv( myPlot->axisScaleDiv( QwtPlot::yLeft ) );
2319
2320   if (mySecondY) {
2321     if (myYGridMajorEnabled) {
2322       grid->enableY( myYGridMajorEnabled );
2323       grid->enableYMin( myYGridMinorEnabled );
2324     }
2325     else if (myY2GridMajorEnabled) {
2326       if ( !myPlot->axisScaleDiv( QwtPlot::yRight ).isEmpty() )
2327         grid->setYDiv( myPlot->axisScaleDiv( QwtPlot::yRight ) );
2328       grid->enableY( myY2GridMajorEnabled );
2329       grid->enableYMin( myY2GridMinorEnabled );
2330     }
2331     else {
2332       grid->enableY( false );
2333       grid->enableYMin( false );
2334     }
2335   }
2336   else {
2337     grid->enableY( myYGridMajorEnabled );
2338     grid->enableYMin( myYGridMinorEnabled );
2339   }
2340   if ( update )
2341     myPlot->replot();
2342 }
2343
2344 /*!
2345   Sets title for some axis
2346 */
2347 void Plot2d_ViewFrame::setTitle( bool enabled, const QString& title,
2348                                  ObjectType type, bool update )
2349 {
2350   switch (type) {
2351     case MainTitle:
2352       myTitleEnabled = enabled;
2353       myTitle = title;
2354       myPlot->setTitle( myTitleEnabled ? myTitle : QString() );
2355       break;
2356     case XTitle:
2357       myXTitleEnabled = enabled;
2358       myXTitle = title;
2359       myPlot->setAxisTitle( QwtPlot::xBottom, myXTitleEnabled ? myXTitle : QString() );
2360       break;
2361     case YTitle:
2362       myYTitleEnabled = enabled;
2363       myYTitle = title;
2364       myPlot->setAxisTitle( QwtPlot::yLeft, myYTitleEnabled ? myYTitle : QString() );
2365       break;
2366     case Y2Title:
2367       myY2TitleEnabled = enabled;
2368       myY2Title = title;
2369       myPlot->setAxisTitle( QwtPlot::yRight, myY2TitleEnabled ? myY2Title : QString() );
2370       break;
2371     default:
2372       break;
2373   }
2374   if ( update )
2375     myPlot->replot();
2376 }
2377 /*!
2378   Sets title for some axis
2379 */
2380 QString Plot2d_ViewFrame::getTitle( ObjectType type ) const
2381 {
2382   QString title = "";
2383   switch (type) {
2384     case MainTitle:
2385       title = myTitle;   break;
2386     case XTitle:
2387       title = myXTitle;  break;
2388     case YTitle:
2389       title = myYTitle;  break;
2390     case Y2Title:
2391       title = myY2Title; break;
2392     default:
2393       break;
2394   }
2395   return title;
2396 }
2397 /*!
2398   Sets font for Plot2d object : title or axis
2399 */
2400 void Plot2d_ViewFrame::setFont( const QFont& font, ObjectType type, bool update)
2401 {
2402   switch (type) {
2403     case MainTitle:
2404       myPlot->title().setFont(font);
2405       break;
2406     case XTitle:
2407        myPlot->axisTitle(QwtPlot::xBottom).setFont(font); break;
2408     case YTitle:
2409       myPlot->axisTitle(QwtPlot::yLeft).setFont(font);    break;
2410     case Y2Title:
2411       myPlot->axisTitle(QwtPlot::yRight).setFont(font);   break;
2412     case XAxis:
2413       myPlot->setAxisFont(QwtPlot::xBottom, font);        break;
2414     case YAxis:
2415       myPlot->setAxisFont(QwtPlot::yLeft, font);          break;
2416     case Y2Axis:
2417       myPlot->setAxisFont(QwtPlot::yRight, font);         break;
2418   }
2419   if ( update )
2420     myPlot->replot();
2421 }
2422
2423 /*!
2424   Sets scale mode for horizontal axis: 0 - linear, 1 - logarithmic
2425 */
2426 void Plot2d_ViewFrame::setHorScaleMode( const int mode, bool update )
2427 {
2428   if ( myXMode == mode )
2429     return;
2430
2431   // san -- Protection against QwtCurve bug in Qwt 0.4.x:
2432   // it crashes if switched to X/Y logarithmic mode, when one or more points have
2433   // non-positive X/Y coordinate
2434   if ( mode && !isXLogEnabled() ){
2435 #ifndef NO_SUIT
2436     SUIT_MessageBox::warning(this, tr("WRN_WARNING"), tr("WRN_XLOG_NOT_ALLOWED"));
2437 #else
2438     QMessageBox::warning(this, tr("WRN_WARNING"), tr("WRN_XLOG_NOT_ALLOWED"));
2439 #endif
2440     return;
2441   }
2442
2443   myXMode = mode;
2444
2445   // set bounds of logarithmic scale
2446   if( myXMode != 0 ) {
2447     myPlot->setAxisScale( QwtPlot::xBottom, 1.0, 1e5 );
2448     myPlot->updateAxes();
2449   }
2450
2451   myPlot->setLogScale(QwtPlot::xBottom, myXMode != 0);
2452
2453   if ( update )
2454     fitAll();
2455   emit vpModeHorChanged();
2456 }
2457
2458 /*!
2459   Gets scale mode for horizontal axis: 0 - linear, 1 - logarithmic
2460 */
2461 int Plot2d_ViewFrame::getHorScaleMode() const
2462 {
2463   return myXMode;
2464 }
2465
2466 /*!
2467   Sets scale mode for vertical axis: 0 - linear, 1 - logarithmic
2468 */
2469 void Plot2d_ViewFrame::setVerScaleMode( const int mode, bool update )
2470 {
2471   if ( myYMode == mode )
2472     return;
2473
2474   // san -- Protection against QwtCurve bug in Qwt 0.4.x:
2475   // it crashes if switched to X/Y logarithmic mode, when one or more points have
2476   // non-positive X/Y coordinate
2477   if ( mode && !isYLogEnabled() ){
2478 #ifndef NO_SUIT
2479     SUIT_MessageBox::warning(this, tr("WRN_WARNING"), tr("WRN_YLOG_NOT_ALLOWED"));
2480 #else
2481     QMessageBox::warning(this, tr("WRN_WARNING"), tr("WRN_YLOG_NOT_ALLOWED"));
2482 #endif
2483     return;
2484   }
2485
2486   myYMode = mode;
2487
2488   // set bounds of logarithmic scale
2489   if( myYMode != 0 ){
2490     myPlot->setAxisScale( QwtPlot::yLeft, 1.0, 1e5 );
2491     myPlot->updateAxes();
2492   }
2493
2494   myPlot->setLogScale(QwtPlot::yLeft, myYMode != 0);
2495   if (mySecondY) {
2496     if( myYMode != 0 ){
2497       myPlot->setAxisScale( QwtPlot::yRight, 1.0, 1e5 );
2498       myPlot->updateAxes();
2499     }
2500     myPlot->setLogScale( QwtPlot::yRight, myYMode != 0 );
2501   }
2502
2503   if ( update )
2504     fitAll();
2505   emit vpModeVerChanged();
2506 }
2507
2508 /*!
2509   Gets scale mode for vertical axis: 0 - linear, 1 - logarithmic
2510 */
2511 int Plot2d_ViewFrame::getVerScaleMode() const
2512 {
2513   return myYMode;
2514 }
2515
2516 /*!
2517   Sets normalization mode to the global maximum by left Y axis
2518 */
2519 void Plot2d_ViewFrame::setNormLMaxMode( bool mode, bool update )
2520 {
2521   if ( myNormLMax == mode )
2522     return;
2523
2524   myNormLMax = mode;
2525   processFiltering(true);
2526   if ( update )
2527     fitAll();
2528   emit vpNormLModeChanged();
2529 }
2530
2531 /*!
2532   Gets normalization mode to the global maximum by left Y axis
2533 */
2534 bool Plot2d_ViewFrame::getNormLMaxMode() const
2535 {
2536   return myNormLMax;
2537 }
2538
2539 /*!
2540   Sets normalization mode to the global minimum by left Y axis
2541 */
2542 void Plot2d_ViewFrame::setNormLMinMode( bool mode, bool update )
2543 {
2544   if ( myNormLMin == mode )
2545     return;
2546
2547   myNormLMin = mode;
2548   processFiltering(true);
2549   if ( update )
2550     fitAll();
2551   emit vpNormLModeChanged();
2552 }
2553
2554 /*!
2555   Gets normalization mode to the global minimum by left Y axis
2556 */
2557 bool Plot2d_ViewFrame::getNormLMinMode() const
2558 {
2559   return myNormLMax;
2560 }
2561
2562 /*!
2563   Sets normalization mode to the global maximum by right Y axis
2564 */
2565 void Plot2d_ViewFrame::setNormRMaxMode( bool mode, bool update )
2566 {
2567   if ( myNormRMax == mode )
2568     return;
2569
2570   myNormRMax = mode;
2571   processFiltering(true);
2572   if ( update )
2573     fitAll();
2574   emit vpNormRModeChanged();
2575 }
2576
2577 /*!
2578   Gets normalization mode to the global maximum by right Y axis
2579 */
2580 bool Plot2d_ViewFrame::getNormRMaxMode() const
2581 {
2582   return myNormRMax;
2583 }
2584
2585 /*!
2586   Sets normalization mode to the global minimum by right Y axis
2587 */
2588 void Plot2d_ViewFrame::setNormRMinMode( bool mode, bool update )
2589 {
2590   if ( myNormRMin == mode )
2591     return;
2592
2593   myNormRMin = mode;
2594   processFiltering(true);
2595   if ( update )
2596     fitAll();
2597   emit vpNormRModeChanged();
2598 }
2599
2600 /*!
2601   Gets normalization mode to the global minimum by right Y axis
2602 */
2603 bool Plot2d_ViewFrame::getNormRMinMode() const
2604 {
2605   return myNormRMax;
2606 }
2607
2608 /*!
2609   Return, scale mode for horizontal axis
2610 */
2611 bool Plot2d_ViewFrame::isModeHorLinear()
2612 {
2613   return (myXMode == 0 ? true : false);
2614 }
2615
2616 /*!
2617   Return, scale mode for vertical axis
2618 */
2619 bool Plot2d_ViewFrame::isModeVerLinear()
2620 {
2621   return (myYMode == 0 ? true : false);
2622 }
2623
2624 /*!
2625   Return \c True if curves are normalize to the global maximum by left Y axis
2626 */
2627 bool Plot2d_ViewFrame::isNormLMaxMode()
2628 {
2629   return (myNormLMax ? true : false);
2630 }
2631
2632 /*!
2633   Return \c True if curves are normalize to the global minimum by left Y axis
2634 */
2635 bool Plot2d_ViewFrame::isNormLMinMode()
2636 {
2637   return (myNormLMin ? true : false);
2638 }
2639
2640 /*!
2641   Return \c True if curves are normalize to the global maximum by right Y axis
2642 */
2643 bool Plot2d_ViewFrame::isNormRMaxMode()
2644 {
2645   return (myNormRMax ? true : false);
2646 }
2647
2648 /*!
2649   Return \c True if curves are normalize to the global minimum by right Y axis
2650 */
2651 bool Plot2d_ViewFrame::isNormRMinMode()
2652 {
2653   return (myNormRMin ? true : false);
2654 }
2655
2656 /*!
2657   Return \c True if legend is shown
2658 */
2659 bool Plot2d_ViewFrame::isLegendShow() const
2660 {
2661   return myShowLegend;
2662 }
2663
2664 /*!
2665   Slot, called when user presses mouse button
2666 */
2667 void Plot2d_ViewFrame::plotMousePressed( const QMouseEvent& me )
2668 {
2669 #ifndef NO_SUIT
2670   Plot2d_ViewWindow* aParent = dynamic_cast<Plot2d_ViewWindow*>(parent());
2671   if (aParent)
2672      aParent->putInfo(getInfo(me.pos()));
2673 #endif
2674   if ( myOperation == NoOpId )
2675     myOperation = testOperation( me );
2676   if ( myOperation != NoOpId ) {
2677     myPnt = me.pos();
2678     if ( myOperation == GlPanId ) {
2679       myPlot->setAxisScale( QwtPlot::yLeft,
2680           myPlot->invTransform( QwtPlot::yLeft, myPnt.y() ) - myYDistance/2,
2681           myPlot->invTransform( QwtPlot::yLeft, myPnt.y() ) + myYDistance/2 );
2682       myPlot->setAxisScale( QwtPlot::xBottom,
2683           myPlot->invTransform( QwtPlot::xBottom, myPnt.x() ) - myXDistance/2,
2684           myPlot->invTransform( QwtPlot::xBottom, myPnt.x() ) + myXDistance/2 );
2685       if (mySecondY)
2686         myPlot->setAxisScale( QwtPlot::yRight,
2687           myPlot->invTransform( QwtPlot::yRight, myPnt.y() ) - myYDistance2/2,
2688           myPlot->invTransform( QwtPlot::yRight, myPnt.y() ) + myYDistance2/2 );
2689       myPlot->replot();
2690     }
2691   }
2692   else {
2693     int btn = (int)me.button() | (int)me.modifiers();
2694     if (btn == Qt::RightButton) {
2695       QMouseEvent* aEvent = new QMouseEvent(QEvent::MouseButtonPress,
2696                                             me.pos(), me.button(), me.buttons(), me.modifiers() );
2697       // QMouseEvent 'me' has the 'MouseButtonDblClick' type. In this case we create new event 'aEvent'.
2698       parent()->eventFilter(this, aEvent);
2699     }
2700   }
2701   setFocus();
2702 }
2703 /*!
2704   Slot, called when user moves mouse
2705 */
2706 bool Plot2d_ViewFrame::plotMouseMoved( const QMouseEvent& me )
2707 {
2708   int    dx = me.pos().x() - myPnt.x();
2709   int    dy = me.pos().y() - myPnt.y();
2710
2711   bool aRes = false;
2712   if ( myOperation != NoOpId) {
2713     if ( myOperation == ZoomId ) {
2714       this->incrementalZoom( dx, dy );
2715       myPnt = me.pos();
2716       aRes = true;
2717     }
2718     else if ( myOperation == PanId ) {
2719       this->incrementalPan( dx, dy );
2720       myPnt = me.pos();
2721       aRes = true;
2722     }
2723   }
2724   else {
2725 #ifndef NO_SUIT
2726      Plot2d_ViewWindow* aParent = dynamic_cast<Plot2d_ViewWindow*>(parent());
2727      if (aParent)
2728        aParent->putInfo(getInfo(me.pos()));
2729 #endif
2730   }
2731   return aRes;
2732 }
2733 /*!
2734   Slot, called when user releases mouse
2735 */
2736 void Plot2d_ViewFrame::plotMouseReleased( const QMouseEvent& me )
2737 {
2738   if ( myOperation == NoOpId && me.button() == Qt::RightButton && me.modifiers() != Qt::ControlModifier )
2739   {
2740     QContextMenuEvent aEvent( QContextMenuEvent::Mouse,
2741                               me.pos(), me.globalPos() );
2742     emit contextMenuRequested( &aEvent );
2743   }
2744   else {
2745 #ifndef NO_ANALYTICAL_CURVES
2746     updateAnalyticalCurves();
2747 #endif
2748   }
2749   myPlot->canvas()->setCursor( QCursor( Qt::CrossCursor ) );
2750   myPlot->defaultPicker();
2751
2752 #ifndef NO_SUIT
2753   Plot2d_ViewWindow* aParent = dynamic_cast<Plot2d_ViewWindow*>(parent());
2754    if (aParent)
2755      aParent->putInfo(tr("INF_READY"));
2756 #endif
2757   myOperation = NoOpId;
2758 }
2759 /*!
2760   Slot, called when user wheeling mouse
2761 */
2762 void Plot2d_ViewFrame::wheelEvent(QWheelEvent* event)
2763 {
2764   QwtPlotLayout* pl = myPlot->plotLayout();
2765
2766   // compute zooming factor
2767   double aDelta = event->delta();
2768   double aScale = (aDelta < 0) ? 100./(-aDelta) : aDelta/100.;
2769
2770   bool scaleXBottom = pl->scaleRect(QwtPlot::xBottom).contains( event->pos() ) ||
2771                       pl->canvasRect().contains( event->pos() );
2772   bool scaleYLeft   = pl->scaleRect(QwtPlot::yLeft).contains( event->pos() ) ||
2773                       pl->canvasRect().contains( event->pos() );
2774   bool scaleYRight  = mySecondY && ( pl->scaleRect(QwtPlot::yRight).contains( event->pos() ) ||
2775                                      pl->canvasRect().contains( event->pos() ) );
2776
2777   // scale x bottom axis
2778   if ( scaleXBottom ) {
2779     QwtScaleMap xMap = myPlot->canvasMap( QwtPlot::xBottom );
2780     if ( xMap.s2() - xMap.s1() > 1.0e-12 || aScale > 1 )
2781       myPlot->setAxisScale( QwtPlot::xBottom, xMap.s1(), xMap.s1() + aScale*(xMap.s2() - xMap.s1()) );
2782   }
2783
2784   // scale y left axis
2785   if ( scaleYLeft ) {
2786     QwtScaleMap yMap = myPlot->canvasMap( QwtPlot::yLeft );
2787     if ( yMap.s2() - yMap.s1() > 1.0e-12 || aScale > 1 )
2788       myPlot->setAxisScale( QwtPlot::yLeft, yMap.s1(), yMap.s1() + aScale*(yMap.s2() - yMap.s1()) );
2789   }
2790
2791   // scale y right axis (note: mySecondY value is checked above)
2792   if ( scaleYRight ) {
2793     QwtScaleMap yMap = myPlot->canvasMap( QwtPlot::yRight );
2794     if ( yMap.s2() - yMap.s1() > 10e-12 || aScale > 1 )
2795       myPlot->setAxisScale( QwtPlot::yRight, yMap.s1(), yMap.s1() + aScale*(yMap.s2() - yMap.s1()) );
2796   }
2797
2798   // redraw
2799   myPlot->replot();
2800   // update zoomer
2801   if ( myPlot->zoomer() ) myPlot->zoomer()->setZoomBase();
2802   // store current mouse position
2803   myPnt = event->pos();
2804 #ifndef NO_ANALYTICAL_CURVES
2805   // update analytical curves
2806   updateAnalyticalCurves();
2807 #endif
2808 }
2809
2810 /*!
2811   Returns qwt plot curve if it is existed in map of curves and 0 otherwise
2812 */
2813 QwtPlotCurve* Plot2d_ViewFrame::getPlotCurve( Plot2d_Curve* curve ) const
2814 {
2815   return dynamic_cast<QwtPlotCurve*>( getPlotObject( curve ) );
2816 }
2817 /*!
2818   Returns true if qwt plot curve is existed in map of curves and false otherwise
2819 */
2820 bool Plot2d_ViewFrame::hasPlotCurve( Plot2d_Curve* curve ) const
2821 {
2822   return hasPlotObject( curve );
2823 }
2824
2825 /*!
2826   Returns qwt plot curve if it is existed in map of curves and 0 otherwise
2827 */
2828 QwtPlotItem* Plot2d_ViewFrame::getPlotObject( Plot2d_Object* object ) const
2829 {
2830   ObjectDict::const_iterator it = myObjects.begin();
2831   for ( ; it != myObjects.end(); it++ ) {
2832     if ( it.value() == object )
2833       return it.key();
2834   }
2835   return 0;
2836 }
2837 /*!
2838   Returns true if qwt plot curve is existed in map of curves and false otherwise
2839 */
2840 bool Plot2d_ViewFrame::hasPlotObject( Plot2d_Object* object ) const
2841 {
2842   ObjectDict::const_iterator it = myObjects.begin();
2843   for ( ; it != myObjects.end(); it++ ) {
2844     if ( it.value() == object )
2845       return true;
2846   }
2847   return false;
2848 }
2849
2850 /*!
2851   Sets curve type
2852 */
2853 void Plot2d_ViewFrame::setCurveType( QwtPlotCurve* curve, int /*curveType*/ )
2854 {
2855   if ( !curve )
2856     return;
2857   if ( myCurveType == 0 )
2858     curve->setStyle( QwtPlotCurve::Dots );//QwtCurve::NoCurve
2859   else if ( myCurveType == 1 ) {
2860     curve->setStyle( QwtPlotCurve::Lines );
2861     curve->setCurveAttribute( QwtPlotCurve::Fitted, false );
2862   }
2863   else if ( myCurveType == 2 ) {
2864     curve->setStyle( QwtPlotCurve::Lines );
2865     QwtSplineCurveFitter* fitter = new QwtSplineCurveFitter();
2866     fitter->setSplineSize( 250 );
2867     curve->setCurveAttribute( QwtPlotCurve::Fitted, true );
2868     curve->setCurveFitter( fitter );
2869   }
2870 }
2871
2872 /*!
2873   View operations : Pan view
2874 */
2875 void Plot2d_ViewFrame::onViewPan()
2876 {
2877   // reset the previous operation
2878   myPlot->defaultPicker();
2879
2880   QCursor panCursor (Qt::SizeAllCursor);
2881   myPlot->canvas()->setCursor( panCursor );
2882   myOperation = PanId;
2883 }
2884 /*!
2885   View operations : Zoom view
2886 */
2887 void Plot2d_ViewFrame::onViewZoom()
2888 {
2889   // reset the previous operation
2890   myPlot->defaultPicker();
2891
2892   QPixmap zoomPixmap (imageZoomCursor);
2893   QCursor zoomCursor (zoomPixmap);
2894   myPlot->canvas()->setCursor( zoomCursor );
2895   myOperation = ZoomId;
2896 }
2897 /*!
2898   View operations : Fit All
2899 */
2900 void Plot2d_ViewFrame::onViewFitAll()
2901 {
2902   fitAll();
2903
2904   // reset the previous operation
2905   myPlot->defaultPicker();
2906   myPlot->canvas()->setCursor( QCursor(Qt::CrossCursor) );
2907   myOperation = NoOpId;
2908 }
2909 /*!
2910   View operations : Fit Area
2911 */
2912 void Plot2d_ViewFrame::onViewFitArea()
2913 {
2914   myPlot->canvas()->setCursor( QCursor( Qt::PointingHandCursor ) );
2915   myOperation = FitAreaId;
2916   myPlot->setPickerMousePattern( Qt::LeftButton );
2917 }
2918 /*!
2919   View operations : Global panning
2920 */
2921 void Plot2d_ViewFrame::onViewGlobalPan()
2922 {
2923   // reset the previous operation
2924   myPlot->defaultPicker();
2925
2926   QPixmap globalPanPixmap (imageCrossCursor);
2927   QCursor glPanCursor (globalPanPixmap);
2928   myPlot->canvas()->setCursor( glPanCursor );
2929   myPlot->setLogScale(QwtPlot::xBottom, false);
2930   myPlot->setLogScale(QwtPlot::yLeft, false);
2931   if (mySecondY)
2932     myPlot->setLogScale(QwtPlot::yRight, false);
2933   myPlot->replot();
2934   QwtScaleMap xMap = myPlot->canvasMap( QwtPlot::xBottom );
2935   QwtScaleMap yMap = myPlot->canvasMap( QwtPlot::yLeft );
2936
2937   myXDistance = xMap.s2() - xMap.s1();
2938   myYDistance = yMap.s2() - yMap.s1();
2939
2940   if (mySecondY) {
2941     QwtScaleMap yMap2 = myPlot->canvasMap( QwtPlot::yRight );
2942     myYDistance2 = yMap2.s2() - yMap2.s1();
2943   }
2944   // don't make fit all
2945   // fitAll();
2946   myOperation = GlPanId;
2947 }
2948
2949 /*!
2950   Precaution for logarithmic X scale
2951 */
2952 bool Plot2d_ViewFrame::isXLogEnabled() const
2953 {
2954   bool allPositive = true;
2955   ObjectDict::const_iterator it = myObjects.begin();
2956   for ( ; allPositive && it != myObjects.end(); it++ )
2957     allPositive = ( it.value()->getMinX() > 0. );
2958   return allPositive;
2959 }
2960
2961 /*!
2962   Precaution for logarithmic Y scale
2963 */
2964 bool Plot2d_ViewFrame::isYLogEnabled() const
2965 {
2966   bool allPositive = true;
2967   ObjectDict::const_iterator it = myObjects.begin();
2968   for ( ; allPositive && it != myObjects.end(); it++ )
2969     allPositive = ( it.value()->getMinY() > 0. );
2970   return allPositive;
2971 }
2972
2973 /**
2974  *
2975  */
2976 void Plot2d_ViewFrame::setEnableAxis( QwtPlot::Axis theAxis, bool isEnable )
2977 {
2978   if ( myPlot->axisEnabled( theAxis ) == isEnable )
2979     return;
2980   myPlot->enableAxis( theAxis, isEnable );
2981   if ( theAxis == QwtPlot::yRight )
2982     mySecondY = isEnable;
2983 }
2984
2985 class Plot2d_QwtPlotZoomer : public QwtPlotZoomer
2986 {
2987 public:
2988   Plot2d_QwtPlotZoomer( int xAxis, int yAxis, QWidget* canvas )
2989   : QwtPlotZoomer( xAxis, yAxis, canvas )
2990   {
2991     qApp->installEventFilter( this );
2992     // now picker working after only a button pick.
2993     // after click on button FitArea in toolbar of the ViewFrame.
2994   };
2995   ~Plot2d_QwtPlotZoomer() {};
2996 };
2997
2998 /*!
2999   Constructor
3000 */
3001 Plot2d_Plot2d::Plot2d_Plot2d( QWidget* parent )
3002   : QwtPlot( parent ),
3003     myPicker( 0 )
3004 {
3005   // Create alternative scales
3006   setAxisScaleDraw( QwtPlot::yLeft,   new Plot2d_ScaleDraw() );
3007   setAxisScaleDraw( QwtPlot::xBottom, new Plot2d_ScaleDraw() );
3008   setAxisScaleDraw( QwtPlot::yRight,  new Plot2d_ScaleDraw() );
3009
3010   myPlotZoomer = new Plot2d_QwtPlotZoomer( QwtPlot::xBottom, QwtPlot::yLeft, canvas() );
3011   myPlotZoomer->setTrackerMode( QwtPicker::AlwaysOff );
3012   myPlotZoomer->setRubberBand( QwtPicker::RectRubberBand );
3013   myPlotZoomer->setRubberBandPen( QColor( Qt::green ) );
3014
3015   defaultPicker();
3016
3017   // auto scaling by default
3018   setAxisAutoScale( QwtPlot::yLeft );
3019   setAxisAutoScale( QwtPlot::yRight );
3020   setAxisAutoScale( QwtPlot::xBottom );
3021
3022   myScaleDraw = NULL;
3023 // grid
3024   myGrid = new QwtPlotGrid();
3025   QPen aMajPen = myGrid->majorPen();
3026   aMajPen.setStyle( Qt::DashLine );
3027   myGrid->setPen( aMajPen );
3028
3029   myGrid->enableX( false );
3030   myGrid->enableXMin( false );
3031   myGrid->enableY( false );
3032   myGrid->enableYMin( false );
3033
3034   myGrid->attach( this );
3035
3036   setMouseTracking( false );
3037   canvas()->setMouseTracking( true );
3038
3039   myPlotZoomer->setEnabled( true );
3040   myPlotZoomer->setZoomBase();
3041
3042   setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
3043 }
3044
3045 Plot2d_Plot2d::~Plot2d_Plot2d()
3046 {
3047 }
3048
3049 /*!
3050   \set axis scale engine - linear or log10
3051 */
3052 void Plot2d_Plot2d::setLogScale( int axisId, bool log10 )
3053 {
3054   if ( log10 )
3055     setAxisScaleEngine( axisId, new QwtLogScaleEngine() );
3056   else
3057     setAxisScaleEngine( axisId, new QwtLinearScaleEngine() );
3058 }
3059
3060 /*!
3061   Recalculates and redraws Plot 2d view
3062 */
3063 void Plot2d_Plot2d::replot()
3064 {
3065   // the following code is intended to enable only axes
3066   // that are really used by displayed objects
3067   bool enableXBottom = false, enableXTop   = false;
3068   bool enableYLeft   = false, enableYRight = false;
3069   const QwtPlotItemList& items = itemList();
3070   QwtPlotItemIterator it;
3071   for ( it = items.begin(); it != items.end(); it++ ) {
3072     QwtPlotItem* item = *it;
3073     if ( item ) {
3074       enableXBottom |= item->xAxis() == QwtPlot::xBottom;
3075       enableXTop    |= item->xAxis() == QwtPlot::xTop;
3076       enableYLeft   |= item->yAxis() == QwtPlot::yLeft;
3077       enableYRight  |= item->yAxis() == QwtPlot::yRight;
3078     }
3079   }
3080   enableAxis( QwtPlot::xBottom, enableXBottom );
3081   enableAxis( QwtPlot::xTop,    enableXTop );
3082   enableAxis( QwtPlot::yLeft,   enableYLeft );
3083   enableAxis( QwtPlot::yRight,  enableYRight );
3084
3085   updateLayout();  // to fix bug(?) of Qwt - view is not updated when title is changed
3086   QwtPlot::replot();
3087 }
3088
3089 /*!
3090   Get legend
3091 */
3092 QwtAbstractLegend* Plot2d_Plot2d::getLegend()
3093 {
3094 #if QWT_VERSION < 0x040200
3095   return d_legend;
3096 #else
3097   return legend(); /* mpv: porting to the Qwt 4.2.0 */
3098 #endif
3099 }
3100
3101 /*!
3102   \return the recommended size for the widget
3103 */
3104 QSize Plot2d_Plot2d::sizeHint() const
3105 {
3106   return QwtPlot::minimumSizeHint();
3107 }
3108
3109 /*!
3110   return minimum size for qwt plot
3111 */
3112 QSize Plot2d_Plot2d::minimumSizeHint() const
3113 {
3114   return QSize( 0, 0 );
3115 //  QSize aSize = QwtPlot::minimumSizeHint();
3116 //  return QSize(aSize.width()*3/4, aSize.height());
3117 }
3118
3119 void Plot2d_Plot2d::defaultPicker()
3120 {
3121   myPlotZoomer->setMousePattern( QwtEventPattern::MouseSelect1,
3122                                  Qt::RightButton, Qt::ControlModifier ); // zooming button
3123   for ( int i = QwtEventPattern::MouseSelect2; i < QwtEventPattern::MouseSelect6; i++ )
3124     myPlotZoomer->setMousePattern( (QwtEventPattern::MousePatternCode)i, Qt::NoButton,
3125                                        Qt::NoModifier );
3126 }
3127
3128 void Plot2d_Plot2d::setPickerMousePattern( int button, int state )
3129 {
3130   myPlotZoomer->setMousePattern( QwtEventPattern::MouseSelect1, (Qt::MouseButton)button,
3131                                          (Qt::KeyboardModifiers)state );
3132 }
3133
3134 /*!
3135  * Set the point picker associated with a graphic view
3136  */
3137 void Plot2d_Plot2d::setPicker( Plot2d_QwtPlotPicker *picker)
3138 {
3139   myPicker = picker;
3140 }
3141
3142 /*!
3143  * Create marker and tooltip associed with a point
3144  */
3145 QwtPlotMarker* Plot2d_Plot2d::createMarkerAndTooltip( QwtSymbol* symbol,
3146                                                       double    X,
3147                                                       double    Y,
3148                                                       QString & tooltip,
3149                                                       Plot2d_QwtPlotPicker *picker)
3150 {
3151   QwtPlotMarker* aPlotMarker = new QwtPlotMarker();
3152
3153   aPlotMarker->setSymbol( symbol );  // symbol must have a color
3154   aPlotMarker->setLabelAlignment( Qt::AlignTop);
3155   aPlotMarker->setXValue(X);
3156   aPlotMarker->setYValue(Y);
3157   //
3158   aPlotMarker->attach(this);
3159
3160   // Associate a tooltip with the point's marker
3161   // PB: how to obtain a tooltip with a rectangular frame ?
3162   //QwtText tooltip ("X=" + QString::number(X) + " Y=" + QString::number(Y) );
3163
3164   QwtText text (tooltip);
3165   //QColor tooltipColor( 245, 222, 179);            // Wheat  -RGB (0 a 255)
3166   QColor tooltipColor( 253, 245, 230);            // OldLace
3167   text.setBackgroundBrush( QBrush(tooltipColor)); //, Qt::SolidPattern));
3168   //
3169   if ( picker ) {
3170     picker->pMarkers.append( aPlotMarker);
3171     picker->pMarkersToolTip[ aPlotMarker] = text;
3172   }
3173   return aPlotMarker;
3174 }
3175
3176 QwtPlotGrid* Plot2d_Plot2d::grid() const
3177 {
3178   return myGrid;
3179 }
3180
3181 QwtPlotZoomer* Plot2d_Plot2d::zoomer() const
3182 {
3183   return myPlotZoomer;
3184 }
3185
3186 /*!
3187   Updates identifiers of Y axis type in the legend.
3188 */
3189 void Plot2d_Plot2d::updateYAxisIdentifiers()
3190 {
3191   bool enableYLeft = false, enableYRight = false;
3192   const QwtPlotItemList& items = itemList();
3193   QwtPlotItemIterator it;
3194   for ( it = items.begin(); it != items.end(); it++ ) {
3195     QwtPlotItem* item = *it;
3196     if ( item ) {
3197       enableYLeft  |= item->yAxis() == QwtPlot::yLeft;
3198       enableYRight |= item->yAxis() == QwtPlot::yRight;
3199     }
3200   }
3201
3202   // if several curves are attached to different axes
3203   // display corresponding identifiers in the legend,
3204   // otherwise hide them
3205   for ( it = items.begin(); it != items.end(); it++ ) {
3206     QwtPlotItem* item = *it;
3207     if ( Plot2d_QwtPlotCurve* aPCurve = dynamic_cast<Plot2d_QwtPlotCurve*>( item ) )
3208       aPCurve->setYAxisIdentifierEnabled( enableYLeft && enableYRight );
3209     if ( item && item->isVisible() && legend() )
3210       item->updateLegend( item, item->legendData() );
3211   }
3212 }
3213
3214 // Methods to manage axis graduations
3215
3216 /* Create definition and graduations of axes
3217  */
3218 void Plot2d_Plot2d::createAxisScaleDraw()
3219 {
3220   myScaleDraw = new Plot2d_AxisScaleDraw( this);
3221 }
3222
3223
3224 /* Stock X axis's ticks in the drawing zone
3225 */
3226 void Plot2d_Plot2d::applyTicks()
3227 {
3228   myScaleDraw->applyTicks();
3229 }
3230
3231
3232 /* Unactivate automatic ticks drawing (call to method Plot2d_AxisScaleDraw::draw() )
3233  * Parameters :
3234  * - number call to ticks drawing (for information) : numcall
3235  */
3236 void Plot2d_Plot2d::unactivAxisScaleDraw( int numcall)
3237 {
3238   // Memorize X axis (myScaleDraw already exists) in the drawing zone
3239   //setAxisScaleDraw( QwtPlot::xBottom, myScaleDraw);  // heritage of QwtPlot
3240
3241   myScaleDraw->unactivTicksDrawing( numcall);
3242 }
3243
3244
3245 /* Draw ticks and labels on X axis of the drawing zone
3246  * Draw systems' names under the X axis of the drawing zone
3247  * Draw vertical segments between X axis's intervals of the systems
3248  * Parameters :
3249  * - left and right margins for ticks : XLeftMargin, XRightMargin
3250  * - for each named system :
3251  *     positions and labels for ticks on X axis : devicesPosLabelTicks
3252  *
3253  * The true drawings will be realized by the method Plot2d_AxisScaleDraw::draw()
3254  * PB: who call il ?
3255  */
3256 void Plot2d_Plot2d::displayXTicksAndLabels(
3257                       double XLeftMargin, double XRightMargin,
3258                       const QList< QPair< QString, QMap<double, QString> > > & devicesPosLabelTicks)
3259                       //                    name        position  label
3260                       //                   system         tick    tick
3261 {
3262   //std::cout << "Plot2d_Plot2d::displayXTicksAndLabels() 1" << std::endl;
3263
3264   int nbDevices = devicesPosLabelTicks.size();
3265   //
3266   //std::cout << "  Nombre de systemes = " << nbDevices << std::endl;
3267   if (nbDevices == 0)  return;
3268
3269   // For drawing systems' names, their positions must be in the allTicks list
3270   // (cf class Plot2d_AxisScaleDraw)
3271
3272   // Liste of ticks' positions and systems' names
3273   QList<double> allTicks;
3274
3275   double devXmin, devXmax;  // X interval of a system
3276   double gapXmin = 0., gapXmax = 0.;  // X interval between two systems
3277   double devLabPos;         // Label's position of a system
3278   double segmentPos;  // Position of the vertical segment between current system and the next
3279
3280   // 1)- Search for the system whose X interval is the most to the left
3281
3282   int ileftDev = 0;
3283   double XminMin = 1.e+12;
3284
3285   if (nbDevices > 1)
3286   {
3287       for (int idev=0; idev < nbDevices; idev++)
3288       {
3289           QPair< QString, QMap<double,QString> > paire = devicesPosLabelTicks.at(idev);
3290
3291           QString deviceLabel = paire.first;
3292
3293           // Ticks' map of the system
3294           QMap<double,QString> devPosLabelTicks = paire.second;
3295
3296           QList<double> posTicks = devPosLabelTicks.keys();
3297
3298           // List's items increasing sorting
3299           qSort( posTicks.begin(), posTicks.end() );  // iterators
3300
3301           // X interval for the system
3302           devXmin = posTicks.first();
3303           devXmax = posTicks.last();
3304
3305           if (devXmin < XminMin)
3306           {
3307               XminMin = devXmin;
3308               ileftDev = idev;
3309           }
3310       }
3311   }
3312
3313   // 2)- Ticks, systems' names, verticals segments
3314
3315   for (int idev=0; idev < nbDevices; idev++)
3316   {
3317       QPair< QString, QMap<double,QString> > paire = devicesPosLabelTicks.at(idev);
3318
3319       QString deviceLabel = paire.first;
3320
3321       std::string std_label = deviceLabel.toStdString();
3322       //const char *c_label = std_label.c_str();
3323       //std::cout << "  deviceLabel: |" << c_label << "|" << std::endl;
3324
3325       // Ticks' map of the system
3326       QMap<double,QString> devPosLabelTicks = paire.second;
3327
3328       int nbTicks = devPosLabelTicks.size();
3329
3330       QList<double> posTicks = devPosLabelTicks.keys();
3331
3332       // List's items increasing sorting
3333       qSort( posTicks.begin(), posTicks.end() );  // iterators
3334
3335       // X interval for the system
3336       devXmin = posTicks.first();
3337       devXmax = posTicks.last();
3338
3339       // Stock ticks' positions and labels on X axis
3340       double pos;
3341       QString label;
3342       //
3343       for (int itic=0; itic < nbTicks; itic++)
3344       {
3345           pos   = posTicks.at(itic);
3346           label = devPosLabelTicks[pos];
3347
3348           myScaleDraw->setLabelTick( pos, label, false);
3349
3350           std::string std_label = label.toStdString();
3351           //const char *c_label = std_label.c_str();
3352           //std::cout << "    tick " << itic << " : pos= " << pos << ", label= |" << c_label << "|" << std::endl;
3353       }
3354       allTicks.append( posTicks);
3355
3356       // Compute the position of the system's label
3357       if (idev == ileftDev)
3358       {
3359           devLabPos = devXmin + 0.25*(devXmax - devXmin);
3360       }
3361       else
3362       {
3363           devLabPos = devXmin + 0.50*(devXmax - devXmin);
3364       }
3365       allTicks.append( devLabPos);
3366
3367       // Stock position and name of the system under X axis
3368       myScaleDraw->setLabelTick( devLabPos, deviceLabel, true);
3369
3370       if (idev > 0)
3371       {
3372           // Create the vertical segment between the current system and the next
3373           gapXmax = devXmin;
3374           segmentPos = gapXmin + 0.5*(gapXmax - gapXmin);
3375
3376           createSeparationLine( segmentPos);
3377       }
3378       gapXmin = devXmax;
3379   }
3380
3381   // List's items increasing sorting
3382   qSort( allTicks.begin(), allTicks.end() );  // iterators
3383
3384   // Stock the interval of X's values
3385   double lowerBound = allTicks.first() - XLeftMargin;
3386   double upperBound = allTicks.last() + XRightMargin;
3387   myScaleDraw->setInterval( lowerBound, upperBound);
3388
3389   // For each system, stock the position of the X's ticks and those of the name
3390   myScaleDraw->setTicks( allTicks);  // do not draw the ticks
3391
3392   // Memorize the X axis in the drawing zone
3393   setAxisScaleDraw( QwtPlot::xBottom, myScaleDraw);  // heritage of QwtPlot
3394
3395   //std::cout << "Plot2d_Plot2d::displayXTicksAndLabels() 1" << std::endl;
3396 }
3397
3398
3399 /* Create vertical segment between two curves
3400  */
3401 void Plot2d_Plot2d::createSeparationLine( double Xpos)
3402 {
3403   QwtPlotMarker* aPlotMarker = new QwtPlotMarker();
3404
3405   aPlotMarker->setLineStyle( QwtPlotMarker::VLine);
3406   aPlotMarker->setXValue( Xpos);
3407   aPlotMarker->setLinePen( QPen(Qt::black));
3408   aPlotMarker->attach(this);  // Add to drawing zone
3409   // To deallocate in EraseAll()
3410   mySeparationLineList.append( aPlotMarker);
3411 }
3412
3413 void Plot2d_Plot2d::clearSeparationLineList()
3414 {
3415   mySeparationLineList.clear();
3416 }
3417
3418 /* Set type of legend symbol
3419  */
3420 void Plot2d_Plot2d::setLegendSymbolType( const int type )
3421 {
3422   myLegendSymbolType = type;
3423 }
3424
3425 /* Get type of legend symbol
3426  */
3427 int Plot2d_Plot2d::getLegendSymbolType()
3428 {
3429   return myLegendSymbolType;
3430 }
3431
3432 /*!
3433   Creates presentation of object
3434   Default implementation is empty
3435 */
3436 Plot2d_Prs* Plot2d_ViewFrame::CreatePrs( const char* /*entry*/ )
3437 {
3438   return 0;
3439 }
3440
3441 /*!
3442   Copies preferences from other viewframe
3443   \param vf - other view frame
3444 */
3445 void Plot2d_ViewFrame::copyPreferences( Plot2d_ViewFrame* vf )
3446 {
3447   if( !vf )
3448     return;
3449
3450   myCurveType = vf->myCurveType;
3451   myShowLegend = vf->myShowLegend;
3452   myLegendPos = vf->myLegendPos;
3453   myLegendSymbolType = vf->myLegendSymbolType;
3454   myLegendFont = vf->myLegendFont;
3455   mySelectedLegendFontColor = vf->mySelectedLegendFontColor;
3456   myMarkerSize = vf->myMarkerSize;
3457   myBackground = vf->myBackground;
3458   mySelectionColor = vf->mySelectionColor;
3459   myTitle = vf->myTitle;
3460   myXTitle = vf->myXTitle;
3461   myYTitle = vf->myYTitle;
3462   myY2Title = vf->myY2Title;
3463   myTitleEnabled = vf->myTitleEnabled;
3464   myXTitleEnabled = vf->myXTitleEnabled;
3465   myYTitleEnabled = vf->myYTitleEnabled;
3466   myY2TitleEnabled = vf->myY2TitleEnabled;
3467   myXGridMajorEnabled = vf->myXGridMajorEnabled;
3468   myYGridMajorEnabled = vf->myYGridMajorEnabled;
3469   myY2GridMajorEnabled = vf->myY2GridMajorEnabled;
3470   myXGridMinorEnabled = vf->myXGridMinorEnabled;
3471   myYGridMinorEnabled = vf->myYGridMinorEnabled;
3472   myY2GridMinorEnabled = vf->myY2GridMinorEnabled;
3473   myXGridMaxMajor = vf->myXGridMaxMajor;
3474   myYGridMaxMajor = vf->myYGridMaxMajor;
3475   myY2GridMaxMajor = vf->myY2GridMaxMajor;
3476   myXGridMaxMinor = vf->myXGridMaxMinor;
3477   myYGridMaxMinor = vf->myYGridMaxMinor;
3478   myY2GridMaxMinor = vf->myY2GridMaxMinor;
3479   myXMode = vf->myXMode;
3480   myYMode = vf->myYMode;
3481   mySecondY = vf->mySecondY;
3482 }
3483
3484 /*!
3485   Updates titles according to curves
3486 */
3487 #define BRACKETIZE(x) QString( "[ " ) + x + QString( " ]" )
3488 void Plot2d_ViewFrame::updateTitles( const bool update )
3489 {
3490   ObjectDict::iterator it = myObjects.begin();
3491   QStringList aXTitles;
3492   QStringList aYTitles;
3493   QStringList aY2Titles;
3494   QStringList aXUnits;
3495   QStringList aYUnits;
3496   QStringList aY2Units;
3497   QStringList aTables;
3498   int i = 0;
3499
3500   Plot2d_Object* anObject;
3501   for ( ; it != myObjects.end(); it++ ) {
3502     // collect titles and units from all curves...
3503     anObject = it.value();
3504     QString xTitle = anObject->getHorTitle().trimmed();
3505     QString yTitle = anObject->getVerTitle().trimmed();
3506     QString xUnits = anObject->getHorUnits().trimmed();
3507     QString yUnits = anObject->getVerUnits().trimmed();
3508
3509     if ( anObject->getYAxis() == QwtPlot::yLeft ) {
3510       if ( !aYTitles.contains( yTitle ) )
3511         aYTitles.append( yTitle );
3512       if ( !aYUnits.contains( yUnits ) )
3513         aYUnits.append( yUnits );
3514     }
3515     else {
3516       if ( !aY2Titles.contains( yTitle ) )
3517         aY2Titles.append( yTitle );
3518       if ( !aY2Units.contains( yUnits ) )
3519         aY2Units.append( yUnits );
3520     }
3521     if ( !aXTitles.contains( xTitle ) )
3522       aXTitles.append( xTitle );
3523     if ( !aXUnits.contains( xUnits ) )
3524       aXUnits.append( xUnits );
3525
3526     QString aName = anObject->getTableTitle();
3527     if( !aName.isEmpty() && !aTables.contains( aName ) )
3528       aTables.append( aName );
3529     ++i;
3530   }
3531   // ... and update plot 2d view
3532   QString xUnits, yUnits, y2Units;
3533   if ( aXUnits.count() == 1 && !aXUnits[0].isEmpty() )
3534     xUnits = BRACKETIZE( aXUnits[0] );
3535   if ( aYUnits.count() == 1 && !aYUnits[0].isEmpty())
3536     yUnits = BRACKETIZE( aYUnits[0] );
3537   if ( aY2Units.count() == 1 && !aY2Units[0].isEmpty())
3538     y2Units = BRACKETIZE( aY2Units[0] );
3539   QString xTitle, yTitle, y2Title;
3540   if ( aXTitles.count() == 1 && aXUnits.count() == 1 )
3541     xTitle = aXTitles[0];
3542   if ( aYTitles.count() == 1 )
3543     yTitle = aYTitles[0];
3544   if ( mySecondY && aY2Titles.count() == 1 )
3545     y2Title = aY2Titles[0];
3546
3547   if ( !xTitle.isEmpty() && !xUnits.isEmpty() )
3548     xTitle += " ";
3549   if ( !yTitle.isEmpty() && !yUnits.isEmpty() )
3550     yTitle += " ";
3551   if ( !y2Title.isEmpty() && !y2Units.isEmpty() )
3552     y2Title += " ";
3553
3554   setTitle( myXTitleEnabled, xTitle + xUnits, XTitle, false );
3555   setTitle( myYTitleEnabled, yTitle + yUnits, YTitle, false );
3556   if ( mySecondY )
3557     setTitle( myY2TitleEnabled, y2Title + y2Units, Y2Title, false );
3558   if( myIsDefTitle )
3559     setTitle( true, aTables.join("; "), MainTitle, false );
3560
3561   // do update if necessary
3562   if ( update ) {
3563     myPlot->replot();
3564   }
3565 }
3566
3567 /*!
3568   Outputs content of viewframe to file
3569   \param file - file name
3570   \param format - file format
3571 */
3572 bool Plot2d_ViewFrame::print( const QString& file, const QString& format ) const
3573 {
3574 #ifdef WIN32
3575   return false;
3576
3577 #else
3578   bool res = false;
3579   if( myPlot )
3580   {
3581     QPaintDevice* pd = 0;
3582     if( format=="PS" || format=="EPS" || format == "PDF" )
3583     {
3584       QPrinter* pr = new QPrinter( QPrinter::HighResolution );
3585       if(format == "PDF")
3586           pr->setOutputFormat(QPrinter::PdfFormat);
3587       pr->setPageSize( QPrinter::A4 );
3588       pr->setOutputFileName( file );
3589       pr->setPrintProgram( "" );
3590       pd = pr;
3591     }
3592
3593     if( pd )
3594     {
3595       QwtPlotRenderer* pr = new QwtPlotRenderer();
3596       pr->renderTo( myPlot, *pd );
3597       res = true;
3598       delete pd;
3599     }
3600   }
3601   return res;
3602 #endif
3603
3604 }
3605
3606 /**
3607  * Print Plot2d window
3608  */
3609 void Plot2d_ViewFrame::printPlot( QPainter* p, const QRectF& rect) const
3610 {
3611   QwtPlotRenderer* pr = new QwtPlotRenderer();
3612   pr->render( myPlot, p, rect );
3613 }
3614
3615 /*!
3616   \return string with all visual parameters
3617 */
3618 QString Plot2d_ViewFrame::getVisualParameters()
3619 {
3620
3621   return getXmlVisualParameters();
3622
3623   /*
3624   RNV: Old case, now visual parameters stored in the XML format.
3625   //
3626   double xmin, xmax, ymin, ymax, y2min, y2max;
3627   getFitRanges( xmin, xmax, ymin, ymax, y2min, y2max );
3628   QString retStr;
3629   //Store font in the visual parameters string as:
3630   //
3631   // ...*FontFamily|FontSize|B|I|U|r:g:b*...
3632
3633   retStr.sprintf( "%d*%d*%d*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%s|%i|%i|%i|%i|%i:%i:%i",
3634                   myXMode, myYMode, mySecondY, xmin, xmax, ymin, ymax, y2min, y2max,
3635                   qPrintable(myLegendFont.family()), myLegendFont.pointSize(),myLegendFont.bold(),
3636                   myLegendFont.italic(), myLegendFont.underline(),myLegendColor.red(),
3637                   myLegendColor.green(), myLegendColor.blue());
3638
3639  //store all Analytical curves
3640   //store each curve in the following format
3641   // ...*Name|isActive|Expresion|NbInervals|isAutoAssign[|MarkerType|LineType|LineWidth|r:g:b]
3642   // parameters in the [ ] is optional in case if isAutoAssign == true
3643   AnalyticalCurveList::iterator it = myAnalyticalCurves.begin();
3644   Plot2d_AnalyticalCurve* c = 0;
3645   bool isAuto;
3646   for( ; it != myAnalyticalCurves.end(); it++) {
3647     c = (*it);
3648     if(!c) continue;
3649     QString curveString("");
3650     isAuto = c->isAutoAssign();
3651     curveString.sprintf("*%s|%i|%s|%i|%i",
3652                         qPrintable(c->getName()),
3653                         c->isActive(),
3654                         qPrintable(c->getExpression()),
3655                         c->getNbIntervals(),
3656                         isAuto);
3657
3658     retStr+=curveString;
3659     if(!isAuto) {
3660       QString optCurveString("");
3661       optCurveString.sprintf("|%i|%i|%i|%i:%i:%i",
3662                              (int)c->getMarker(),
3663                              (int)c->getLine(),
3664                              c->getLineWidth(),
3665                              c->getColor().red(),
3666                              c->getColor().green(),
3667                              c->getColor().blue());
3668       retStr+=optCurveString;
3669     }
3670   }
3671   retStr += QString( "*%1" ).arg( Qtx::colorToString( backgroundColor() ) );
3672   return retStr;
3673   */
3674 }
3675
3676 /*!
3677   Restores all visual parameters from string
3678 */
3679 void Plot2d_ViewFrame::setVisualParameters( const QString& parameters )
3680 {
3681   if(setXmlVisualParameters(parameters))
3682     return;
3683
3684   double xmin, xmax;
3685   QStringList paramsLst = parameters.split( '*' );
3686   if ( paramsLst.size() >= 9 ) {
3687     double ymin, ymax, y2min, y2max;
3688     myXMode = paramsLst[0].toInt();
3689     myYMode = paramsLst[1].toInt();
3690     mySecondY = (bool)paramsLst[2].toInt();
3691     xmin =  paramsLst[3].toDouble();
3692     xmax =  paramsLst[4].toDouble();
3693     ymin =  paramsLst[5].toDouble();
3694     ymax =  paramsLst[6].toDouble();
3695     y2min = paramsLst[7].toDouble();
3696     y2max = paramsLst[8].toDouble();
3697
3698     if (mySecondY)
3699       setTitle( myY2TitleEnabled, myY2Title, Y2Title, false );
3700     setHorScaleMode( myXMode, /*update=*/false );
3701     setVerScaleMode( myYMode, /*update=*/false );
3702
3703     if (mySecondY) {
3704       QwtScaleMap yMap2 = myPlot->canvasMap( QwtPlot::yRight );
3705       myYDistance2 = yMap2.s2() - yMap2.s1();
3706     }
3707
3708     fitData( 0, xmin, xmax, ymin, ymax, y2min, y2max );
3709     fitData( 0, xmin, xmax, ymin, ymax, y2min, y2max );
3710   }
3711
3712   //Restore legend font
3713   if(paramsLst.size() >= 10) {
3714     QStringList fontList = paramsLst[9].split( '|' );
3715     if(fontList.size() == 6) {
3716       myLegendFont = QFont(fontList[0]);
3717       myLegendFont.setPointSize(fontList[1].toInt());
3718       myLegendFont.setBold(fontList[2].toInt());
3719       myLegendFont.setItalic(fontList[3].toInt());
3720       myLegendFont.setUnderline(fontList[4].toInt());
3721       QStringList colorList = fontList[5].split(":");
3722       setLegendFont( myLegendFont );
3723
3724       if(colorList.size() == 3) {
3725               myLegendColor = QColor(colorList[0].toInt(),
3726                                                  colorList[1].toInt(),
3727                                                  colorList[2].toInt());
3728               setLegendFontColor( myLegendColor );
3729       }
3730     }
3731   }
3732
3733 #ifndef NO_ANALYTICAL_CURVES
3734   //Restore all Analytical curves
3735   int startCurveIndex = 10;
3736   if( paramsLst.size() >= startCurveIndex+1 ) {
3737     for( int i=startCurveIndex; i<paramsLst.size() ; i++ ) {
3738       QStringList curveLst = paramsLst[i].split("|");
3739       if( curveLst.size() == 5 || curveLst.size() == 9 ) {
3740         Plot2d_AnalyticalCurve* c = new Plot2d_AnalyticalCurve();
3741         c->setName(curveLst[0]);
3742         c->setActive(curveLst[1].toInt());
3743         c->setExpression(curveLst[2]);
3744         c->setNbIntervals(curveLst[3].toLong());
3745         c->setAutoAssign(curveLst[4].toInt());
3746         if( !c->isAutoAssign() ) {
3747           c->setMarker((Plot2d::MarkerType)curveLst[5].toInt());
3748           c->setLine((Plot2d::LineType)curveLst[6].toInt());
3749           c->setLineWidth(curveLst[7].toInt());
3750           QStringList colorList = curveLst[8].split(":");
3751           if( colorList.size() == 3 ) {
3752             c->setColor(QColor(colorList[0].toInt(),
3753                                colorList[1].toInt(),
3754                                colorList[2].toInt()));
3755           }
3756         } else {
3757           c->autoFill( myPlot );
3758         }
3759         addAnalyticalCurve(c);
3760         updateAnalyticalCurve(c);
3761       }
3762       else if( curveLst.size() == 1 ) {
3763         // background color can be set here
3764         QColor c;
3765         if ( Qtx::stringToColor( paramsLst[i], c ) )
3766           setBackgroundColor( c );
3767       }
3768     }
3769     myPlot->replot();
3770   }
3771 #endif
3772 }
3773
3774 /*!
3775   Store visual parameters in xml format.
3776 */
3777 QString Plot2d_ViewFrame::getXmlVisualParameters() {
3778   QString retStr;
3779   QXmlStreamWriter aWriter(&retStr);
3780   aWriter.setAutoFormatting(true);
3781
3782   //Ranges
3783   aWriter.writeStartDocument();
3784   aWriter.writeStartElement("ViewState");
3785   aWriter.writeStartElement("Range");
3786   double xmin, xmax, ymin, ymax, y2min, y2max;
3787   getFitRanges( xmin, xmax, ymin, ymax, y2min, y2max );
3788   aWriter.writeAttribute("Xmin", QString("").sprintf("%.12e",xmin));
3789   aWriter.writeAttribute("Xmax", QString("").sprintf("%.12e",xmax));
3790   aWriter.writeAttribute("Ymin", QString("").sprintf("%.12e",ymin));
3791   aWriter.writeAttribute("Ymax", QString("").sprintf("%.12e",ymax));
3792   aWriter.writeAttribute("Y2min", QString("").sprintf("%.12e",y2min));
3793   aWriter.writeAttribute("Y2max", QString("").sprintf("%.12e",y2max));
3794   aWriter.writeEndElement();
3795
3796   //Display mode
3797   aWriter.writeStartElement("DisplayMode");
3798   aWriter.writeAttribute("SecondAxis", QString("").sprintf("%d",mySecondY));
3799   aWriter.writeStartElement("ScaleMode");
3800   aWriter.writeAttribute("Xscale", QString("").sprintf("%d",myXMode));
3801   aWriter.writeAttribute("Yscale", QString("").sprintf("%d",myYMode));
3802   aWriter.writeEndElement();
3803   aWriter.writeStartElement("NormalizationMode");
3804   aWriter.writeAttribute("LeftMin", QString("").sprintf("%d",myNormLMin));
3805   aWriter.writeAttribute("LeftMax", QString("").sprintf("%d",myNormLMax));
3806   aWriter.writeAttribute("RightMin", QString("").sprintf("%d",myNormRMin));
3807   aWriter.writeAttribute("RightMax", QString("").sprintf("%d",myNormRMax));
3808   aWriter.writeEndElement();
3809   aWriter.writeEndElement();
3810
3811   //Legend
3812   aWriter.writeStartElement("Legend");
3813   aWriter.writeAttribute("Visibility", QString("").sprintf("%d", myShowLegend));
3814   aWriter.writeStartElement("LegendFont");
3815   aWriter.writeAttribute("Family", myLegendFont.family());
3816   aWriter.writeAttribute("Size", QString("").sprintf("%d",myLegendFont.pointSize()));
3817   aWriter.writeAttribute("Bold", QString("").sprintf("%d",myLegendFont.bold()));
3818   aWriter.writeAttribute("Italic", QString("").sprintf("%d",myLegendFont.italic()));
3819   aWriter.writeAttribute("Underline", QString("").sprintf("%d",myLegendFont.underline()));
3820   aWriter.writeAttribute("R", QString("").sprintf("%d",myLegendColor.red()));
3821   aWriter.writeAttribute("G", QString("").sprintf("%d",myLegendColor.green()));
3822   aWriter.writeAttribute("B", QString("").sprintf("%d",myLegendColor.blue()));
3823   aWriter.writeEndElement();
3824   aWriter.writeEndElement();
3825
3826 #ifndef NO_ANALYTICAL_CURVES
3827   //AnalyticalCurve
3828   aWriter.writeStartElement("AnalyticalCurves");
3829   AnalyticalCurveList::iterator it = myAnalyticalCurves.begin();
3830   Plot2d_AnalyticalCurve* c = 0;
3831   bool isAuto;
3832   int id = 1;
3833   for( ; it != myAnalyticalCurves.end(); it++) {
3834     c = (*it);
3835     if(!c) continue;
3836     aWriter.writeStartElement(QString("AnalyticalCurve_%1").arg(id));
3837     isAuto = c->isAutoAssign();
3838     aWriter.writeAttribute("Name",c->getName());
3839     aWriter.writeAttribute("IsActive", QString("").sprintf("%d",        c->isActive()));
3840                 aWriter.writeAttribute("Expression", c->getExpression());
3841     aWriter.writeAttribute("NbIntervals", QString("").sprintf("%ld",    c->getNbIntervals()));
3842     aWriter.writeAttribute("isAuto", QString("").sprintf("%d",isAuto));
3843     if(!isAuto) {
3844       aWriter.writeAttribute("Marker", QString("").sprintf("%d",(int)c->getMarker()));
3845       aWriter.writeAttribute("Line", QString("").sprintf("%d",(int)c->getLine()));
3846       aWriter.writeAttribute("LineWidth", QString("").sprintf("%d",c->getLineWidth()));
3847       aWriter.writeAttribute("R", QString("").sprintf("%d",c->getColor().red()));
3848       aWriter.writeAttribute("G", QString("").sprintf("%d",c->getColor().green()));
3849       aWriter.writeAttribute("B", QString("").sprintf("%d",c->getColor().blue()));
3850     }
3851     aWriter.writeEndElement();
3852     id++;
3853   }
3854   aWriter.writeEndElement(); //AnalyticalCurve
3855 #endif
3856
3857   //Background
3858   aWriter.writeStartElement(QString("Background"));
3859   aWriter.writeStartElement(QString("BackgroundColor"));
3860   aWriter.writeAttribute("R", QString("").sprintf("%d",backgroundColor().red()));
3861   aWriter.writeAttribute("G", QString("").sprintf("%d",backgroundColor().green()));
3862   aWriter.writeAttribute("B", QString("").sprintf("%d",backgroundColor().blue()));
3863   aWriter.writeEndElement();
3864   aWriter.writeEndElement();
3865
3866
3867   aWriter.writeEndDocument();
3868   return retStr;
3869 }
3870 /*!
3871   Restore visual parameters from xml format.
3872 */
3873 bool Plot2d_ViewFrame::setXmlVisualParameters(const QString& parameters) {
3874   QXmlStreamReader aReader(parameters);
3875   double xmin = 0., xmax = 0., ymin = 0., ymax = 0., y2min = 0., y2max = 0.;
3876   bool leftMin,leftMax,rightMin,rightMax;
3877   leftMin = leftMax = rightMin = rightMax = false;
3878   while(!aReader.atEnd()) {
3879       aReader.readNext();
3880       if (aReader.isStartElement()) {
3881       QXmlStreamAttributes aAttr = aReader.attributes();
3882         if(aReader.name() == "Range") {
3883           xmin = aAttr.value("Xmin").toString().toDouble();
3884           xmax = aAttr.value("Xmax").toString().toDouble();
3885           ymin = aAttr.value("Ymin").toString().toDouble();
3886           ymax = aAttr.value("Ymax").toString().toDouble();
3887           y2min = aAttr.value("Y2min").toString().toDouble();
3888           y2max = aAttr.value("Y2max").toString().toDouble();
3889         } else if(aReader.name() == "DisplayMode") {
3890           mySecondY = aAttr.value("Y2max").toString().toDouble();
3891         } else if(aReader.name() == "ScaleMode") {
3892            myXMode = aAttr.value("Xscale").toString().toInt();
3893            myYMode = aAttr.value("Yscale").toString().toInt();
3894         } else if(aReader.name() == "NormalizationMode") {
3895             leftMin = (bool)aAttr.value("LeftMin").toString().toInt();
3896             leftMax = (bool)aAttr.value("LeftMax").toString().toInt();
3897             rightMin = (bool)aAttr.value("RightMin").toString().toInt();
3898             rightMax = (bool)aAttr.value("RightMax").toString().toInt();
3899         } else if(aReader.name() == "Legend") {
3900           myShowLegend = (bool)aAttr.value("Visibility").toString().toInt();
3901         } else if (aReader.name() == "LegendFont") {
3902             myLegendFont = QFont(aAttr.value("Family").toString());
3903             myLegendFont.setPointSize(aAttr.value("Size").toString().toInt());
3904             myLegendFont.setBold((bool)aAttr.value("Bold").toString().toInt());
3905             myLegendFont.setItalic((bool)aAttr.value("Italic").toString().toInt());
3906             myLegendFont.setUnderline((bool)aAttr.value("Underline").toString().toInt());
3907               myLegendColor = QColor(aAttr.value("R").toString().toInt(),
3908                                                      aAttr.value("G").toString().toInt(),
3909                                                      aAttr.value("B").toString().toInt());
3910                   setLegendFontColor( myLegendColor );
3911             setLegendFont(myLegendFont);
3912         } else if(aReader.name().toString().indexOf("AnalyticalCurve_") >= 0) {
3913 #ifndef NO_ANALYTICAL_CURVES
3914             Plot2d_AnalyticalCurve* c = new Plot2d_AnalyticalCurve();
3915                   c->setName(aAttr.value("Name").toString());
3916                   c->setActive((bool)aAttr.value("IsActive").toString().toInt());
3917                   c->setExpression(aAttr.value("Expression").toString());
3918                   c->setNbIntervals(aAttr.value("NbIntervals").toString().toLong());
3919                   c->setAutoAssign((bool)aAttr.value("isAuto").toString().toInt());
3920                   if( !c->isAutoAssign() ) {
3921                     c->setMarker((Plot2d::MarkerType)aAttr.value("Marker").toString().toInt());
3922                     c->setLine((Plot2d::LineType)aAttr.value("Line").toString().toInt());
3923                     c->setLineWidth(aAttr.value("LineWidth").toString().toInt());
3924                     c->setColor(QColor(aAttr.value("R").toString().toInt(),
3925                                                    aAttr.value("G").toString().toInt(),
3926                                                    aAttr.value("B").toString().toInt()));
3927             } else {
3928                     c->autoFill( myPlot );
3929                   }
3930                   addAnalyticalCurve(c);
3931                   updateAnalyticalCurve(c);
3932 #endif
3933         } else if(aReader.name().toString() == "BackgroundColor") {
3934           setBackgroundColor(QColor(aAttr.value("R").toString().toInt(),
3935                                                       aAttr.value("G").toString().toInt(),
3936                                                       aAttr.value("B").toString().toInt()));
3937         }
3938       }
3939   }
3940
3941   if(aReader.hasError())
3942     return false;
3943
3944   if (mySecondY)
3945     setTitle( myY2TitleEnabled, myY2Title, Y2Title, false );
3946   setHorScaleMode( myXMode, /*update=*/false );
3947   setVerScaleMode( myYMode, /*update=*/false );
3948   if (mySecondY) {
3949     QwtScaleMap yMap2 = myPlot->canvasMap( QwtPlot::yRight );
3950     myYDistance2 = yMap2.s2() - yMap2.s1();
3951   }
3952   setNormLMinMode(leftMin);
3953   setNormLMaxMode(leftMax);
3954   setNormRMinMode(rightMin);
3955   setNormRMaxMode(rightMax);
3956
3957   showLegend( myShowLegend, false );
3958
3959   fitData( 0, xmin, xmax, ymin, ymax, y2min, y2max );
3960   return true;
3961 }
3962
3963 /*!
3964   Incremental zooming operation
3965 */
3966 void Plot2d_ViewFrame::incrementalPan( const int incrX, const int incrY ) {
3967   QwtScaleMap xMap = myPlot->canvasMap( QwtPlot::xBottom );
3968   QwtScaleMap yMap = myPlot->canvasMap( QwtPlot::yLeft );
3969
3970   myPlot->setAxisScale( QwtPlot::yLeft,
3971                         myPlot->invTransform( QwtPlot::yLeft, yMap.transform( yMap.s1() )-incrY ),
3972                         myPlot->invTransform( QwtPlot::yLeft, yMap.transform( yMap.s2() )-incrY ) );
3973   myPlot->setAxisScale( QwtPlot::xBottom,
3974                         myPlot->invTransform( QwtPlot::xBottom, xMap.transform( xMap.s1() )-incrX ),
3975                         myPlot->invTransform( QwtPlot::xBottom, xMap.transform( xMap.s2() )-incrX ) );
3976   if (mySecondY) {
3977     QwtScaleMap y2Map = myPlot->canvasMap( QwtPlot::yRight );
3978     myPlot->setAxisScale( QwtPlot::yRight,
3979                           myPlot->invTransform( QwtPlot::yRight, y2Map.transform( y2Map.s1() )-incrY ),
3980                           myPlot->invTransform( QwtPlot::yRight, y2Map.transform( y2Map.s2() )-incrY ) );
3981   }
3982   myPlot->replot();
3983 }
3984
3985 /*!
3986   Incremental panning operation
3987 */
3988 void Plot2d_ViewFrame::incrementalZoom( const int incrX, const int incrY ) {
3989   QwtScaleMap xMap = myPlot->canvasMap( QwtPlot::xBottom );
3990   QwtScaleMap yMap = myPlot->canvasMap( QwtPlot::yLeft );
3991
3992   myPlot->setAxisScale( QwtPlot::yLeft, yMap.s1(),
3993                         myPlot->invTransform( QwtPlot::yLeft, yMap.transform( yMap.s2() ) + incrY ) );
3994   myPlot->setAxisScale( QwtPlot::xBottom, xMap.s1(),
3995                         myPlot->invTransform( QwtPlot::xBottom, xMap.transform( xMap.s2() ) - incrX ) );
3996   if (mySecondY) {
3997     QwtScaleMap y2Map = myPlot->canvasMap( QwtPlot::yRight );
3998     myPlot->setAxisScale( QwtPlot::yRight, y2Map.s1(),
3999                           myPlot->invTransform( QwtPlot::yRight, y2Map.transform( y2Map.s2() ) + incrY ) );
4000   }
4001   myPlot->replot();
4002 }
4003
4004 /*
4005   Update plot item
4006 */
4007 void Plot2d_ViewFrame::updatePlotItem(Plot2d_Object* theObject, QwtPlotItem* theItem) {
4008   theObject->updatePlotItem( theItem );
4009   Plot2d_Curve* c = dynamic_cast<Plot2d_Curve*>(theObject);
4010   QwtPlotCurve* cu = dynamic_cast<QwtPlotCurve*>(theItem);
4011   Plot2d_NormalizeAlgorithm* aNormAlgo;
4012   if(c && cu) {
4013     if(c->getYAxis() == QwtPlot::yRight)
4014       aNormAlgo = myRNormAlgo;
4015     else
4016       aNormAlgo = myLNormAlgo;
4017     if(aNormAlgo->getNormalizationMode() != Plot2d_NormalizeAlgorithm::NormalizeNone) {
4018       AlgoPlot2dOutputData aResultData =  aNormAlgo->getOutput();
4019       AlgoPlot2dOutputData::iterator itTmp = aResultData.find(theObject);
4020       double *xNew,*yNew;
4021       int size = itTmp.value().size();
4022       xNew = new double[size];
4023       yNew = new double[size];
4024       int j = 0;
4025       for (; j < size; ++j) {
4026         xNew[j] = itTmp.value().at(j).first;
4027         yNew[j] = itTmp.value().at(j).second;
4028       }
4029       cu->setSamples(xNew, yNew,j);
4030       delete [] xNew;
4031       delete [] yNew;
4032       if(aNormAlgo->getNormalizationMode() != Plot2d_NormalizeAlgorithm::NormalizeNone) {
4033         QString name = c->getName().isEmpty() ? c->getVerTitle() : c->getName();
4034         name = name + QString("(B=%1, K=%2)");
4035         name = name.arg(aNormAlgo->getBkoef(c)).arg(aNormAlgo->getKkoef(c));
4036         cu->setTitle(name);
4037       }
4038     }
4039   }
4040 }
4041
4042 /**
4043  *
4044  */
4045 QwtPlotCanvas* Plot2d_ViewFrame::getPlotCanvas() const
4046 {
4047   return myPlot ? (QwtPlotCanvas*)myPlot->canvas() : 0;
4048 }
4049
4050 /*!
4051   return closest curve if it exist, else 0
4052 */
4053 Plot2d_Curve* Plot2d_ViewFrame::getClosestCurve( QPoint p, double& distance, int& index ) const
4054 {
4055   CurveDict aCurves = getCurves();
4056   CurveDict::iterator it = aCurves.begin();
4057   Plot2d_Curve* pCurve = 0;
4058   distance = -1.;
4059   for ( ; it != aCurves.end(); it++ ) {
4060     QwtPlotCurve* aCurve = it.key();
4061     if ( !aCurve )
4062       continue;
4063     double d;
4064     int i = aCurve->closestPoint( p, &d );
4065     if ( i > -1 && ( distance < 0 || d < distance ) ) {
4066       pCurve = it.value();
4067       distance = d;
4068       index = i;
4069     }
4070   }
4071   return pCurve;
4072 }
4073
4074 #ifndef NO_ANALYTICAL_CURVES
4075 /*!
4076  \brief  Deselect all analytical curves.
4077 */
4078 void Plot2d_ViewFrame::deselectAnalyticalCurves() {
4079   foreach(Plot2d_AnalyticalCurve* c, myAnalyticalCurves) {
4080    c->setSelected(false);
4081   }
4082 }
4083 #endif
4084
4085 /*!
4086  \brief  Deselect all objects, except analytical curves.
4087 */
4088 void Plot2d_ViewFrame::deselectObjects() {
4089   ObjectDict::const_iterator it = myObjects.begin(), aLast = myObjects.end();
4090   for ( ; it != aLast; it++ ) {
4091           it.value()->setSelected(false);
4092    }
4093 }
4094
4095 #define INCREMENT_FOR_OP 10
4096
4097 /*!
4098   Performs incremental panning to the left
4099 */
4100 void Plot2d_ViewFrame::onPanLeft()
4101 {
4102   this->incrementalPan( -INCREMENT_FOR_OP, 0 );
4103 #ifndef NO_ANALYTICAL_CURVES
4104   updateAnalyticalCurves();
4105 #endif
4106 }
4107
4108 /*!
4109   Performs incremental panning to the right
4110 */
4111 void Plot2d_ViewFrame::onPanRight()
4112 {
4113   this->incrementalPan( INCREMENT_FOR_OP, 0 );
4114 #ifndef NO_ANALYTICAL_CURVES
4115   updateAnalyticalCurves();
4116 #endif
4117 }
4118
4119 /*!
4120   Performs incremental panning to the top
4121 */
4122 void Plot2d_ViewFrame::onPanUp()
4123 {
4124   this->incrementalPan( 0, -INCREMENT_FOR_OP );
4125 #ifndef NO_ANALYTICAL_CURVES
4126   updateAnalyticalCurves();
4127 #endif
4128 }
4129
4130 /*!
4131   Performs incremental panning to the bottom
4132 */
4133 void Plot2d_ViewFrame::onPanDown()
4134 {
4135   this->incrementalPan( 0, INCREMENT_FOR_OP );
4136 #ifndef NO_ANALYTICAL_CURVES
4137   updateAnalyticalCurves();
4138 #endif
4139 }
4140
4141 /*!
4142   Performs incremental zooming in
4143 */
4144 void Plot2d_ViewFrame::onZoomIn()
4145 {
4146   this->incrementalZoom( INCREMENT_FOR_OP, INCREMENT_FOR_OP );
4147 #ifndef NO_ANALYTICAL_CURVES
4148   updateAnalyticalCurves();
4149 #endif
4150 }
4151
4152 /*!
4153   Performs incremental zooming out
4154 */
4155 void Plot2d_ViewFrame::onZoomOut()
4156 {
4157   this->incrementalZoom( -INCREMENT_FOR_OP, -INCREMENT_FOR_OP );
4158 #ifndef NO_ANALYTICAL_CURVES
4159   updateAnalyticalCurves();
4160 #endif
4161 }
4162
4163 /*!
4164   Schedules a FitAll operation by putting it to the application's
4165   event queue. This ensures that other important events (show, resize, etc.)
4166   are processed first.
4167 */
4168 void Plot2d_ViewFrame::customEvent( QEvent* ce )
4169 {
4170   if ( ce->type() == FITALL_EVENT )
4171     fitAll();
4172 }
4173
4174
4175 /*!
4176  * Return Plot2d_Object by the QwtPlotItem
4177  *
4178 */
4179 Plot2d_Object* Plot2d_ViewFrame::getPlotObject( QwtPlotItem* plotItem ) const {
4180
4181   ObjectDict::const_iterator it = myObjects.begin();
4182   for( ; it != myObjects.end(); ++it ) {
4183     if ( it.key() == plotItem ) {
4184       return it.value();
4185     }
4186   }
4187   return 0;
4188 }
4189
4190 Plot2d_ScaleDraw::Plot2d_ScaleDraw( char f, int prec )
4191   : QwtScaleDraw(),
4192     myFormat(f),
4193     myPrecision(prec)
4194 {
4195   invalidateCache();
4196 }
4197
4198 QwtText Plot2d_ScaleDraw::label( double value ) const
4199 {
4200   QwtScaleMap m = scaleMap();
4201   QString str1 = QwtScaleDraw::label( m.s1() ).text();
4202   QString str2 = QwtScaleDraw::label( m.s2() ).text();
4203   if ( str1 == str2 ) {
4204     double aDist = fabs(scaleMap().s2()-scaleMap().s1())/5;
4205     int precision = 0;
4206     while (aDist < 1 ) {
4207       precision++;
4208       aDist *= 10.;
4209     }
4210     if ( precision > 0 && value > 0 )
4211       return QLocale::system().toString( value,'f', precision );
4212   }
4213
4214   return QwtScaleDraw::label( value );
4215 }
4216
4217 Plot2d_YScaleDraw::Plot2d_YScaleDraw()
4218   : QwtScaleDraw()
4219 {
4220 }
4221
4222 QwtText Plot2d_YScaleDraw::label( double value ) const
4223 {
4224   // Axis labels format
4225   QString strD = QString( "%1").arg( value, 10, 'e', 3); // format 10.3e
4226
4227   return QwtText( strD);
4228 }
4229
4230 /* Definition of X axis graduations
4231  */
4232 const QString Plot2d_AxisScaleDraw::DEVICE_FONT = QString("Times");
4233 const int     Plot2d_AxisScaleDraw::DEVICE_FONT_SIZE = 12;
4234 const int     Plot2d_AxisScaleDraw::DEVICE_BY = 40;
4235
4236 Plot2d_AxisScaleDraw::Plot2d_AxisScaleDraw( Plot2d_Plot2d* plot)
4237 : myPlot(plot)
4238 {
4239   myLowerBound = -1;
4240   myUpperBound = -1;
4241   setLabelAlignment(Qt::AlignRight);
4242   setLabelRotation(45.);
4243
4244   applyTicks();
4245
4246   myActivTicksDrawing   = true;
4247   myNumTicksDrawingCall = 1;
4248 }
4249
4250
4251 Plot2d_AxisScaleDraw::~Plot2d_AxisScaleDraw()
4252 {
4253 }
4254
4255
4256 /* Unactivate automatic ticks drawing
4257  */
4258 void Plot2d_AxisScaleDraw::unactivTicksDrawing( int numcall)
4259 {
4260   myActivTicksDrawing   = false;
4261   myNumTicksDrawingCall = numcall;
4262 }
4263
4264
4265 /* Draw X ticks and labels.
4266  * Draw systems names under X axis.
4267  * Overload the same name QwtScaleDraw method.
4268  * (PB: who call automaticaly this method)
4269  */
4270 void Plot2d_AxisScaleDraw::draw( QPainter* painter, const QPalette & palette) const
4271 {
4272   //std::cout << "Plot2d_AxisScaleDraw::draw() : activ= " << myActivTicksDrawing
4273   //                           << "  numcall= " << myNumTicksDrawingCall << std::endl;
4274
4275   if (!myActivTicksDrawing)  return;
4276
4277   //std::cout << "Plot2d_AxisScaleDraw::draw()" << std::endl;
4278
4279   QList<double> major_ticks  = scaleDiv().ticks(QwtScaleDiv::MajorTick);
4280   QList<double> medium_ticks = scaleDiv().ticks(QwtScaleDiv::MediumTick);
4281   QList<double> minor_ticks  = scaleDiv().ticks(QwtScaleDiv::MinorTick);
4282
4283   medium_ticks.clear();
4284   minor_ticks.clear();
4285   major_ticks.clear();
4286
4287   major_ticks.append( myTicks);
4288
4289   QwtScaleDiv aScaleDiv = myPlot->axisScaleDiv( QwtPlot::xBottom );
4290   aScaleDiv.setTicks( QwtScaleDiv::MajorTick,  major_ticks );
4291   aScaleDiv.setTicks( QwtScaleDiv::MediumTick, medium_ticks );
4292   aScaleDiv.setTicks( QwtScaleDiv::MinorTick,  minor_ticks );
4293   myPlot->setAxisScaleDiv( QwtPlot::xBottom, aScaleDiv );
4294
4295   QwtScaleDraw *scale = myPlot->axisScaleDraw(QwtPlot::xBottom);
4296   ((Plot2d_AxisScaleDraw*)(scale))->applyTicks();
4297
4298   QwtScaleDraw::draw( painter, palette);
4299
4300   for (int i = 0; i < myTicks.size(); i++)
4301   {
4302       drawLabel( painter, myTicks[i]);
4303   }
4304
4305   //std::cout << "Ok for Plot2d_AxisScaleDraw::draw()" << std::endl;
4306 }
4307
4308
4309 double Plot2d_AxisScaleDraw::extent( const QFont &font ) const
4310 {
4311   QFontMetrics fm( font );
4312   return QwtScaleDraw::extent( font ) + fm.height() * 2;
4313 }
4314
4315 QwtText Plot2d_AxisScaleDraw::label( double value) const
4316 {
4317   if (myLabelX.contains(value))
4318           return myLabelX[value];
4319
4320   return QwtText(QString::number(value, 'f', 1));
4321 }
4322
4323
4324 /* Stock position and label of a X tick
4325  */
4326 void Plot2d_AxisScaleDraw::setLabelTick( double value, QString label, bool isDevice)
4327 {
4328   //qDebug()<< "setLabelTick ( " << value << ","<< label <<" )";
4329   if ( isDevice )
4330   {
4331       // For systems names under X axis
4332       myLabelDevice[value] = label;
4333   }
4334   else
4335   {
4336       // For X axis graduations
4337       myLabelX[value] = label;
4338   }
4339 }
4340
4341
4342 /* Stock ticks positions of a system, and draw them
4343  */
4344 void Plot2d_AxisScaleDraw::setTicks(const QList<double> aTicks)
4345 {
4346   //std::cout << "  Plot2d_AxisScaleDraw::setTicks()" << std::endl;
4347   myTicks = aTicks;
4348
4349   applyTicks();
4350 }
4351
4352
4353 void Plot2d_AxisScaleDraw::setInterval(double lowerBound, double upperBound)
4354 {
4355   myLowerBound = lowerBound;
4356   myUpperBound = upperBound;
4357   myPlot->setAxisScale( QwtPlot::xBottom, myLowerBound, myUpperBound );
4358 }
4359
4360
4361 /* Stock X ticks in drawing zone
4362  */
4363 void Plot2d_AxisScaleDraw::applyTicks()
4364 {
4365   //std::cout << "  Plot2d_AxisScaleDraw::applyTicks()" << std::endl;
4366
4367   QList<double> major_ticks = scaleDiv().ticks(QwtScaleDiv::MajorTick);
4368   QList<double> medium_ticks = scaleDiv().ticks(QwtScaleDiv::MediumTick);
4369   QList<double> minor_ticks = scaleDiv().ticks(QwtScaleDiv::MinorTick);
4370
4371   medium_ticks.clear();
4372   minor_ticks.clear();
4373
4374   QwtScaleDiv aQwtScaleDiv = myPlot->axisScaleDiv( QwtPlot::xBottom );
4375   aQwtScaleDiv.setTicks( QwtScaleDiv::MajorTick, myTicks );
4376   aQwtScaleDiv.setTicks( QwtScaleDiv::MediumTick, medium_ticks );
4377   aQwtScaleDiv.setTicks( QwtScaleDiv::MinorTick, minor_ticks );
4378   myPlot->setAxisScaleDiv( QwtPlot::xBottom, aQwtScaleDiv );
4379
4380   QwtScaleDiv* aScaleDiv = (QwtScaleDiv*) &scaleDiv();
4381
4382   aScaleDiv->setTicks(QwtScaleDiv::MajorTick, myTicks);
4383   aScaleDiv->setTicks(QwtScaleDiv::MediumTick, medium_ticks);
4384   aScaleDiv->setTicks(QwtScaleDiv::MinorTick, minor_ticks);
4385
4386   if (myLowerBound != -1 && myUpperBound != -1)
4387               aScaleDiv->setInterval(myLowerBound, myUpperBound);
4388
4389   //for (int i = 0; i < myTicks.size(); i++){
4390   //  QPoint p = labelPosition( i );
4391   //  qDebug() << i<< ") applyTicks -> LABEL" <<p;
4392   //}
4393 }
4394
4395
4396 void Plot2d_AxisScaleDraw::drawLabel( QPainter* painter, double value) const
4397 {
4398   //std::cout << "  Plot2d_AxisScaleDraw::drawLabel( " << value << " ) : "; //<< std::endl;
4399
4400   //qDebug() << "drawLabel  ( " <<value<<" )";
4401   if ( myLabelDevice.contains(value) )
4402   {
4403       QString deviceLabel = myLabelDevice[value];
4404       //
4405       std::string std_label = deviceLabel.toStdString();
4406       //const char *c_label = std_label.c_str();
4407       //std::cout << "    deviceLabel= |" << c_label << "|" << std::endl;
4408
4409       QPointF p = labelPosition( value );
4410       p += QPoint(0, DEVICE_BY);
4411       QFont  prevf = painter->font();
4412       //QColor prevc = (painter->pen()).color();
4413
4414       QFont devicef( DEVICE_FONT, DEVICE_FONT_SIZE, QFont::Bold);
4415       //
4416       //painter->setPen( QColor("blue") );
4417       painter->setFont( devicef );
4418       painter->drawText( p, myLabelDevice[value] );
4419       //painter->setPen( prevc );
4420       painter->setFont( prevf );
4421   }
4422   if ( myLabelX.contains(value) )
4423   {
4424       QString xLabel = myLabelX[value];
4425       //
4426       std::string std_label = xLabel.toStdString();
4427       //const char *c_label = std_label.c_str();
4428       //std::cout << "    xLabel= |" << c_label << "|" << std::endl;
4429
4430       QwtScaleDraw::drawLabel( painter, value );
4431   }
4432 }
4433
4434
4435 void Plot2d_AxisScaleDraw::drawTick( QPainter* painter, double value, int len) const
4436 {
4437   //qDebug() << "drawTick  ( " <<value<<" , "<<len<<" )  " ;
4438   //qDebug() << "myLabelX" << myLabelX;
4439   //
4440   if ( myLabelX.contains(value) )
4441   {
4442       QwtScaleDraw::drawTick( painter, value, len);
4443   }
4444 }
4445
4446
4447 /* Management of tooltips associated with markers for curves points or others points
4448  */
4449 const double Plot2d_QwtPlotPicker::BOUND_HV_SIZE = 0.2;
4450
4451 Plot2d_QwtPlotPicker::Plot2d_QwtPlotPicker( int            xAxis,
4452                                             int            yAxis,
4453                                             RubberBand     rubberBand,
4454                                             DisplayMode    trackerMode,
4455                                             QwtPlotCanvas *canvas)
4456 : QwtPlotPicker( xAxis,
4457                  yAxis,
4458                  rubberBand,
4459                  trackerMode,
4460                  canvas)    // of drawing zone QwtPlot
4461 {
4462 }
4463
4464 Plot2d_QwtPlotPicker::Plot2d_QwtPlotPicker( int            xAxis,
4465                                             int            yAxis,
4466                                             QwtPlotCanvas *canvas)
4467 : QwtPlotPicker( xAxis,
4468                  yAxis,
4469                  canvas)
4470 {
4471 }
4472
4473 Plot2d_QwtPlotPicker::~Plot2d_QwtPlotPicker()
4474 {
4475 }
4476 // http://www.qtcentre.org/threads/22751-How-do-i-select-a-QwtPlotMarker-using-a-QPlotPicker
4477
4478 /* Return the tooltip associated with a point when the mouse cursor pass near
4479  */
4480 QwtText Plot2d_QwtPlotPicker::trackerText( const QPoint & pos ) const
4481 {
4482   for (QList<QwtPlotMarker* >::const_iterator pMarkerIt = pMarkers.begin();pMarkerIt != pMarkers.end(); ++pMarkerIt )
4483     {
4484       QwtPlotMarker* pMarker = *pMarkerIt;
4485       if ( pMarker != NULL )
4486         {
4487           const QwtSymbol* symb=pMarker->symbol();
4488           const QSize& sz=symb->size();
4489           const QwtScaleMap yMapRef=plot()->canvasMap(QwtPlot::yLeft);
4490           const QwtScaleMap xMap=plot()->canvasMap(pMarker->xAxis());
4491           const QwtScaleMap yMap=plot()->canvasMap(pMarker->yAxis());
4492           QwtDoubleRect  bound0=pMarker->boundingRect();
4493           int x1 = qRound(xMap.transform(bound0.left()));
4494           int x2 = qRound(xMap.transform(bound0.right()));
4495           int y1 = qRound(yMap.transform(bound0.top()));
4496           int y2 = qRound(yMap.transform(bound0.bottom()));
4497           
4498           if ( x2 < x1 )
4499             qSwap(x1, x2);
4500           if ( y2 < y1 )
4501             qSwap(y1, y2);
4502           
4503           QRect bound00=QRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
4504           QPoint toto(xMap.transform(pos.x()),yMapRef.transform(pos.y()));
4505           bound00.setX(bound00.x()-sz.width());
4506           bound00.setY(bound00.y()-sz.height());
4507           bound00.setWidth(bound00.width()+sz.width());
4508           bound00.setHeight(bound00.height()+sz.height());
4509           if( bound00.contains(toto) )
4510             {
4511               return pMarkersToolTip[pMarker];
4512             }
4513         }
4514   }
4515   return QwtText();
4516 }