Salome HOME
Join modifications from branch BR_DEBUG_3_2_0b1
[modules/gui.git] / src / Plot2d / Plot2d_ViewFrame.cxx
index a5f7abd2a205b50393de0c5d003e3b49db2c1bea..f7b862f7b80fc7c6ff120dc4c7b31c7f4f43b0ec 100755 (executable)
@@ -1,3 +1,21 @@
+// Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either 
+// version 2.1 of the License.
+// 
+// This library is distributed in the hope that it will be useful 
+// but WITHOUT ANY WARRANTY; without even the implied warranty of 
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public  
+// License along with this library; if not, write to the Free Software 
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
 #include "Plot2d_ViewFrame.h"
 
 #include "Plot2d_Prs.h"
@@ -12,8 +30,6 @@
 #include "SUIT_ResourceMgr.h"
 #include "SUIT_Application.h"
 
-//#include "utilities.h"
-
 #include "qapplication.h"
 #include <qtoolbar.h>
 #include <qtoolbutton.h>
 #include <qptrlist.h>
 #include <qlayout.h>
 #include <qmap.h>
+#include <qpainter.h>
+#include <qpaintdevicemetrics.h>
 
 #include <qwt_math.h>
 #include <qwt_plot_canvas.h>
-#include <iostream.h>
+#include <iostream>
 #include <stdlib.h>
+#include <qprinter.h>
 
-//#include "utilities.h"
+#include <qwt_legend.h>
 
 #define DEFAULT_LINE_WIDTH     0     // (default) line width
 #define DEFAULT_MARKER_SIZE    9     // default marker size
@@ -111,17 +130,6 @@ const char* imageCrossCursor[] = {
   "................................"};
   
 
-QPixmap zoomPixmap(imageZoomCursor);
-QPixmap globalPanPixmap(imageCrossCursor);
-
-QCursor        panCursor(Qt::SizeAllCursor);
-QCursor        zoomCursor(zoomPixmap);
-QCursor        glPanCursor(globalPanPixmap);
-
-//=================================================================================
-// Plot2d_ViewFrame implementation
-//=================================================================================
-
 /*!
   Constructor
 */
@@ -287,8 +295,8 @@ void Plot2d_ViewFrame::readPreferences()
   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
 
   myCurveType = resMgr->integerValue( "Plot2d", "CurveType", myCurveType );
-  if ( myCurveType < 1 || myCurveType > 2 )
-    myCurveType = 1;
+  setCurveType( resMgr->integerValue( "Plot2d", "CurveType", myCurveType ) );
+
   myShowLegend = resMgr->booleanValue( "Plot2d", "ShowLegend", myShowLegend );
   myLegendPos = resMgr->integerValue( "Plot2d", "LegendPos", myLegendPos );
   myMarkerSize = resMgr->integerValue( "Plot2d", "MarkerSize", myMarkerSize );
@@ -381,7 +389,6 @@ QString Plot2d_ViewFrame::getInfo( const QPoint& pnt )
     if ( xmark-2 == pnt.x() ) {
       xCoord = majXmark; 
       xFound = true;
-//      MESSAGE("Plot2d_ViewFrame::getInfo : close maj X mark("<<i<<") = "<<majXmark<<" "<<xmark<<" "<<pnt.x());
       break;
     }
   }
@@ -392,7 +399,6 @@ QString Plot2d_ViewFrame::getInfo( const QPoint& pnt )
       if ( xmark-2 == pnt.x() ) {
         xCoord = minXmark; 
         xFound = true;
-//        MESSAGE("Plot2d_ViewFrame::getInfo : close min X mark("<<i<<") = "<<minXmark<<" "<<xmark<<" "<<pnt.x());
         break;
       }
     }
@@ -583,6 +589,15 @@ void Plot2d_ViewFrame::displayCurve( Plot2d_Curve* curve, bool update )
 {
   if ( !curve )
     return;
+
+  // san -- Protection against QwtCurve bug in Qwt 0.4.x: 
+  // it crashes if switched to X/Y logarithmic mode, when one or more points have
+  // non-positive X/Y coordinate
+  if ( myXMode && curve->getMinX() <= 0. )
+    setHorScaleMode( 0, false );
+  if ( myYMode && curve->getMinY() <= 0. )
+    setVerScaleMode( 0, false );
+
   if ( hasCurve( curve ) ) {
     updateCurve( curve, update );
   }
@@ -622,6 +637,7 @@ void Plot2d_ViewFrame::displayCurve( Plot2d_Curve* curve, bool update )
       myPlot->setCurveStyle( curveKey, QwtCurve::Spline );
     myPlot->setCurveData( curveKey, curve->horData(), curve->verData(), curve->nbPoints() );
   }
+  updateTitles();
   if ( update )
     myPlot->replot();
 }
@@ -629,7 +645,7 @@ void Plot2d_ViewFrame::displayCurve( Plot2d_Curve* curve, bool update )
 /*!
   Adds curves into view
 */
-void Plot2d_ViewFrame::displayCurves( curveList curves, bool update )
+void Plot2d_ViewFrame::displayCurves( const curveList& curves, bool update )
 {
   myPlot->setUpdatesEnabled( false );
   QPtrListIterator<Plot2d_Curve> it(curves);
@@ -656,6 +672,7 @@ void Plot2d_ViewFrame::eraseCurve( Plot2d_Curve* curve, bool update )
   if ( curveKey ) {
     myPlot->removeCurve( curveKey );
     myCurves.remove( curveKey );
+    updateTitles();
     if ( update )
       myPlot->replot();
   }
@@ -664,7 +681,7 @@ void Plot2d_ViewFrame::eraseCurve( Plot2d_Curve* curve, bool update )
 /*!
   Erases curves
 */
-void Plot2d_ViewFrame::eraseCurves( curveList& curves, bool update )
+void Plot2d_ViewFrame::eraseCurves( const curveList& curves, bool update )
 {
   QPtrListIterator<Plot2d_Curve> it(curves);
   Plot2d_Curve* aCurve;
@@ -822,6 +839,49 @@ void Plot2d_ViewFrame::fitArea( const QRect& area )
   myPlot->replot();
 }
 
+/*!
+  "Fit Data" command for TUI interface
+*/
+void Plot2d_ViewFrame::fitData(const int mode,
+                              const double xMin, const double xMax,
+                              const double yMin, const double yMax,
+                              double y2Min, double y2Max)
+{
+  if ( mode == 0 || mode == 2 ) {
+    myPlot->setAxisScale( QwtPlot::yLeft, yMax, yMin );
+    if (mySecondY)
+      myPlot->setAxisScale( QwtPlot::yRight, y2Max, y2Min );
+  }
+  if ( mode == 0 || mode == 1 ) 
+    myPlot->setAxisScale( QwtPlot::xBottom, xMin, xMax ); 
+  myPlot->replot();
+}
+
+/*!
+  Gets current fit ranges for view frame
+*/
+void Plot2d_ViewFrame::getFitRanges(double& xMin,double& xMax,
+                                   double& yMin, double& yMax,
+                                   double& y2Min, double& y2Max)
+{
+  int ixMin = myPlot->canvasMap( QwtPlot::xBottom ).i1();
+  int ixMax = myPlot->canvasMap( QwtPlot::xBottom ).i2();
+  int iyMin = myPlot->canvasMap( QwtPlot::yLeft ).i1();
+  int iyMax = myPlot->canvasMap( QwtPlot::yLeft ).i2();
+  xMin = myPlot->invTransform(QwtPlot::xBottom, ixMin);
+  xMax = myPlot->invTransform(QwtPlot::xBottom, ixMax);
+  yMin = myPlot->invTransform(QwtPlot::yLeft, iyMin);
+  yMax = myPlot->invTransform(QwtPlot::yLeft, iyMax);
+  y2Min = 0;
+  y2Max = 0;
+  if (mySecondY) {
+    int iyMin = myPlot->canvasMap( QwtPlot::yRight ).i1();
+    int iyMax = myPlot->canvasMap( QwtPlot::yRight ).i2();
+    y2Min = myPlot->invTransform(QwtPlot::yRight, iyMin);
+    y2Max = myPlot->invTransform(QwtPlot::yRight, iyMax);
+  }
+}
+
 /*!
   Tests if it is necessary to start operation on mouse action
 */
@@ -835,8 +895,12 @@ int Plot2d_ViewFrame::testOperation( const QMouseEvent& me )
   switch (btn)
   {
   case zoomBtn:
-    myPlot->canvas()->setCursor( zoomCursor );
-    return ZoomId;
+    {
+      QPixmap zoomPixmap (imageZoomCursor);
+      QCursor zoomCursor (zoomPixmap);
+      myPlot->canvas()->setCursor( zoomCursor );
+      return ZoomId;
+    }
   case panBtn:
     myPlot->canvas()->setCursor( QCursor( Qt::SizeAllCursor ) );
     return PanId;
@@ -890,12 +954,6 @@ void Plot2d_ViewFrame::onSettings()
     if ( cols[ "blue-min" ] > color.blue() )
       cols[ "blue-min" ] = color.blue();
   }
-  for (IList::Iterator it = mars.begin();  it != mars.end(); ++it)
-    MESSAGE("markers( " << it.key() << ") = " << it.data() );
-  for (IList::Iterator it = lins.begin();  it != lins.end(); ++it)
-    MESSAGE("lines( " << it.key() << ") = " << it.data() );
-  for (SList::Iterator it = cols.begin();  it != cols.end(); ++it)
-    MESSAGE("colors( " << it.key() << ") = " << it.data() );
 #endif
   
   Plot2d_SetupViewDlg* dlg = new Plot2d_SetupViewDlg( this, true, mySecondY );
@@ -978,34 +1036,13 @@ void Plot2d_ViewFrame::onSettings()
 void Plot2d_ViewFrame::onFitData()
 {
   Plot2d_FitDataDlg* dlg = new Plot2d_FitDataDlg( this, mySecondY );
-  int ixMin = myPlot->canvasMap( QwtPlot::xBottom ).i1();
-  int ixMax = myPlot->canvasMap( QwtPlot::xBottom ).i2();
-  int iyMin = myPlot->canvasMap( QwtPlot::yLeft ).i1();
-  int iyMax = myPlot->canvasMap( QwtPlot::yLeft ).i2();
-  double xMin = myPlot->invTransform(QwtPlot::xBottom, ixMin);
-  double xMax = myPlot->invTransform(QwtPlot::xBottom, ixMax);
-  double yMin = myPlot->invTransform(QwtPlot::yLeft, iyMin);
-  double yMax = myPlot->invTransform(QwtPlot::yLeft, iyMax);
-  double y2Min = 0;
-  double y2Max = 0;
-  if (mySecondY) {
-    int iyMin = myPlot->canvasMap( QwtPlot::yRight ).i1();
-    int iyMax = myPlot->canvasMap( QwtPlot::yRight ).i2();
-    y2Min = myPlot->invTransform(QwtPlot::yRight, iyMin);
-    y2Max = myPlot->invTransform(QwtPlot::yRight, iyMax);
-  }
+  double xMin,xMax,yMin,yMax,y2Min,y2Max;
+  getFitRanges(xMin,xMax,yMin,yMax,y2Min,y2Max);
   
   dlg->setRange( xMin, xMax, yMin, yMax, y2Min, y2Max );
   if ( dlg->exec() == QDialog::Accepted ) {
     int mode = dlg->getRange( xMin, xMax, yMin, yMax, y2Min, y2Max );
-    if ( mode == 0 || mode == 2 ) {
-      myPlot->setAxisScale( QwtPlot::yLeft, yMax, yMin );
-      if (mySecondY)
-        myPlot->setAxisScale( QwtPlot::yRight, y2Max, y2Min );
-    }
-    if ( mode == 0 || mode == 1 ) 
-      myPlot->setAxisScale( QwtPlot::xBottom, xMin, xMax ); 
-    myPlot->replot();
+    fitData(mode,xMin,xMax,yMin,yMax,y2Min,y2Max);
   }
   delete dlg;
 }
@@ -1041,6 +1078,11 @@ void Plot2d_ViewFrame::setCurveType( int curveType, bool update )
   emit vpCurveChanged();
 }
 
+/*!
+  Sets curve title
+  \param curveKey - curve id
+  \param title - new title
+*/
 void Plot2d_ViewFrame::setCurveTitle( int curveKey, const QString& title ) 
 { 
   if(myPlot) myPlot->setCurveTitle(curveKey, title); 
@@ -1280,11 +1322,17 @@ void Plot2d_ViewFrame::setFont( const QFont& font, ObjectType type, bool update)
 */
 void Plot2d_ViewFrame::setHorScaleMode( const int mode, bool update )
 {
+  // san -- Protection against QwtCurve bug in Qwt 0.4.x: 
+  // it crashes if switched to X/Y logarithmic mode, when one or more points have
+  // non-positive X/Y coordinate
+  if ( mode && !isXLogEnabled() ){
+    SUIT_MessageBox::warn1(this, tr("WARNING"), tr("WRN_XLOG_NOT_ALLOWED"), tr("BUT_OK"));
+    return;
+  }
+
   myXMode = mode;
-  if ( myXMode == 0 ) // linear
-    myPlot->changeAxisOptions( QwtPlot::xBottom, QwtAutoScale::Logarithmic, false );
-  else                // logarithmic
-    myPlot->changeAxisOptions( QwtPlot::xBottom, QwtAutoScale::Logarithmic, true );
+
+  myPlot->changeAxisOptions( QwtPlot::xBottom, QwtAutoScale::Logarithmic, myXMode != 0 );
 
   if ( update )
     fitAll();
@@ -1295,17 +1343,19 @@ void Plot2d_ViewFrame::setHorScaleMode( const int mode, bool update )
 */
 void Plot2d_ViewFrame::setVerScaleMode( const int mode, bool update )
 {
-  myYMode = mode;
-  if ( myYMode == 0 ) { // linear
-    myPlot->changeAxisOptions( QwtPlot::yLeft, QwtAutoScale::Logarithmic, false );
-    if (mySecondY)
-      myPlot->changeAxisOptions( QwtPlot::yRight, QwtAutoScale::Logarithmic, false );
-  }
-  else {               // logarithmic
-    myPlot->changeAxisOptions( QwtPlot::yLeft, QwtAutoScale::Logarithmic, true );
-    if (mySecondY)
-      myPlot->changeAxisOptions( QwtPlot::yRight, QwtAutoScale::Logarithmic, true );
+  // san -- Protection against QwtCurve bug in Qwt 0.4.x: 
+  // it crashes if switched to X/Y logarithmic mode, when one or more points have
+  // non-positive X/Y coordinate
+  if ( mode && !isYLogEnabled() ){
+    SUIT_MessageBox::warn1(this, tr("WARNING"), tr("WRN_YLOG_NOT_ALLOWED"), tr("BUT_OK"));
+    return;
   }
+
+  myYMode = mode;
+  myPlot->changeAxisOptions( QwtPlot::yLeft, QwtAutoScale::Logarithmic, myYMode != 0 );
+  if (mySecondY)
+    myPlot->changeAxisOptions( QwtPlot::yRight, QwtAutoScale::Logarithmic, myYMode != 0 );
+
   if ( update )
     fitAll();
   emit vpModeVerChanged();
@@ -1331,6 +1381,9 @@ bool Plot2d_ViewFrame::isModeVerLinear()
 */
 void Plot2d_ViewFrame::plotMousePressed(const QMouseEvent& me )
 {
+  Plot2d_ViewWindow* aParent = dynamic_cast<Plot2d_ViewWindow*>(parent());
+   if (aParent)
+     aParent->putInfo(getInfo(me.pos()));
   if ( myOperation == NoOpId )
     myOperation = testOperation( me );
   if ( myOperation != NoOpId ) {
@@ -1411,7 +1464,9 @@ void Plot2d_ViewFrame::plotMouseMoved( const QMouseEvent& me )
     }
   }
   else {
-    ((Plot2d_ViewWindow*)parent())->putInfo(getInfo(me.pos()));
+     Plot2d_ViewWindow* aParent = dynamic_cast<Plot2d_ViewWindow*>(parent());
+     if (aParent)
+       aParent->putInfo(getInfo(me.pos()));
   }
 }
 /*!
@@ -1433,7 +1488,9 @@ void Plot2d_ViewFrame::plotMouseReleased( const QMouseEvent& me )
   myPlot->canvas()->setCursor( QCursor( Qt::CrossCursor ) );
   myPlot->setOutlineStyle( Qwt::Triangle );
 
-  ((Plot2d_ViewWindow*)parent())->putInfo(tr("INF_READY"));
+  Plot2d_ViewWindow* aParent = dynamic_cast<Plot2d_ViewWindow*>(parent());
+   if (aParent)
+     aParent->putInfo(tr("INF_READY"));
   myOperation = NoOpId;
 }
 /*!
@@ -1462,39 +1519,12 @@ void Plot2d_ViewFrame::wheelEvent(QWheelEvent* event)
   myPlot->replot();
   myPnt = event->pos();
 }
-/*!
-  View operations : Dump view
-*/
-void Plot2d_ViewFrame::onDump()
-{
-  QApplication::setOverrideCursor( Qt::waitCursor );
-  QPixmap px = QPixmap::grabWindow(winId());
-  QApplication::restoreOverrideCursor();
-
-  SUIT_Application* app = ((Plot2d_ViewWindow*)parent())->getViewManager()->study()->application();
-
-  QString aFileName = app->getFileName( false, QString::null, tr("PLOT2D_IMAGE_FILES"), tr("INF_APP_DUMP_VIEW"), 0 );
-
-  if ( !aFileName.isNull() )
-  {
-    QApplication::setOverrideCursor( Qt::waitCursor );
-    QString fmt = SUIT_Tools::extension( aFileName ).upper();
-    if (fmt.isEmpty())
-      fmt = QString("BMP"); // default format
-    if (fmt == "JPG")
-      fmt = "JPEG";
-    bool bOk = px.save(aFileName, fmt.latin1());
-    QApplication::restoreOverrideCursor();
-    if (!bOk) {
-      SUIT_MessageBox::error1(this, tr("ERROR"), tr("ERR_DOC_CANT_SAVE_FILE"), tr("BUT_OK"));
-    }
-  }
-}
 /*!
   View operations : Pan view
 */
 void Plot2d_ViewFrame::onViewPan()
 { 
+  QCursor panCursor (Qt::SizeAllCursor);
   myPlot->canvas()->setCursor( panCursor );
   myOperation = PanId;
   qApp->installEventFilter( this );
@@ -1504,6 +1534,8 @@ void Plot2d_ViewFrame::onViewPan()
 */
 void Plot2d_ViewFrame::onViewZoom() 
 {
+  QPixmap zoomPixmap (imageZoomCursor);
+  QCursor zoomCursor (zoomPixmap);
   myPlot->canvas()->setCursor( zoomCursor );
   myOperation = ZoomId;
   qApp->installEventFilter( this );
@@ -1529,6 +1561,8 @@ void Plot2d_ViewFrame::onViewFitArea()
 */
 void Plot2d_ViewFrame::onViewGlobalPan() 
 {
+  QPixmap globalPanPixmap (imageCrossCursor);
+  QCursor glPanCursor (globalPanPixmap);
   myPlot->canvas()->setCursor( glPanCursor );
   myPlot->changeAxisOptions( QwtPlot::xBottom, QwtAutoScale::Logarithmic, false );
   myPlot->changeAxisOptions( QwtPlot::yLeft, QwtAutoScale::Logarithmic, false );
@@ -1550,9 +1584,32 @@ void Plot2d_ViewFrame::onViewGlobalPan()
   qApp->installEventFilter( this );
 }
 
-//=================================================================================
-// Plot2d_Plot2d implementation
-//=================================================================================
+/*!
+  Precaution for logarithmic X scale
+*/
+bool Plot2d_ViewFrame::isXLogEnabled() const
+{
+  bool allPositive = true;
+  QIntDictIterator<Plot2d_Curve> it( myCurves );
+  for ( ; allPositive && it.current(); ++it ) {
+    allPositive = ( it.current()->getMinX() > 0. );
+  }
+  return allPositive;
+}
+
+/*!
+  Precaution for logarithmic Y scale
+*/
+bool Plot2d_ViewFrame::isYLogEnabled() const
+{
+  bool allPositive = true;
+  QIntDictIterator<Plot2d_Curve> it( myCurves );
+  for ( ; allPositive && it.current(); ++it ) {
+    allPositive = ( it.current()->getMinY() > 0. );
+  }
+  return allPositive;
+}
+
 /*!
   Constructor
 */
@@ -1686,11 +1743,17 @@ void Plot2d_Plot2d::getNextMarker( QwtSymbol::Style& typeMarker, QColor& color,
 */
 }
 
+/*!
+  \return the default layout behavior of the widget
+*/
 QSizePolicy Plot2d_Plot2d::sizePolicy() const
 {
   return QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
 }
 
+/*!
+  \return the recommended size for the widget
+*/
 QSize Plot2d_Plot2d::sizeHint() const
 {
   return QwtPlot::minimumSizeHint();
@@ -1730,3 +1793,190 @@ bool Plot2d_Plot2d::existMarker( const QwtSymbol::Style typeMarker, const QColor
   }
   return false;
 }
+
+/*!
+  Creates presentation of object
+  Default implementation is empty
+*/
+Plot2d_Prs* Plot2d_ViewFrame::CreatePrs( const char* /*entry*/ )
+{
+  return 0;
+}
+
+/*!
+  Copies preferences from other viewframe
+  \param vf - other view frame
+*/
+void Plot2d_ViewFrame::copyPreferences( Plot2d_ViewFrame* vf )
+{
+  if( !vf )
+    return;
+
+  myCurveType = vf->myCurveType;
+  myShowLegend = vf->myShowLegend;
+  myLegendPos = vf->myLegendPos;
+  myMarkerSize = vf->myMarkerSize;
+  myBackground = vf->myBackground;
+  myTitle = vf->myTitle; 
+  myXTitle = vf->myXTitle;
+  myYTitle = vf->myYTitle;
+  myY2Title = vf->myY2Title;
+  myTitleEnabled = vf->myTitleEnabled;
+  myXTitleEnabled = vf->myXTitleEnabled;
+  myYTitleEnabled = vf->myYTitleEnabled;
+  myY2TitleEnabled = vf->myY2TitleEnabled;
+  myXGridMajorEnabled = vf->myXGridMajorEnabled;
+  myYGridMajorEnabled = vf->myYGridMajorEnabled;
+  myY2GridMajorEnabled = vf->myY2GridMajorEnabled;
+  myXGridMinorEnabled = vf->myXGridMinorEnabled;
+  myYGridMinorEnabled = vf->myYGridMinorEnabled;
+  myY2GridMinorEnabled = vf->myY2GridMinorEnabled;
+  myXGridMaxMajor = vf->myXGridMaxMajor;
+  myYGridMaxMajor = vf->myYGridMaxMajor;
+  myY2GridMaxMajor = vf->myY2GridMaxMajor;
+  myXGridMaxMinor = vf->myXGridMaxMinor;
+  myYGridMaxMinor = vf->myYGridMaxMinor;
+  myY2GridMaxMinor = vf->myY2GridMaxMinor;
+  myXMode = vf->myXMode;
+  myYMode = vf->myYMode;
+  mySecondY = vf->mySecondY;
+}
+
+/*!
+  Updates titles according to curves
+*/
+#define BRACKETIZE(x) QString( "[ " ) + x + QString( " ]" )
+void Plot2d_ViewFrame::updateTitles() 
+{
+  QIntDictIterator<Plot2d_Curve> it( myCurves );
+  QStringList aXTitles;
+  QStringList aYTitles;
+  QStringList aXUnits;
+  QStringList aYUnits;
+  QStringList aTables;
+  int i = 0;
+  while ( it.current() ) {
+    // collect titles and units from all curves...
+    QString xTitle = it.current()->getHorTitle().stripWhiteSpace();
+    QString yTitle = it.current()->getVerTitle().stripWhiteSpace();
+    QString xUnits = it.current()->getHorUnits().stripWhiteSpace();
+    QString yUnits = it.current()->getVerUnits().stripWhiteSpace();
+    
+    aYTitles.append( yTitle );
+    if ( aXTitles.find( xTitle ) == aXTitles.end() )
+      aXTitles.append( xTitle );
+    if ( aXUnits.find( xUnits ) == aXUnits.end() )
+      aXUnits.append( xUnits );
+    if ( aYUnits.find( yUnits ) == aYUnits.end() )
+      aYUnits.append( yUnits );
+
+    QString aName = it.current()->getTableTitle();
+    if( !aName.isEmpty() && aTables.find( aName ) == aTables.end() )
+      aTables.append( aName );
+
+    ++it;
+    ++i;
+  }
+  // ... and update plot 2d view
+  QString xUnits, yUnits;
+  if ( aXUnits.count() == 1 && !aXUnits[0].isEmpty() )
+    xUnits = BRACKETIZE( aXUnits[0] );
+  if ( aYUnits.count() == 1 && !aYUnits[0].isEmpty())
+    yUnits = BRACKETIZE( aYUnits[0] );
+  QString xTitle, yTitle;
+  if ( aXTitles.count() == 1 && aXUnits.count() == 1 )
+    xTitle = aXTitles[0];
+  if ( aYTitles.count() == 1 )
+    yTitle = aYTitles[0];
+
+  if ( !xTitle.isEmpty() && !xUnits.isEmpty() )
+    xTitle += " ";
+  if ( !yTitle.isEmpty() && !yUnits.isEmpty() )
+    yTitle += " ";
+
+  setTitle( myXTitleEnabled, xTitle + xUnits, XTitle, true );
+  setTitle( myYTitleEnabled, yTitle + yUnits, YTitle, true );
+  setTitle( true, aTables.join("; "), MainTitle, true );
+}
+
+/*!
+  Outputs content of viewframe to file
+  \param file - file name
+  \param format - file format
+*/
+bool Plot2d_ViewFrame::print( const QString& file, const QString& format ) const
+{
+#ifdef WIN32
+  return false;
+
+#else
+  bool res = false;
+  if( myPlot )
+  {
+    QPaintDevice* pd = 0;
+    if( format=="PS" )
+    {
+      QPrinter* pr = new QPrinter( QPrinter::HighResolution );
+      pr->setPageSize( QPrinter::A4 );
+      pr->setOutputToFile( true );
+      pr->setOutputFileName( file );
+      pr->setPrintProgram( "" );
+      pd = pr;
+    }
+
+    if( pd )
+    {
+      myPlot->print( *pd );
+      res = true;
+      delete pd;
+    }
+  }
+  return res;
+#endif
+}
+
+/*!
+  \return string with all visual parameters
+*/
+QString Plot2d_ViewFrame::getVisualParameters()
+{
+  double xmin, xmax, ymin, ymax, y2min, y2max;
+  getFitRanges( xmin, xmax, ymin, ymax, y2min, y2max );
+  QString retStr;
+  retStr.sprintf( "%d*%d*%d*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e", myXMode,
+                 myYMode, mySecondY, xmin, xmax, ymin, ymax, y2min, y2max );
+  return retStr; 
+}
+
+/*!
+  Restores all visual parameters from string
+*/
+void Plot2d_ViewFrame::setVisualParameters( const QString& parameters )
+{
+  QStringList paramsLst = QStringList::split( '*', parameters, true );
+  if ( paramsLst.size() == 9 ) {
+    double xmin, xmax, ymin, ymax, y2min, y2max;
+    myXMode = paramsLst[0].toInt();
+    myYMode = paramsLst[1].toInt();
+    mySecondY = (bool)paramsLst[2].toInt();
+    xmin =  paramsLst[3].toDouble();
+    xmax =  paramsLst[4].toDouble();
+    ymin =  paramsLst[5].toDouble();
+    ymax =  paramsLst[6].toDouble();
+    y2min = paramsLst[7].toDouble();
+    y2max = paramsLst[8].toDouble();
+
+    if (mySecondY)
+      setTitle( myY2TitleEnabled, myY2Title, Y2Title, false );
+    setHorScaleMode( myXMode, /*update=*/false );
+    setVerScaleMode( myYMode, /*update=*/false );
+    
+    if (mySecondY) {
+      QwtDiMap yMap2 = myPlot->canvasMap( QwtPlot::yRight );
+      myYDistance2 = yMap2.d2() - yMap2.d1();
+    }
+
+    fitData( 0, xmin, xmax, ymin, ymax, y2min, y2max );
+    fitData( 0, xmin, xmax, ymin, ymax, y2min, y2max );
+  }  
+}