scidavis  2.3.0
About: SciDAVis is a free application for Scientific Data Analysis and Visualization (a fork off of QtiPlot).
  Fossies Dox: scidavis-2.3.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

Graph.cpp
Go to the documentation of this file.
1 
11 
30 #include <QVarLengthArray>
31 
32 #include "Graph.h"
33 #include "Grid.h"
34 #include "CanvasPicker.h"
35 #include "QwtErrorPlotCurve.h"
36 #include "Legend.h"
37 #include "ArrowMarker.h"
38 #include "ScalePicker.h"
39 #include "TitlePicker.h"
40 #include "QwtPieCurve.h"
41 #include "ImageMarker.h"
42 #include "QwtBarCurve.h"
43 #include "BoxCurve.h"
44 #include "QwtHistogram.h"
45 #include "VectorCurve.h"
46 #include "ScaleDraw.h"
47 #include "ColorButton.h"
48 #include "PatternBox.h"
49 #include "SymbolBox.h"
50 #include "FunctionCurve.h"
51 #include "Spectrogram.h"
52 #include "SelectionMoveResizer.h"
53 #include "RangeSelectorTool.h"
54 #include "PlotCurve.h"
55 #include "ApplicationWindow.h"
56 #include "core/column/Column.h"
57 
58 #include <QApplication>
59 #include <QBitmap>
60 #include <QClipboard>
61 #include <QCursor>
62 #include <QImage>
63 #include <QMessageBox>
64 #include <QPixmap>
65 #include <QPainter>
66 #include <QMenu>
67 #include <QTextStream>
68 #include <QLocale>
69 #include <QPrintDialog>
70 #include <QImageWriter>
71 #include <QFileInfo>
72 #include <QRegExp>
73 
74 #if QT_VERSION >= 0x040300
75  #include <QSvgGenerator>
76 #endif
77 
78 #include <qwt_painter.h>
79 #include <qwt_plot_canvas.h>
80 #include <qwt_plot_layout.h>
81 #include <qwt_plot_zoomer.h>
82 #include <qwt_scale_widget.h>
83 #include <qwt_scale_engine.h>
84 #include <qwt_text.h>
85 #include <qwt_text_label.h>
86 #include <qwt_color_map.h>
87 
88 #include <stdexcept>
89 
90 #include <math.h>
91 #include <stdlib.h>
92 #include <stdio.h>
93 #include <stddef.h>
94 using namespace std;
95 
96 Graph::Graph(QWidget* parent, QString name, Qt::WindowFlags f)
97 : QWidget(parent,f)
98 {
99  if ( name.isEmpty() )
100  setObjectName( "graph" );
101  else
102  setObjectName( name );
103 
104  n_curves=0;
105  d_active_tool = NULL;
106  widthLine=1;
107  selectedMarker=-1;
108  drawTextOn=false;
109  drawLineOn=false;
110  drawArrowOn=false;
111  ignoreResize = true;
112  drawAxesBackbone = true;
113  m_autoscale = true;
114  autoScaleFonts = false;
115  hidden_size = QSize();
116  d_antialiasing = true;
117  d_scale_on_print = true;
118  d_print_cropmarks = false;
119 
121  defaultArrowColor = QColor(Qt::black);
122  defaultArrowLineStyle = Qt::SolidLine;
125  defaultArrowHeadFill = true;
126 
127  defaultMarkerFont = QFont();
128  defaultMarkerFrame = 1;
129  defaultTextMarkerColor = QColor(Qt::black);
130  defaultTextMarkerBackground = QColor(Qt::white);
131 
132  d_user_step = QVector<double>(QwtPlot::axisCnt);
133  for (int i=0; i<QwtPlot::axisCnt; i++)
134  {
135  axisType << Numeric;
136  axesFormatInfo << QString();
137  axesFormulas << QString();
138  d_user_step[i] = 0.0;
139  }
140 
141  d_plot = new Plot(this);
142  cp = new CanvasPicker(this);
143 
146 
147  d_zoomer[0]= new QwtPlotZoomer(QwtPlot::xBottom, QwtPlot::yLeft,
148  QwtPicker::DragSelection | QwtPicker::CornerToCorner, QwtPicker::AlwaysOff, d_plot->canvas());
149  d_zoomer[0]->setRubberBandPen(QPen(Qt::black));
150  d_zoomer[1] = new QwtPlotZoomer(QwtPlot::xTop, QwtPlot::yRight,
151  QwtPicker::DragSelection | QwtPicker::CornerToCorner,
152  QwtPicker::AlwaysOff, d_plot->canvas());
153  zoom(false);
154 
155  setGeometry(0, 0, 500, 400);
156  setFocusPolicy(Qt::StrongFocus);
157  setFocusProxy(d_plot);
158  setMouseTracking(true );
159 
160  legendMarkerID = -1; // no legend for an empty graph
161  d_texts = QVector<int>();
162  c_type = QVector<int>();
163  c_keys = QVector<int>();
164 
165  connect (cp,SIGNAL(selectPlot()),this,SLOT(activateGraph()));
166  connect (cp,SIGNAL(drawTextOff()),this,SIGNAL(drawTextOff()));
167  connect (cp,SIGNAL(viewImageDialog()),this,SIGNAL(viewImageDialog()));
168  connect (cp,SIGNAL(viewTextDialog()),this,SIGNAL(viewTextDialog()));
169  connect (cp,SIGNAL(viewLineDialog()),this,SIGNAL(viewLineDialog()));
170  connect (cp,SIGNAL(showPlotDialog(int)),this,SIGNAL(showPlotDialog(int)));
171  connect (cp,SIGNAL(showMarkerPopupMenu()),this,SIGNAL(showMarkerPopupMenu()));
172  connect (cp,SIGNAL(modified()), this, SIGNAL(modifiedGraph()));
173 
174  connect (titlePicker,SIGNAL(showTitleMenu()),this,SLOT(showTitleContextMenu()));
175  connect (titlePicker,SIGNAL(doubleClicked()),this,SIGNAL(viewTitleDialog()));
176  connect (titlePicker,SIGNAL(removeTitle()),this,SLOT(removeTitle()));
177  connect (titlePicker,SIGNAL(clicked()), this,SLOT(selectTitle()));
178 
179  connect (scalePicker,SIGNAL(clicked()),this,SLOT(activateGraph()));
180  connect (scalePicker,SIGNAL(clicked()),this,SLOT(deselectMarker()));
181  connect (scalePicker,SIGNAL(axisDblClicked(int)),this,SIGNAL(axisDblClicked(int)));
182  connect (scalePicker,SIGNAL(axisTitleRightClicked(int)),this,SLOT(showAxisTitleMenu(int)));
183  connect (scalePicker,SIGNAL(axisRightClicked(int)),this,SLOT(showAxisContextMenu(int)));
184  connect (scalePicker,SIGNAL(xAxisTitleDblClicked()),this,SIGNAL(xAxisTitleDblClicked()));
185  connect (scalePicker,SIGNAL(yAxisTitleDblClicked()),this,SIGNAL(yAxisTitleDblClicked()));
186  connect (scalePicker,SIGNAL(rightAxisTitleDblClicked()),this,SIGNAL(rightAxisTitleDblClicked()));
187  connect (scalePicker,SIGNAL(topAxisTitleDblClicked()),this,SIGNAL(topAxisTitleDblClicked()));
188 
189  connect (d_zoomer[0],SIGNAL(zoomed (const QwtDoubleRect &)),this,SLOT(zoomed (const QwtDoubleRect &)));
190 }
191 
193 {
194  emit modifiedGraph();
195 }
196 
198 {
199  emit selectedGraph(this);
200  setFocus();
201 }
202 
204 {
205  selectedMarker = -1;
206  if (d_markers_selector)
207  delete d_markers_selector;
208 }
209 
211 {
212  return selectedMarker;
213 }
214 
215 QwtPlotMarker* Graph::selectedMarkerPtr()
216 {
217  return d_plot->marker(selectedMarker);
218 }
219 
220 void Graph::setSelectedMarker(long mrk, bool add)
221 {
222  selectedMarker = mrk;
223  if (add) {
224  if (d_markers_selector) {
225  if (d_texts.contains(mrk))
226  d_markers_selector->add((Legend*)d_plot->marker(mrk));
227  else if (d_lines.contains(mrk))
229  else if (d_images.contains(mrk))
231  } else {
232  if (d_texts.contains(mrk))
234  else if (d_lines.contains(mrk))
236  else if (d_images.contains(mrk))
238  else
239  return;
240  connect(d_markers_selector, SIGNAL(targetsChanged()), this, SIGNAL(modifiedGraph()));
241  }
242  } else {
243  if (d_texts.contains(mrk)) {
244  if (d_markers_selector) {
245  if (d_markers_selector->contains((Legend*)d_plot->marker(mrk)))
246  return;
247  delete d_markers_selector;
248  }
250  } else if (d_lines.contains(mrk)) {
251  if (d_markers_selector) {
252  if (d_markers_selector->contains((ArrowMarker*)d_plot->marker(mrk)))
253  return;
254  delete d_markers_selector;
255  }
257  } else if (d_images.contains(mrk)) {
258  if (d_markers_selector) {
259  if (d_markers_selector->contains((ImageMarker*)d_plot->marker(mrk)))
260  return;
261  delete d_markers_selector;
262  }
264  } else
265  return;
266  connect(d_markers_selector, SIGNAL(targetsChanged()), this, SIGNAL(modifiedGraph()));
267  }
268 }
269 
270 void Graph::initFonts(const QFont &scaleTitleFnt, const QFont &numbersFnt)
271 {
272  for (int i = 0;i<QwtPlot::axisCnt;i++)
273  {
274  d_plot->setAxisFont (i,numbersFnt);
275  QwtText t = d_plot->axisTitle (i);
276  t.setFont (scaleTitleFnt);
277  d_plot->setAxisTitle(i, t);
278  }
279 }
280 
281 void Graph::setAxisFont(int axis,const QFont &fnt)
282 {
283  d_plot->setAxisFont (axis, fnt);
284  d_plot->replot();
285  emit modifiedGraph();
286 }
287 
288 QFont Graph::axisFont(int axis)
289 {
290  return d_plot->axisFont (axis);
291 }
292 
293 void Graph::enableAxis(int axis, bool on)
294 {
295  d_plot->enableAxis(axis, on);
296  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(axis);
297  if (scale)
298  scale->setMargin(0);
299 
300  scalePicker->refresh();
301 }
302 
303 void Graph::enableAxes(const QStringList& list)
304 {
305  int i;
306  for (i = 0;i<QwtPlot::axisCnt;i++)
307  {
308  bool ok=list[i+1].toInt();
309  d_plot->enableAxis(i,ok);
310  }
311 
312  for (i = 0;i<QwtPlot::axisCnt;i++)
313  {
314  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(i);
315  if (scale)
316  scale->setMargin(0);
317  }
318  scalePicker->refresh();
319 }
320 
321 void Graph::enableAxes(QVector<bool> axesOn)
322 {
323  for (int i = 0; i<QwtPlot::axisCnt; i++)
324  d_plot->enableAxis(i, axesOn[i]);
325 
326  for (int i = 0;i<QwtPlot::axisCnt;i++)
327  {
328  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(i);
329  if (scale)
330  scale->setMargin(0);
331  }
332  scalePicker->refresh();
333 }
334 
335 QVector<bool> Graph::enabledAxes()
336 {
337  QVector<bool> axesOn(4);
338  for (int i = 0; i<QwtPlot::axisCnt; i++)
339  axesOn[i]=d_plot->axisEnabled (i);
340  return axesOn;
341 }
342 
344 {
345  QList<int> baselineDist;
346  for (int i = 0; i<QwtPlot::axisCnt; i++)
347  {
348  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(i);
349  if (scale)
350  baselineDist << scale->margin();
351  else
352  baselineDist << 0;
353  }
354  return baselineDist;
355 }
356 
357 void Graph::setAxesBaseline(const QList<int> &lst)
358 {
359  for (int i = 0; i<QwtPlot::axisCnt; i++)
360  {
361  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(i);
362  if (scale)
363  scale->setMargin(lst[i]);
364  }
365 }
366 
367 void Graph::setAxesBaseline(QStringList &lst)
368 {
369  lst.removeAll(lst.first());
370  for (int i = 0; i<QwtPlot::axisCnt; i++)
371  {
372  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(i);
373  if (scale)
374  scale->setMargin((lst[i]).toInt());
375  }
376 }
377 
378 QList<int> Graph::axesType()
379 {
380  return axisType;
381 }
382 
383 void Graph::setLabelsNumericFormat(int axis, int format, int prec, const QString& formula)
384 {
385  axisType[axis] = Numeric;
386  axesFormulas[axis] = formula;
387 
388  ScaleDraw *sd_old = (ScaleDraw *)d_plot->axisScaleDraw (axis);
389  const QwtScaleDiv div = sd_old->scaleDiv ();
390 
391  if (format == Plot::Superscripts){
392  QwtSupersciptsScaleDraw *sd = new QwtSupersciptsScaleDraw(*static_cast<const ScaleDraw*>(d_plot->axisScaleDraw(axis)), formula.toUtf8().constData());
393  sd->setLabelFormat('s', prec);
394  sd->setScaleDiv(div);
395  d_plot->setAxisScaleDraw (axis, sd);
396  } else {
397  ScaleDraw *sd = new ScaleDraw(*static_cast<const ScaleDraw*>(d_plot->axisScaleDraw(axis)), formula.toUtf8().constData());
398  sd->enableComponent(QwtAbstractScaleDraw::Labels, true);
399  sd->setScaleDiv(div);
400 
401  if (format == Plot::Automatic)
402  sd->setLabelFormat ('g', prec);
403  else if (format == Plot::Scientific )
404  sd->setLabelFormat ('e', prec);
405  else if (format == Plot::Decimal)
406  sd->setLabelFormat ('f', prec);
407 
408  d_plot->setAxisScaleDraw (axis, sd);
409  }
410 }
411 
412 void Graph::setLabelsNumericFormat(int axis, const QStringList& l)
413 {
414  QwtScaleDraw *sd = d_plot->axisScaleDraw (axis);
415  if (!sd->hasComponent(QwtAbstractScaleDraw::Labels) ||
416  axisType[axis] != Numeric) return;
417 
418  int format=l[2*axis].toInt();
419  int prec=l[2*axis+1].toInt();
420  setLabelsNumericFormat(axis, format, prec, axesFormulas[axis]);
421 }
422 
423 void Graph::setLabelsNumericFormat(const QStringList& l)
424 {
425  for (int axis = 0; axis<4; axis++)
426  setLabelsNumericFormat (axis, l);
427 }
428 
430 {
431  QString s="AxisType\t";
432  for (int i=0; i<4; i++)
433  {
434  int type = axisType[i];
435  s+=QString::number(type);
436  if (type == Time || type == Date || type == DateTime || type == Txt ||
437  type == ColHeader || type == Day || type == Month)
438  s += ";" + axesFormatInfo[i];
439  s+="\t";
440  };
441 
442  return s+"\n";
443 }
444 
446 {
447  QList<int> ticksTypeList=d_plot->getMajorTicksType();
448  QString s="MajorTicks\t";
449  int i;
450  for (i=0; i<4; i++)
451  s+=QString::number(ticksTypeList[i])+"\t";
452  s += "\n";
453 
454  ticksTypeList=d_plot->getMinorTicksType();
455  s += "MinorTicks\t";
456  for (i=0; i<4; i++)
457  s+=QString::number(ticksTypeList[i])+"\t";
458 
459  return s+"\n";
460 }
461 
463 {
464  QStringList lst;
465  for (int axis=0; axis<QwtPlot::axisCnt; axis++)
466  {
467  const QwtScaleDraw *sd = d_plot->axisScaleDraw (axis);
468  lst << QString::number(sd->hasComponent(QwtAbstractScaleDraw::Labels));
469  }
470  return lst;
471 }
472 
474 {
475  QString s="EnabledTickLabels\t";
476  for (int axis=0; axis<QwtPlot::axisCnt; axis++)
477  {
478  const QwtScaleDraw *sd = d_plot->axisScaleDraw (axis);
479  s += QString::number(sd->hasComponent(QwtAbstractScaleDraw::Labels))+"\t";
480  }
481  return s+"\n";
482 }
483 
485 {
486  QString s="LabelsFormat\t";
487  for (int axis=0; axis<QwtPlot::axisCnt; axis++)
488  {
489  s += QString::number(d_plot->axisLabelFormat(axis))+"\t";
490  s += QString::number(d_plot->axisLabelPrecision(axis))+"\t";
491  }
492  return s+"\n";
493 }
494 
496 {
497  QString s="AxesBaseline\t";
498  for (int i = 0; i<QwtPlot::axisCnt; i++)
499  {
500  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(i);
501  if (scale)
502  s+= QString::number(scale->margin()) + "\t";
503  else
504  s+= "0\t";
505  }
506  return s+"\n";
507 }
508 
510 {
511  QString s="LabelsRotation\t";
512  s+=QString::number(labelsRotation(QwtPlot::xBottom))+"\t";
513  s+=QString::number(labelsRotation(QwtPlot::xTop))+"\n";
514  return s;
515 }
516 
517 void Graph::setEnabledTickLabels(const QStringList& labelsOn)
518 {
519  for (int axis=0; axis<QwtPlot::axisCnt; axis++)
520  {
521  QwtScaleWidget *sc = d_plot->axisWidget(axis);
522  if (sc)
523  {
524  QwtScaleDraw *sd = d_plot->axisScaleDraw (axis);
525  sd->enableComponent (QwtAbstractScaleDraw::Labels, labelsOn[axis] == "1");
526  }
527  }
528 }
529 
530 void Graph::setMajorTicksType(const QList<int>& lst)
531 {
532  if (d_plot->getMajorTicksType() == lst)
533  return;
534 
535  for (int i=0;i<(int)lst.count();i++)
536  {
537  ScaleDraw *sd = (ScaleDraw *)d_plot->axisScaleDraw (i);
538  if (lst[i]==ScaleDraw::None || lst[i]==ScaleDraw::In)
539  sd->enableComponent (QwtAbstractScaleDraw::Ticks, false);
540  else
541  {
542  sd->enableComponent (QwtAbstractScaleDraw::Ticks);
543  sd->setTickLength (QwtScaleDiv::MinorTick, d_plot->minorTickLength());
544  sd->setTickLength (QwtScaleDiv::MediumTick, d_plot->minorTickLength());
545  sd->setTickLength (QwtScaleDiv::MajorTick, d_plot->majorTickLength());
546  }
548  }
549 }
550 
551 void Graph::setMajorTicksType(const QStringList& lst)
552 {
553  for (int i=0; i<(int)lst.count(); i++)
554  d_plot->setMajorTicksType(i, lst[i].toInt());
555 }
556 
557 void Graph::setMinorTicksType(const QList<int>& lst)
558 {
559  if (d_plot->getMinorTicksType() == lst)
560  return;
561 
562  for (int i=0;i<(int)lst.count();i++)
563  d_plot->setMinorTicksType(i, lst[i]);
564 }
565 
566 void Graph::setMinorTicksType(const QStringList& lst)
567 {
568  for (int i=0;i<(int)lst.count();i++)
569  d_plot->setMinorTicksType(i,lst[i].toInt());
570 }
571 
573 {
574  return d_plot->minorTickLength();
575 }
576 
578 {
579  return d_plot->majorTickLength();
580 }
581 
582 void Graph::setAxisTicksLength(int axis, int majTicksType, int minTicksType,
583  int minLength, int majLength)
584 {
585  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(axis);
586  if (!scale)
587  return;
588 
589  d_plot->setTickLength(minLength, majLength);
590 
591  ScaleDraw *sd = (ScaleDraw *)d_plot->axisScaleDraw (axis);
592  sd->setMajorTicksStyle((ScaleDraw::TicksStyle)majTicksType);
593  sd->setMinorTicksStyle((ScaleDraw::TicksStyle)minTicksType);
594 
595  if (majTicksType == ScaleDraw::None && minTicksType == ScaleDraw::None)
596  sd->enableComponent (QwtAbstractScaleDraw::Ticks, false);
597  else
598  sd->enableComponent (QwtAbstractScaleDraw::Ticks);
599 
600  if (majTicksType == ScaleDraw::None || majTicksType == ScaleDraw::In)
601  majLength = minLength;
602  if (minTicksType == ScaleDraw::None || minTicksType == ScaleDraw::In)
603  minLength = 0;
604 
605  sd->setTickLength (QwtScaleDiv::MinorTick, minLength);
606  sd->setTickLength (QwtScaleDiv::MediumTick, minLength);
607  sd->setTickLength (QwtScaleDiv::MajorTick, majLength);
608 }
609 
610 void Graph::setTicksLength(int minLength, int majLength)
611 {
612  QList<int> majTicksType = d_plot->getMajorTicksType();
613  QList<int> minTicksType = d_plot->getMinorTicksType();
614 
615  for (int i=0; i<4; i++)
616  setAxisTicksLength (i, majTicksType[i], minTicksType[i], minLength, majLength);
617 }
618 
619 void Graph::changeTicksLength(int minLength, int majLength)
620 {
621  if (d_plot->minorTickLength() == minLength &&
622  d_plot->majorTickLength() == majLength)
623  return;
624 
625  setTicksLength(minLength, majLength);
626 
627  d_plot->hide();
628  for (int i=0; i<4; i++)
629  {
630  if (d_plot->axisEnabled(i))
631  {
632  d_plot->enableAxis (i,false);
633  d_plot->enableAxis (i,true);
634  }
635  }
636  d_plot->replot();
637  d_plot->show();
638 
639  emit modifiedGraph();
640 }
641 
642 void Graph::showAxis(int axis, int type, const QString& formatInfo, Table *table,
643  bool axisOn, int majTicksType, int minTicksType, bool labelsOn,
644  const QColor& c, int format, int prec, int rotation, int baselineDist,
645  const QString& formula, const QColor& labelsColor)
646 {
647  d_plot->enableAxis(axis, axisOn);
648  if (!axisOn)
649  return;
650 
651  QList<int> majTicksTypeList = d_plot->getMajorTicksType();
652  QList<int> minTicksTypeList = d_plot->getMinorTicksType();
653 
654  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(axis);
655  ScaleDraw *sclDraw = (ScaleDraw *)d_plot->axisScaleDraw (axis);
656 
657  if (d_plot->axisEnabled (axis) == axisOn &&
658  majTicksTypeList[axis] == majTicksType &&
659  minTicksTypeList[axis] == minTicksType &&
660  axesColors()[axis] == COLORNAME(c) &&
661  axesNumColors()[axis] == COLORNAME(labelsColor) &&
662  prec == d_plot->axisLabelPrecision (axis) &&
663  format == d_plot->axisLabelFormat (axis) &&
664  labelsRotation(axis) == rotation &&
665  axisType[axis] == type &&
666  axesFormatInfo[axis] == formatInfo &&
667  axesFormulas[axis] == formula &&
668  scale->margin() == baselineDist &&
669  sclDraw->hasComponent (QwtAbstractScaleDraw::Labels) == labelsOn)
670  return;
671 
672  scale->setMargin(baselineDist);
673  QPalette pal = scale->palette();
674  if (pal.color(QPalette::Active, QPalette::WindowText) != c)
675  pal.setColor(QPalette::WindowText, c);
676  if (pal.color(QPalette::Active, QPalette::Text) != labelsColor)
677  pal.setColor(QPalette::Text, labelsColor);
678  scale->setPalette(pal);
679 
680  if (!labelsOn)
681  sclDraw->enableComponent (QwtAbstractScaleDraw::Labels, false);
682  else
683  {
684  switch(type) {
685  case Numeric:
686  setLabelsNumericFormat(axis, format, prec, formula);
687  break;
688  case Day:
689  setLabelsDayFormat (axis, format);
690  break;
691  case Month:
692  setLabelsMonthFormat (axis, format);
693  break;
694  case Time:
695  case Date:
696  case DateTime:
697  setLabelsDateTimeFormat (axis, type, formatInfo);
698  break;
699  case Txt:
700  setLabelsTextFormat(axis, table, formatInfo);
701  break;
702  case ColHeader:
703  setLabelsColHeaderFormat(axis, table);
704  break;
705  }
706 
707  setAxisLabelRotation(axis, rotation);
708  }
709 
710  sclDraw = (ScaleDraw *)d_plot->axisScaleDraw (axis);
711  sclDraw->enableComponent(QwtAbstractScaleDraw::Backbone, drawAxesBackbone);
712 
713  setAxisTicksLength(axis, majTicksType, minTicksType,
715 
716  if (axisOn && (axis == QwtPlot::xTop || axis == QwtPlot::yRight))
717  updateSecondaryAxis(axis);//synchronize scale divisions
718 
719  scalePicker->refresh();
720  d_plot->updateLayout(); //This is necessary in order to enable/disable tick labels
721  scale->repaint();
722  d_plot->replot();
723  emit modifiedGraph();
724 }
725 
726 void Graph::setLabelsDayFormat(int axis, int format)
727 {
728  axisType[axis] = Day;
729  axesFormatInfo[axis] = QString::number(format);
730 
731  ScaleDraw *sd_old = (ScaleDraw *)d_plot->axisScaleDraw (axis);
732  const QwtScaleDiv div = sd_old->scaleDiv ();
733 
734  WeekDayScaleDraw *sd = new WeekDayScaleDraw(*static_cast<const ScaleDraw*>(d_plot->axisScaleDraw(axis)), (WeekDayScaleDraw::NameFormat)format);
735  sd->enableComponent(QwtAbstractScaleDraw::Labels, true);
736  sd->setScaleDiv(div);
737  d_plot->setAxisScaleDraw (axis, sd);
738 }
739 
740 void Graph::setLabelsMonthFormat(int axis, int format)
741 {
742  axisType[axis] = Month;
743  axesFormatInfo[axis] = QString::number(format);
744 
745  ScaleDraw *sd_old = (ScaleDraw *)d_plot->axisScaleDraw (axis);
746  const QwtScaleDiv div = sd_old->scaleDiv ();
747 
748  MonthScaleDraw *sd = new MonthScaleDraw(*static_cast<const ScaleDraw*>(d_plot->axisScaleDraw(axis)), (MonthScaleDraw::NameFormat)format);
749  sd->enableComponent(QwtAbstractScaleDraw::Labels, true);
750  sd->setScaleDiv(div);
751  d_plot->setAxisScaleDraw (axis, sd);
752 }
753 
754 void Graph::setLabelsTextFormat(int axis, const Column *column, int startRow, int endRow) {
755  // TODO: The whole text labels functionality is very limited. Specifying
756  // only one column for the labels will always mean that the labels
757  // correspond to 1, 2, 3, 4, etc.. Other label mappings such as
758  // a -> 1.5, b -> 4.5, c -> 16.5 (with step set to 0.5) or similar
759  // require to have an additional column with numeric values.
760  // This should be supported in our new plotting framework.
761  if (!column) return;
762  future::Table *table = qobject_cast<future::Table*>(column->parentAspect());
763  if (!table) return;
764  if (axis < 0 || axis > 3) return;
765 
766  axisType[axis] = Txt;
767  axesFormatInfo[axis] = table->name() + "_" + column->name();
768 
769  QMap<int, QString> list;
770  for (int row = startRow; row <= endRow; row++)
771  if (!column->isInvalid(row))
772  list.insert(row+1, column->textAt(row));
773  QwtTextScaleDraw *sd = new QwtTextScaleDraw(*static_cast<const ScaleDraw*>(d_plot->axisScaleDraw(axis)), list);
774  sd->enableComponent(QwtAbstractScaleDraw::Labels, true);
775  d_plot->setAxisScaleDraw(axis, sd);
776 }
777 
778 void Graph::setLabelsTextFormat(int axis, Table *table, const QString& columnName) {
779  Column *col = 0;
780  if (!table || !(col = table->column(columnName))) {
781  QMessageBox::critical(this, tr("Internal Error"),
782  tr("<html>Failed to set axis labels on Graph %1. Maybe you're trying to open a corrupted"
783  " project file; or there's some problem within SciDAVis. Please report this"
784  " as a bug (together with detailed instructions how to reproduce this message or"
785  " the corrupted file).<p>"
786  "<a href=\"https://sourceforge.net/tracker/?group_id=199120&atid=968214>\">"
787  "bug tracker: https://sourceforge.net/tracker/?group_id=199120&atid=968214</a></html>")
788  .arg(objectName()));
789  return;
790  }
791  setLabelsTextFormat(axis, col, 0, col->rowCount()-1);
792 }
793 
794 void Graph::setLabelsColHeaderFormat(int axis, Table *table) {
795  if (!table) return;
796 
797  axisType[axis] = ColHeader;
798  axesFormatInfo[axis] = table->name();
799 
800  QMap<int, QString> list;
801  for (int col=0; col < table->columnCount(); col++)
802  if (table->colPlotDesignation(col) == SciDAVis::Y)
803  list.insert(col, table->colLabel(col));
804  QwtTextScaleDraw *sd = new QwtTextScaleDraw(*static_cast<const ScaleDraw*>(d_plot->axisScaleDraw(axis)), list);
805  sd->enableComponent(QwtAbstractScaleDraw::Labels, true);
806  d_plot->setAxisScaleDraw(axis, sd);
807 }
808 
809 void Graph::setLabelsDateTimeFormat(int axis, int type, const QString& formatInfo)
810 {
811  QStringList list = formatInfo.split(";", QString::KeepEmptyParts);
812  if ((int)list.count() < 2 || list[1].isEmpty()) {
813  QMessageBox::critical(this, tr("Error"), tr("Couldn't change the axis type to the requested format!"));
814  return;
815  }
816 
817  switch(type) {
818  case Time:
819  {
820  TimeScaleDraw *sd = new TimeScaleDraw (*static_cast<const ScaleDraw*>(d_plot->axisScaleDraw(axis)),
821  list[0].isEmpty() ? QTime(12,0,0,0) : QTime::fromString (list[0]), list[1]);
822  sd->enableComponent(QwtAbstractScaleDraw::Labels, true);
823  sd->enableComponent (QwtAbstractScaleDraw::Backbone, drawAxesBackbone);
824  d_plot->setAxisScaleDraw (axis, sd);
825  break;
826  }
827  case Date:
828  {
829  DateScaleDraw *sd = new DateScaleDraw(*static_cast<const ScaleDraw*>(d_plot->axisScaleDraw(axis)),
830  QDate::fromString(list[0], "yyyy-MM-dd"), list[1]);
831  sd->enableComponent(QwtAbstractScaleDraw::Labels, true);
832  sd->enableComponent (QwtAbstractScaleDraw::Backbone, drawAxesBackbone);
833  d_plot->setAxisScaleDraw (axis, sd);
834  break;
835  }
836  case DateTime:
837  {
838  DateTimeScaleDraw *sd = new DateTimeScaleDraw (*static_cast<const ScaleDraw*>(d_plot->axisScaleDraw(axis)),
839  QDateTime::fromString (list[0], "yyyy-MM-ddThh:mm:ss"), list[1]);
840  sd->enableComponent(QwtAbstractScaleDraw::Labels, true);
841  sd->enableComponent (QwtAbstractScaleDraw::Backbone, drawAxesBackbone);
842  d_plot->setAxisScaleDraw (axis, sd);
843  break;
844  }
845  default:
846  // safeguard - such an argument is invalid for this method
847  return;
848  }
849 
850  axisType[axis] = type;
851  axesFormatInfo[axis] = formatInfo;
852 }
853 
854 void Graph::setAxisLabelRotation(int axis, int rotation)
855 {
856  if (axis==QwtPlot::xBottom)
857  {
858  if (rotation > 0)
859  d_plot->setAxisLabelAlignment(axis, Qt::AlignRight|Qt::AlignVCenter);
860  else if (rotation < 0)
861  d_plot->setAxisLabelAlignment(axis, Qt::AlignLeft|Qt::AlignVCenter);
862  else if (rotation == 0)
863  d_plot->setAxisLabelAlignment(axis, Qt::AlignHCenter|Qt::AlignBottom);
864  }
865  else if (axis==QwtPlot::xTop)
866  {
867  if (rotation > 0)
868  d_plot->setAxisLabelAlignment(axis, Qt::AlignLeft|Qt::AlignVCenter);
869  else if (rotation < 0)
870  d_plot->setAxisLabelAlignment(axis, Qt::AlignRight|Qt::AlignVCenter);
871  else if (rotation == 0)
872  d_plot->setAxisLabelAlignment(axis, Qt::AlignHCenter|Qt::AlignTop);
873  }
874  d_plot->setAxisLabelRotation (axis, (double)rotation);
875 }
876 
878 {
879  ScaleDraw *sclDraw = (ScaleDraw *)d_plot->axisScaleDraw (axis);
880  return (int)sclDraw->labelRotation();
881 }
882 
883 void Graph::setYAxisTitleFont(const QFont &fnt)
884 {
885  QwtText t = d_plot->axisTitle (QwtPlot::yLeft);
886  t.setFont (fnt);
887  d_plot->setAxisTitle (QwtPlot::yLeft, t);
888  d_plot->replot();
889  emit modifiedGraph();
890 }
891 
892 void Graph::setXAxisTitleFont(const QFont &fnt)
893 {
894  QwtText t = d_plot->axisTitle (QwtPlot::xBottom);
895  t.setFont (fnt);
896  d_plot->setAxisTitle (QwtPlot::xBottom, t);
897  d_plot->replot();
898  emit modifiedGraph();
899 }
900 
901 void Graph::setRightAxisTitleFont(const QFont &fnt)
902 {
903  QwtText t = d_plot->axisTitle (QwtPlot::yRight);
904  t.setFont (fnt);
905  d_plot->setAxisTitle (QwtPlot::yRight, t);
906  d_plot->replot();
907  emit modifiedGraph();
908 }
909 
910 void Graph::setTopAxisTitleFont(const QFont &fnt)
911 {
912  QwtText t = d_plot->axisTitle (QwtPlot::xTop);
913  t.setFont (fnt);
914  d_plot->setAxisTitle (QwtPlot::xTop, t);
915  d_plot->replot();
916  emit modifiedGraph();
917 }
918 
919 void Graph::setAxisTitleFont(int axis,const QFont &fnt)
920 {
921  QwtText t = d_plot->axisTitle (axis);
922  t.setFont (fnt);
923  d_plot->setAxisTitle(axis, t);
924  d_plot->replot();
925  emit modifiedGraph();
926 }
927 
928 QFont Graph::axisTitleFont(int axis)
929 {
930  return d_plot->axisTitle(axis).font();
931 }
932 
933 QColor Graph::axisTitleColor(int axis)
934 {
935  QColor c;
936  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(axis);
937  if (scale)
938  c = scale->title().color();
939  return c;
940 }
941 
942 void Graph::setAxesNumColors(const QStringList& colors)
943 {
944  for (int i=0;i<4;i++)
945  {
946  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(i);
947  if (scale)
948  {
949  QPalette pal = scale->palette();
950  pal.setColor(QPalette::Text, QColor(COLORVALUE(colors[i])));
951  scale->setPalette(pal);
952  }
953  }
954 }
955 
956 void Graph::setAxesColors(const QStringList& colors)
957 {
958  for (int i=0;i<4;i++)
959  {
960  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(i);
961  if (scale)
962  {
963  QPalette pal =scale->palette();
964  pal.setColor(QPalette::WindowText,QColor(COLORVALUE(colors[i])));
965  scale->setPalette(pal);
966  }
967  }
968 }
969 
971 {
972  QString s="AxesColors\t";
973  QStringList colors, numColors;
974  QPalette pal;
975  int i;
976  for (i=0;i<4;i++)
977  {
978  colors << COLORNAME(QColor(Qt::black));
979  numColors << COLORNAME(QColor(Qt::black));
980  }
981 
982  for (i=0;i<4;i++)
983  {
984  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(i);
985  if (scale)
986  {
987  pal=scale->palette();
988  colors[i]=COLORNAME(pal.color(QPalette::Active, QPalette::WindowText));
989  numColors[i]=COLORNAME(pal.color(QPalette::Active, QPalette::Text));
990  }
991  }
992  s+=colors.join ("\t")+"\n";
993  s+="AxesNumberColors\t"+numColors.join ("\t")+"\n";
994  return s;
995 }
996 
997 QStringList Graph::axesColors()
998 {
999  QStringList colors;
1000  QPalette pal;
1001  int i;
1002  for (i=0;i<4;i++)
1003  colors << COLORNAME(QColor(Qt::black));
1004 
1005  for (i=0;i<4;i++)
1006  {
1007  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(i);
1008  if (scale)
1009  {
1010  pal=scale->palette();
1011  colors[i]=COLORNAME(pal.color(QPalette::Active, QPalette::WindowText));
1012  }
1013  }
1014  return colors;
1015 }
1016 
1017 QColor Graph::axisColor(int axis)
1018 {
1019  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(axis);
1020  if (scale)
1021  return scale->palette().color(QPalette::Active, QPalette::WindowText);
1022  else
1023  return QColor(Qt::black);
1024 }
1025 
1026 QColor Graph::axisNumbersColor(int axis)
1027 {
1028  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(axis);
1029  if (scale)
1030  return scale->palette().color(QPalette::Active, QPalette::Text);
1031  else
1032  return QColor(Qt::black);
1033 }
1034 
1036 {
1037  QStringList colors;
1038  QPalette pal;
1039  int i;
1040  for (i=0;i<4;i++)
1041  colors << COLORNAME(QColor(Qt::black));
1042 
1043  for (i=0;i<4;i++)
1044  {
1045  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(i);
1046  if (scale)
1047  {
1048  pal=scale->palette();
1049  colors[i]=COLORNAME(pal.color(QPalette::Active, QPalette::Text));
1050  }
1051  }
1052  return colors;
1053 }
1054 
1055 void Graph::setTitleColor(const QColor & c)
1056 {
1057  QwtText t = d_plot->title();
1058  t.setColor(c);
1059  d_plot->setTitle (t);
1060  d_plot->replot();
1061  emit modifiedGraph();
1062 }
1063 
1065 {
1066  QwtText t = d_plot->title();
1067  t.setRenderFlags(align);
1068  d_plot->setTitle (t);
1069  d_plot->replot();
1070  emit modifiedGraph();
1071 }
1072 
1073 void Graph::setTitleFont(const QFont &fnt)
1074 {
1075  QwtText t = d_plot->title();
1076  t.setFont(fnt);
1077  d_plot->setTitle (t);
1078  d_plot->replot();
1079  emit modifiedGraph();
1080 }
1081 
1082 void Graph::setYAxisTitle(const QString& text)
1083 {
1084  d_plot->setAxisTitle(QwtPlot::yLeft, text);
1085  d_plot->replot();
1086  emit modifiedGraph();
1087 }
1088 
1089 void Graph::setXAxisTitle(const QString& text)
1090 {
1091  d_plot->setAxisTitle(QwtPlot::xBottom, text);
1092  d_plot->replot();
1093  emit modifiedGraph();
1094 }
1095 
1096 void Graph::setRightAxisTitle(const QString& text)
1097 {
1098  d_plot->setAxisTitle(QwtPlot::yRight, text);
1099  d_plot->replot();
1100  emit modifiedGraph();
1101 }
1102 
1103 void Graph::setTopAxisTitle(const QString& text)
1104 {
1105  d_plot->setAxisTitle(QwtPlot::xTop, text);
1106  d_plot->replot();
1107  emit modifiedGraph();
1108 }
1109 
1111 {
1112  return d_plot->axisTitle(axis).renderFlags();
1113 }
1114 
1115 void Graph::setAxesTitlesAlignment(const QStringList& align)
1116 {
1117  for (int i=0;i<4;i++)
1118  {
1119  QwtText t = d_plot->axisTitle(i);
1120  t.setRenderFlags(align[i+1].toInt());
1121  d_plot->setAxisTitle (i, t);
1122  }
1123 }
1124 
1126 {
1127  QwtText t = d_plot->axisTitle(QwtPlot::xBottom);
1128  t.setRenderFlags(align);
1129  d_plot->setAxisTitle (QwtPlot::xBottom, t);
1130 
1131  d_plot->replot();
1132  emit modifiedGraph();
1133 }
1134 
1136 {
1137  QwtText t = d_plot->axisTitle(QwtPlot::yLeft);
1138  t.setRenderFlags(align);
1139  d_plot->setAxisTitle (QwtPlot::yLeft, t);
1140 
1141  d_plot->replot();
1142  emit modifiedGraph();
1143 }
1144 
1146 {
1147  QwtText t = d_plot->axisTitle(QwtPlot::xTop);
1148  t.setRenderFlags(align);
1149  d_plot->setAxisTitle (QwtPlot::xTop, t);
1150  d_plot->replot();
1151  emit modifiedGraph();
1152 }
1153 
1155 {
1156  QwtText t = d_plot->axisTitle(QwtPlot::yRight);
1157  t.setRenderFlags(align);
1158  d_plot->setAxisTitle (QwtPlot::yRight, t);
1159 
1160  d_plot->replot();
1161  emit modifiedGraph();
1162 }
1163 
1164 void Graph::setAxisTitle(int axis, const QString& text)
1165 {
1166  d_plot->setAxisTitle(axis, text);
1167  d_plot->replot();
1168  emit modifiedGraph();
1169 }
1170 
1171 
1172 QStringList Graph::scalesTitles()
1173 {
1174  QStringList scaleTitles;
1175  int axis;
1176  for (int i=0;i<QwtPlot::axisCnt;i++)
1177  {
1178  switch (i)
1179  {
1180  case 0:
1181  axis=2;
1182  scaleTitles<<d_plot->axisTitle(axis).text();
1183  break;
1184 
1185  case 1:
1186  axis=0;
1187  scaleTitles<<d_plot->axisTitle(axis).text();
1188  break;
1189 
1190  case 2:
1191  axis=3;
1192  scaleTitles<<d_plot->axisTitle(axis).text();
1193  break;
1194 
1195  case 3:
1196  axis=1;
1197  scaleTitles<<d_plot->axisTitle(axis).text();
1198  break;
1199  }
1200  }
1201  return scaleTitles;
1202 }
1203 
1205 {
1206  for (int i=0; i<n_curves; i++)
1207  {
1208  QwtPlotItem *it = plotItem(i);
1209  if (!it)
1210  continue;
1211 
1212  if (it->rtti() == QwtPlotItem::Rtti_PlotSpectrogram)
1213  {
1214  Spectrogram *sp = (Spectrogram *)it;
1215  if (sp->colorScaleAxis() == axis)
1216  return;
1217  }
1218 
1219  if ((axis == QwtPlot::yRight && it->yAxis() == QwtPlot::yRight) ||
1220  (axis == QwtPlot::xTop && it->xAxis () == QwtPlot::xTop))
1221  return;
1222  }
1223 
1224  int a = QwtPlot::xBottom;
1225  if (axis == QwtPlot::yRight)
1226  a = QwtPlot::yLeft;
1227 
1228  if (!d_plot->axisEnabled(a))
1229  return;
1230 
1231  QwtScaleEngine *se = d_plot->axisScaleEngine(a);
1232  const QwtScaleDiv *sd = d_plot->axisScaleDiv(a);
1233 
1234  QwtScaleEngine *sc_engine = 0;
1235  if (se->transformation()->type() == QwtScaleTransformation::Log10)
1236  sc_engine = new QwtLog10ScaleEngine();
1237  else if (se->transformation()->type() == QwtScaleTransformation::Linear)
1238  sc_engine = new QwtLinearScaleEngine();
1239 
1240  if (se->testAttribute(QwtScaleEngine::Inverted))
1241  sc_engine->setAttribute(QwtScaleEngine::Inverted);
1242 
1243  d_plot->setAxisScaleEngine (axis, sc_engine);
1244  d_plot->setAxisScaleDiv (axis, *sd);
1245 
1246  d_user_step[axis] = d_user_step[a];
1247 
1248  QwtScaleWidget *scale = d_plot->axisWidget(a);
1249  int start = scale->startBorderDist();
1250  int end = scale->endBorderDist();
1251 
1252  scale = d_plot->axisWidget(axis);
1253  scale->setMinBorderDist (start, end);
1254 }
1255 
1257 {
1258  for (int i = 0; i < QwtPlot::axisCnt; i++)
1259  d_plot->setAxisAutoScale(i);
1260 
1261  d_plot->replot();
1262  d_zoomer[0]->setZoomBase();
1263  d_zoomer[1]->setZoomBase();
1264  updateScale();
1265 
1266  emit modifiedGraph();
1267 }
1268 
1269 void Graph::setScale(int axis, double start, double end, double step, int majorTicks, int minorTicks, int type, bool inverted)
1270 {
1271  QwtScaleEngine *sc_engine = 0;
1272  if (type)
1273  sc_engine = new QwtLog10ScaleEngine();
1274  else
1275  sc_engine = new QwtLinearScaleEngine();
1276 
1277  int max_min_intervals = minorTicks;
1278  if (minorTicks == 1)
1279  max_min_intervals = 3;
1280  if (minorTicks > 1)
1281  max_min_intervals = minorTicks + 1;
1282 
1283  QwtScaleDiv div = sc_engine->divideScale (qMin(start, end), qMax(start, end), majorTicks, max_min_intervals, step);
1284  d_plot->setAxisMaxMajor (axis, majorTicks);
1285  d_plot->setAxisMaxMinor (axis, minorTicks);
1286 
1287  if (inverted){
1288  sc_engine->setAttribute(QwtScaleEngine::Inverted);
1289  div.invert();
1290  }
1291 
1292  d_plot->setAxisScaleEngine (axis, sc_engine);
1293  d_plot->setAxisScaleDiv (axis, div);
1294 
1295  d_zoomer[0]->setZoomBase();
1296  d_zoomer[1]->setZoomBase();
1297 
1298  d_user_step[axis] = step;
1299 
1300  if (axis == QwtPlot::xBottom || axis == QwtPlot::yLeft){
1301  updateSecondaryAxis(QwtPlot::xTop);
1302  updateSecondaryAxis(QwtPlot::yRight);
1303  }
1304 
1305  d_plot->replot();
1306  //keep markers on canvas area
1308  d_plot->replot();
1309 }
1310 
1312 {
1313  QStringList cList;
1314  QList<int> keys = d_plot->curveKeys();
1315  for (int i=0; i<(int)keys.count(); i++)
1316  {
1317  QwtPlotCurve *c = d_plot->curve(keys[i]);
1318  if (c && c_type[i] != ErrorBars)
1319  cList << c->title().text();
1320  }
1321 return cList;
1322 }
1323 
1324 QStringList Graph::curvesList()
1325 {
1326  QStringList cList;
1327  QList<int> keys = d_plot->curveKeys();
1328  for (int i=0; i<(int)keys.count(); i++)
1329  {
1330  QwtPlotCurve *c = d_plot->curve(keys[i]);
1331  if (c)
1332  cList << c->title().text();
1333  }
1334 return cList;
1335 }
1336 
1337 QStringList Graph::plotItemsList() const
1338 {
1339  QStringList cList;
1340  QList<int> keys = d_plot->curveKeys();
1341  for (int i=0; i<(int)keys.count(); i++)
1342  {
1343  QwtPlotItem *it = d_plot->plotItem(keys[i]);
1344  if (it)
1345  cList << it->title().text();
1346  }
1347  return cList;
1348 }
1349 
1351 {
1352  QImage image(d_plot->size(), QImage::Format_ARGB32);
1353  exportPainter(image);
1354  QApplication::clipboard()->setImage(image);
1355 }
1356 
1357 void Graph::exportToFile(const QString& fileName)
1358 {
1359  if ( fileName.isEmpty() ){
1360  QMessageBox::critical(this, tr("Error"), tr("Please provide a valid file name!"));
1361  return;
1362  }
1363 
1364  if (fileName.contains(".eps") || fileName.contains(".pdf") || fileName.contains(".ps")){
1365  exportVector(fileName);
1366  return;
1367  } else if(fileName.contains(".svg")){
1368  exportSVG(fileName);
1369  return;
1370  } else {
1371  QList<QByteArray> list = QImageWriter::supportedImageFormats();
1372  for(int i=0 ; i<list.count() ; i++){
1373  if (fileName.contains( "." + list[i].toLower())){
1374  exportImage(fileName);
1375  return;
1376  }
1377  }
1378  QMessageBox::critical(this, tr("Error"), tr("File format not handled, operation aborted!"));
1379  }
1380 }
1381 
1382 void Graph::exportImage(const QString& fileName, int quality)
1383 {
1384  QImage image(size(), QImage::Format_ARGB32);
1385  exportPainter(image);
1386  image.save(fileName, 0, quality);
1387 }
1388 
1389 void Graph::exportVector(const QString& fileName, int, bool color, bool keepAspect, QPrinter::PageSize pageSize, QPrinter::Orientation orientation)
1390 {
1391  if ( fileName.isEmpty() ){
1392  QMessageBox::critical(this, tr("Error"), tr("Please provide a valid file name!"));
1393  return;
1394  }
1395 
1396  QPrinter printer;
1397  printer.setCreator("SciDAVis");
1398  printer.setFullPage(true);
1399 
1400  printer.setOutputFileName(fileName);
1401  if (fileName.contains(".eps"))
1402  {
1403 #if QT_VERSION >= 0x050000
1404  QMessageBox::warning(this, tr("Warning"),
1405  tr("Output in postscript format is not available for Qt5, using PDF"));
1406  printer.setOutputFormat(QPrinter::PdfFormat);
1407  printer.setOutputFileName(fileName+".pdf");
1408 #else
1409  printer.setOutputFormat(QPrinter::PostScriptFormat);
1410 #endif
1411  }
1412 
1413  if (color)
1414  printer.setColorMode(QPrinter::Color);
1415  else
1416  printer.setColorMode(QPrinter::GrayScale);
1417 
1418  if (pageSize == QPrinter::Custom)
1419  printer.setPaperSize(size(), QPrinter::Point);
1420  else
1421  {
1422  printer.setOrientation(orientation);
1423  printer.setPaperSize(pageSize);
1424  }
1425 
1426  exportPainter(printer, keepAspect);
1427 }
1428 
1430 {
1431  QPrinter printer;
1432  printer.setColorMode (QPrinter::Color);
1433  printer.setFullPage(true);
1434 
1435  //printing should preserve plot aspect ratio, if possible
1436  double aspect = double(d_plot->width())/double(d_plot->height());
1437  if (aspect < 1)
1438  printer.setOrientation(QPrinter::Portrait);
1439  else
1440  printer.setOrientation(QPrinter::Landscape);
1441 
1442  QPrintDialog printDialog(&printer);
1443  if (printDialog.exec() == QDialog::Accepted)
1444  {
1445  QRect plotRect = d_plot->rect();
1446  QRect paperRect = printer.paperRect();
1447  if (d_scale_on_print)
1448  {
1449  int dpiy = printer.logicalDpiY();
1450  int margin = (int) ((2/2.54)*dpiy ); // 2 cm margins
1451 
1452  int width = qRound(aspect*printer.height()) - 2*margin;
1453  int x=qRound(abs(printer.width()- width)*0.5);
1454 
1455  plotRect = QRect(x, margin, width, printer.height() - 2*margin);
1456  if (x < margin)
1457  {
1458  plotRect.setLeft(margin);
1459  plotRect.setWidth(printer.width() - 2*margin);
1460  }
1461  }
1462  else
1463  {
1464  int x_margin = (paperRect.width() - plotRect.width())/2;
1465  int y_margin = (paperRect.height() - plotRect.height())/2;
1466  plotRect.moveTo(x_margin, y_margin);
1467  }
1468 
1469  QPainter paint(&printer);
1470  if (d_print_cropmarks)
1471  {
1472  QRect cr = plotRect; // cropmarks rectangle
1473  cr.adjust(-1, -1, 2, 2);
1474  paint.save();
1475  paint.setPen(QPen(QColor(Qt::black), 0.5, Qt::DashLine));
1476  paint.drawLine(paperRect.left(), cr.top(), paperRect.right(), cr.top());
1477  paint.drawLine(paperRect.left(), cr.bottom(), paperRect.right(), cr.bottom());
1478  paint.drawLine(cr.left(), paperRect.top(), cr.left(), paperRect.bottom());
1479  paint.drawLine(cr.right(), paperRect.top(), cr.right(), paperRect.bottom());
1480  paint.restore();
1481  }
1482 
1483  print(&paint, plotRect);
1484  }
1485 }
1486 
1487 void Graph::exportSVG(const QString& fname)
1488 {
1489 #if QT_VERSION >= 0x040300
1490  QSvgGenerator svg;
1491  svg.setFileName(fname);
1492 #if QT_VERSION >= 0x040500
1493  svg.setSize(d_plot->size());
1494  svg.setViewBox(d_plot->rect());
1495  svg.setResolution(96); // FIXME hardcored
1496  svg.setTitle(this->objectName());
1497 #endif
1498  exportPainter(svg);
1499 #endif
1500 }
1501 
1502 void Graph::exportPainter(QPaintDevice& paintDevice, bool keepAspect, QRect rect)
1503 {
1504  QPainter p(&paintDevice);
1505  exportPainter(p, keepAspect, rect, QSize(paintDevice.width(), paintDevice.height()));
1506 }
1507 
1508 void Graph::exportPainter(QPainter &painter, bool keepAspect, QRect rect, QSize size)
1509  {
1510  if (size == QSize()) size = d_plot->size();
1511  if (rect == QRect()) rect = QRect(QPoint(0,0),size);
1512  if (keepAspect)
1513  {
1514  QSize scaled = rect.size();
1515  scaled.scale(size, Qt::KeepAspectRatio);
1516  size = scaled;
1517  }
1518 
1519  painter.scale(
1520  (double)size.width()/(double)rect.width(),
1521  (double)size.height()/(double)rect.height()
1522  );
1523 
1524  print(&painter, rect);
1525  }
1526 
1528 {
1529  if (d_range_selector)
1530  return curveKey(curveIndex(d_range_selector->selectedCurve()));
1531  else
1532  return -1;
1533 }
1534 
1536 {
1537  if (d_range_selector)
1538  return d_range_selector->selectedCurve()->title().text();
1539  else
1540  return {};
1541 }
1542 
1544 {
1545  return (selectedMarker>=0);
1546 }
1547 
1549 {
1550  if (selectedMarker>=0)
1551  {
1552  if (d_markers_selector) {
1553  if (d_texts.contains(selectedMarker))
1555  else if (d_lines.contains(selectedMarker))
1557  else if (d_images.contains(selectedMarker))
1559  }
1561  d_plot->replot();
1562  emit modifiedGraph();
1563 
1565  legendMarkerID=-1;
1566 
1567  if (d_lines.contains(selectedMarker)>0)
1568  {
1569  int index = d_lines.indexOf(selectedMarker);
1570  int last_line_marker = (int)d_lines.size() - 1;
1571  for (int i=index; i < last_line_marker; i++)
1572  d_lines[i]=d_lines[i+1];
1573  d_lines.resize(last_line_marker);
1574  }
1575  else if(d_texts.contains(selectedMarker)>0)
1576  {
1577  int index=d_texts.indexOf(selectedMarker);
1578  int last_text_marker = d_texts.size() - 1;
1579  for (int i=index; i < last_text_marker; i++)
1580  d_texts[i]=d_texts[i+1];
1581  d_texts.resize(last_text_marker);
1582  }
1583  else if(d_images.contains(selectedMarker)>0)
1584  {
1585  int index=d_images.indexOf(selectedMarker);
1586  int last_image_marker = d_images.size() - 1;
1587  for (int i=index; i < last_image_marker; i++)
1588  d_images[i]=d_images[i+1];
1589  d_images.resize(last_image_marker);
1590  }
1591  selectedMarker=-1;
1592  }
1593 }
1594 
1596 {
1597  copyMarker();
1598  removeMarker();
1599 }
1600 
1602 {
1603  return (d_lines.contains(selectedMarker));
1604 }
1605 
1607 {
1608  return (d_images.contains(selectedMarker));
1609 }
1610 
1612 {
1613  if (selectedMarker<0){
1615  return ;
1616  }
1617 
1618  if (d_lines.contains(selectedMarker)){
1620  auxMrkStart=mrkL->startPoint();
1621  auxMrkEnd=mrkL->endPoint();
1623  } else if (d_images.contains(selectedMarker)){
1625  auxMrkStart=mrkI->origin();
1626  QRect rect=mrkI->rect();
1627  auxMrkEnd=rect.bottomRight();
1628  auxMrkFileName=mrkI->fileName();
1630  } else
1632 }
1633 
1635 {
1636  if (selectedMarkerType == Arrow){
1637  ArrowMarker* mrkL = new ArrowMarker();
1638  int linesOnPlot = (int)d_lines.size();
1639  d_lines.resize(++linesOnPlot);
1640  d_lines[linesOnPlot-1] = d_plot->insertMarker(mrkL);
1641 
1642  mrkL->setColor(auxMrkColor);
1643  mrkL->setWidth(auxMrkWidth);
1644  mrkL->setStyle(auxMrkStyle);
1645  mrkL->setStartPoint(QPoint(auxMrkStart.x()+10,auxMrkStart.y()+10));
1646  mrkL->setEndPoint(QPoint(auxMrkEnd.x()+10,auxMrkEnd.y()+10));
1648  mrkL->drawEndArrow(endArrowOn);
1652  } else if (selectedMarkerType==Image){
1654  int imagesOnPlot=d_images.size();
1655  d_images.resize(++imagesOnPlot);
1656  d_images[imagesOnPlot-1] = d_plot->insertMarker(mrk);
1657 
1658  QPoint o = d_plot->canvas()->mapFromGlobal(QCursor::pos());
1659  if (!d_plot->canvas()->contentsRect().contains(o))
1660  o = QPoint(auxMrkStart.x()+20, auxMrkStart.y()+20);
1661  mrk->setOrigin(o);
1662  mrk->setSize(QRect(auxMrkStart,auxMrkEnd).size());
1663  } else {
1664  Legend* mrk=new Legend(d_plot);
1665  int texts = d_texts.size();
1666  d_texts.resize(++texts);
1667  d_texts[texts-1] = d_plot->insertMarker(mrk);
1668 
1669  QPoint o=d_plot->canvas()->mapFromGlobal(QCursor::pos());
1670  if (!d_plot->canvas()->contentsRect().contains(o))
1671  o=QPoint(auxMrkStart.x()+20,auxMrkStart.y()+20);
1672  mrk->setOrigin(o);
1673  mrk->setAngle(auxMrkAngle);
1674  mrk->setFrameStyle(auxMrkBkg);
1675  mrk->setFont(auxMrkFont);
1676  mrk->setText(auxMrkText);
1677  mrk->setTextColor(auxMrkColor);
1679  }
1680 
1681  d_plot->replot();
1682  deselectMarker();
1683 }
1684 
1685 void Graph::setCopiedMarkerEnds(const QPoint& start, const QPoint& end)
1686 {
1687  auxMrkStart=start;
1688  auxMrkEnd=end;
1689 }
1690 
1691 void Graph::setCopiedTextOptions(int bkg, const QString& text, const QFont& font,
1692  const QColor& color, const QColor& bkgColor)
1693 {
1694  auxMrkBkg=bkg;
1695  auxMrkText=text;
1696  auxMrkFont=font;
1697  auxMrkColor=color;
1698  auxMrkBkgColor = bkgColor;
1699 }
1700 
1701 void Graph::setCopiedArrowOptions(int width, Qt::PenStyle style, const QColor& color,
1702  bool start, bool end, int headLength,
1703  int headAngle, bool filledHead)
1704 {
1705  auxMrkWidth=width;
1706  auxMrkStyle=style;
1707  auxMrkColor=color;
1708  startArrowOn=start;
1709  endArrowOn=end;
1710  auxArrowHeadLength=headLength;
1711  auxArrowHeadAngle=headAngle;
1712  auxFilledArrowHead=filledHead;
1713 }
1714 
1716 {
1717  return d_plot->titleLabel()->hasFocus();
1718 }
1719 
1721 {
1722  if (!d_plot->hasFocus())
1723  {
1724  emit selectedGraph(this);
1725  QwtTextLabel *title = d_plot->titleLabel();
1726  title->setFocus();
1727  }
1728 
1729  deselectMarker();
1730 }
1731 
1732 void Graph::setTitle(const QString& t)
1733 {
1734  d_plot->setTitle (t);
1735  emit modifiedGraph();
1736 }
1737 
1739 {
1740  if (d_plot->titleLabel()->hasFocus())
1741  {
1742  d_plot->setTitle(" ");
1743  emit modifiedGraph();
1744  }
1745 }
1746 
1747 void Graph::initTitle(bool on, const QFont& fnt)
1748 {
1749  if (on)
1750  {
1751  QwtText t = d_plot->title();
1752  t.setFont(fnt);
1753  t.setText(tr("Title"));
1754  d_plot->setTitle (t);
1755  }
1756 }
1757 
1759 {
1760  if (legendMarkerID >= 0)
1761  {
1762  int index = d_texts.indexOf(legendMarkerID);
1763  int texts = d_texts.size();
1764  for (int i=index; i<texts-1; i++)
1765  d_texts[i]=d_texts[i+1];
1766  d_texts.resize(--texts);
1767 
1769  legendMarkerID=-1;
1770  }
1771 }
1772 
1773 void Graph::updateImageMarker(int x, int y, int w, int h)
1774 {
1776  mrk->setRect(x, y, w, h);
1777  d_plot->replot();
1778  emit modifiedGraph();
1779 }
1780 
1781 void Graph::updateTextMarker(const QString& text,int angle, int bkg,const QFont& fnt,
1782  const QColor& textColor, const QColor& backgroundColor)
1783 {
1785  mrkL->setText(text);
1786  mrkL->setAngle(angle);
1787  mrkL->setTextColor(textColor);
1788  mrkL->setBackgroundColor(backgroundColor);
1789  mrkL->setFont(fnt);
1790  mrkL->setFrameStyle(bkg);
1791 
1792  d_plot->replot();
1793  emit modifiedGraph();
1794 }
1795 
1797 {
1798  if (legendMarkerID >=0 )
1799  return (Legend*) d_plot->marker(legendMarkerID);
1800  else
1801  return 0;
1802 }
1803 
1805 {
1806  QString text="";
1807  for (int i=0; i<n_curves; i++)
1808  {
1809  const QwtPlotCurve *c = curve(i);
1810  if (c && c->rtti() != QwtPlotItem::Rtti_PlotSpectrogram && c_type[i] != ErrorBars )
1811  {
1812  text+="\\c{";
1813  text+=QString::number(i+1);
1814  text+="}";
1815  const FunctionCurve *fc = dynamic_cast<const FunctionCurve*>(c);
1816  if (fc)
1817  text += fc->legend();
1818  else
1819  text += c->title().text();
1820  text+="\n";
1821  }
1822  }
1823  return text;
1824 }
1825 
1827 {
1828  QString text="";
1829  QList<int> keys= d_plot->curveKeys();
1830  const QwtPlotCurve *curve = (QwtPlotCurve *)d_plot->curve(keys[0]);
1831  if (curve)
1832  {
1833  for (int i=0;i<int(curve->dataSize());i++)
1834  {
1835  text+="\\p{";
1836  text+=QString::number(i+1);
1837  text+="} ";
1838  text+=QString::number(i+1);
1839  text+="\n";
1840  }
1841  }
1842  return text;
1843 }
1844 
1845 void Graph::updateCurvesData(Table* w, const QString& colName)
1846 {
1847  QList<int> keys = d_plot->curveKeys();
1848  int updated_curves = 0;
1849  QList<PlotCurve*> to_remove; // curves which changed too much to be kept
1850  for (int i=0; i<(int)keys.count(); i++)
1851  {
1852  QwtPlotItem *it = d_plot->plotItem(keys[i]);
1853  if (!it)
1854  continue;
1855  if (it->rtti() == QwtPlotItem::Rtti_PlotSpectrogram)
1856  continue;
1857  if (static_cast<PlotCurve*>(it)->type() == Function) continue;
1858  DataCurve *c = static_cast<DataCurve*>(it);
1859  if (c->table() == w && (c->xColumnName() == colName || c->yColumnName() == colName)) {
1860  int colType = w->column(colName)->columnMode();
1861  AxisType atype;
1862  if (c->xColumnName() == colName) {
1863  if (c->type() == HorizontalBars)
1864  atype = (AxisType)axisType[QwtPlot::yLeft];
1865  else
1866  atype = (AxisType)axisType[QwtPlot::xBottom];
1867  } else {
1868  if (c->type() == HorizontalBars)
1869  atype = (AxisType)axisType[QwtPlot::xBottom];
1870  else
1871  atype = (AxisType)axisType[QwtPlot::yLeft];
1872  }
1873  // compare setLabels*Format() calls in insertCurve()
1874  if ( (colType == Table::Text && atype != Txt) ||
1875  (colType == Table::Time && atype != Time) ||
1876  (colType == Table::Date && atype != Date) ||
1877  (colType == Table::DateTime && atype != DateTime))
1878  to_remove << c;
1879  else if (c->updateData(w, colName))
1880  updated_curves++;
1881  } else if(((DataCurve *)it)->updateData(w, colName))
1882  updated_curves++;
1883  }
1884  foreach (PlotCurve *c, to_remove) {
1885  removeCurve(curveIndex(c));
1886  updated_curves++;
1887  }
1888  if (updated_curves) {
1889  if (isPiePlot())
1890  updatePlot();
1891  else {
1892  if (m_autoscale) {
1893  for (int i = 0; i < QwtPlot::axisCnt; i++)
1894  d_plot->setAxisAutoScale(i);
1895  }
1896  d_plot->replot();
1897  }
1898  }
1899 }
1900 
1902 {
1903  QString list="EnabledAxes\t";
1904  for (int i = 0;i<QwtPlot::axisCnt;i++)
1905  list+=QString::number(d_plot->axisEnabled (i))+"\t";
1906 
1907  list+="\n";
1908  return list;
1909 }
1910 
1912 {
1913  return d_plot->lineWidth()>0;
1914 }
1915 
1917 {
1918  QwtPlotCanvas* canvas=(QwtPlotCanvas*) d_plot->canvas();
1919  QPalette pal =canvas->palette();
1920  return pal.color(QPalette::Active, QPalette::WindowText);
1921 }
1922 
1924 {
1925  QwtPlotCanvas* canvas=(QwtPlotCanvas*) d_plot->canvas();
1926  return canvas->lineWidth();
1927 }
1928 
1929 void Graph::drawCanvasFrame(const QStringList& frame)
1930 {
1931  d_plot->setLineWidth((frame[1]).toInt());
1932  if ((frame[1]).toInt())
1933  d_plot->setFrameStyle(QFrame::Box);
1934 
1935  QPalette pal = d_plot->palette();
1936  pal.setColor(QPalette::WindowText,QColor(COLORVALUE(frame[2])));
1937  d_plot->setPalette(pal);
1938 }
1939 
1940 void Graph::drawCanvasFrame(bool frameOn, int width, const QColor& color)
1941 {
1942  QPalette pal = d_plot->palette();
1943 
1944  if (frameOn && d_plot->lineWidth() == width &&
1945  pal.color(QPalette::Active, QPalette::WindowText) == color)
1946  return;
1947 
1948  if (frameOn)
1949  {
1950  d_plot->setLineWidth(width);
1951  pal.setColor(QPalette::WindowText,color);
1952  d_plot->setPalette(pal);
1953  }
1954  else
1955  {
1956  d_plot->setLineWidth(0);
1957  pal.setColor(QPalette::WindowText,QColor(Qt::black));
1958  d_plot->setPalette(pal);
1959  }
1960  emit modifiedGraph();
1961 }
1962 
1963 void Graph::drawCanvasFrame(bool frameOn, int width)
1964 {
1965  if (frameOn)
1966  {
1967  d_plot->setLineWidth(width);
1968  }
1969 }
1970 
1972 {
1973  if (drawAxesBackbone == yes)
1974  return;
1975 
1976  drawAxesBackbone = yes;
1977 
1978  for (int i=0; i<QwtPlot::axisCnt; i++)
1979  {
1980  QwtScaleWidget *scale=(QwtScaleWidget*) d_plot->axisWidget(i);
1981  if (scale)
1982  {
1983  ScaleDraw *sclDraw = (ScaleDraw *)d_plot->axisScaleDraw (i);
1984  sclDraw->enableComponent (QwtAbstractScaleDraw::Backbone, yes);
1985  scale->repaint();
1986  }
1987  }
1988 
1989  d_plot->replot();
1990  emit modifiedGraph();
1991 }
1992 
1993 void Graph::loadAxesOptions(const QString& s)
1994 {
1995  if (s == "1")
1996  return;
1997 
1998  drawAxesBackbone = false;
1999 
2000  for (int i=0; i<QwtPlot::axisCnt; i++)
2001  {
2002  QwtScaleWidget *scale=(QwtScaleWidget*) d_plot->axisWidget(i);
2003  if (scale)
2004  {
2005  ScaleDraw *sclDraw = (ScaleDraw *)d_plot->axisScaleDraw (i);
2006  sclDraw->enableComponent (QwtAbstractScaleDraw::Backbone, false);
2007  scale->repaint();
2008  }
2009  }
2010 }
2011 
2013 {
2014  if (d_plot->axesLinewidth() == width)
2015  return;
2016 
2017  d_plot->setAxesLinewidth(width);
2018 
2019  for (int i=0; i<QwtPlot::axisCnt; i++)
2020  {
2021  QwtScaleWidget *scale=(QwtScaleWidget*) d_plot->axisWidget(i);
2022  if (scale)
2023  {
2024  scale->setPenWidth(width);
2025  scale->repaint();
2026  }
2027  }
2028 
2029  d_plot->replot();
2030  emit modifiedGraph();
2031 }
2032 
2034 {
2035  d_plot->setAxesLinewidth(width);
2036 }
2037 
2039 {
2040  QString s="";
2041  int w = d_plot->canvas()->lineWidth();
2042  if (w>0)
2043  {
2044  s += "CanvasFrame\t" + QString::number(w)+"\t";
2045  s += COLORNAME(canvasFrameColor())+"\n";
2046  }
2047  s += "CanvasBackground\t" + COLORNAME(d_plot->canvasBackground())+"\t";
2048  s += QString::number(d_plot->canvasBackground().alpha())+"\n";
2049  return s;
2050 }
2051 
2053 {
2054  int i;
2055  QString s;
2056  QStringList list,axesList;
2057  QFont f;
2058  list<<"TitleFont";
2059  f=d_plot->title().font();
2060  list<<f.family();
2061  list<<QString::number(f.pointSize());
2062  list<<QString::number(f.weight());
2063  list<<QString::number(f.italic());
2064  list<<QString::number(f.underline());
2065  list<<QString::number(f.strikeOut());
2066  s=list.join ("\t")+"\n";
2067 
2068  for (i=0;i<d_plot->axisCnt;i++)
2069  {
2070  f=d_plot->axisTitle(i).font();
2071  list[0]="ScaleFont"+QString::number(i);
2072  list[1]=f.family();
2073  list[2]=QString::number(f.pointSize());
2074  list[3]=QString::number(f.weight());
2075  list[4]=QString::number(f.italic());
2076  list[5]=QString::number(f.underline());
2077  list[6]=QString::number(f.strikeOut());
2078  s+=list.join ("\t")+"\n";
2079  }
2080 
2081  for (i=0;i<d_plot->axisCnt;i++)
2082  {
2083  f=d_plot->axisFont(i);
2084  list[0]="AxisFont"+QString::number(i);
2085  list[1]=f.family();
2086  list[2]=QString::number(f.pointSize());
2087  list[3]=QString::number(f.weight());
2088  list[4]=QString::number(f.italic());
2089  list[5]=QString::number(f.underline());
2090  list[6]=QString::number(f.strikeOut());
2091  s+=list.join ("\t")+"\n";
2092  }
2093  return s;
2094 }
2095 
2097 {
2098  QString s;
2099  for (int i=0; i<4; i++)
2100  if (!axesFormulas[i].isEmpty())
2101  {
2102  s += "<AxisFormula pos=\""+QString::number(i)+"\">\n";
2103  s += axesFormulas[i];
2104  s += "\n</AxisFormula>\n";
2105  }
2106  return s;
2107 }
2108 
2110 {
2111  QString s;
2112  for (int i=0; i < QwtPlot::axisCnt; i++)
2113  {
2114  s += "scale\t" + QString::number(i)+"\t";
2115 
2116  const QwtScaleDiv *scDiv=d_plot->axisScaleDiv(i);
2117  QwtValueList lst = scDiv->ticks (QwtScaleDiv::MajorTick);
2118 
2119 #if QWT_VERSION >= 0x050200
2120  s += QString::number(qMin(scDiv->lowerBound(), scDiv->upperBound()), 'g', 15)+"\t";
2121  s += QString::number(qMax(scDiv->lowerBound(), scDiv->upperBound()), 'g', 15)+"\t";
2122 #else
2123  s += QString::number(qMin(scDiv->lBound(), scDiv->hBound()), 'g', 15)+"\t";
2124  s += QString::number(qMax(scDiv->lBound(), scDiv->hBound()), 'g', 15)+"\t";
2125 #endif
2126  s += QString::number(d_user_step[i], 'g', 15)+"\t";
2127  s += QString::number(d_plot->axisMaxMajor(i))+"\t";
2128  s += QString::number(d_plot->axisMaxMinor(i))+"\t";
2129 
2130  const QwtScaleEngine *sc_eng = d_plot->axisScaleEngine(i);
2131  QwtScaleTransformation *tr = sc_eng->transformation();
2132  s += QString::number((int)tr->type())+"\t";
2133  s += QString::number(sc_eng->testAttribute(QwtScaleEngine::Inverted))+"\n";
2134  }
2135  return s;
2136 }
2137 
2138 void Graph::setXAxisTitleColor(const QColor& c)
2139 {
2140  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(QwtPlot::xBottom);
2141  if (scale)
2142  {
2143  QwtText t = scale->title();
2144  t.setColor (c);
2145  scale->setTitle (t);
2146  emit modifiedGraph();
2147  }
2148 }
2149 
2150 void Graph::setYAxisTitleColor(const QColor& c)
2151 {
2152  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(QwtPlot::yLeft);
2153  if (scale)
2154  {
2155  QwtText t = scale->title();
2156  t.setColor (c);
2157  scale->setTitle (t);
2158  emit modifiedGraph();
2159  }
2160 }
2161 
2162 void Graph::setRightAxisTitleColor(const QColor& c)
2163 {
2164  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(QwtPlot::yRight);
2165  if (scale)
2166  {
2167  QwtText t = scale->title();
2168  t.setColor (c);
2169  scale->setTitle (t);
2170  emit modifiedGraph();
2171  }
2172 }
2173 
2174 void Graph::setTopAxisTitleColor(const QColor& c)
2175 {
2176  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(QwtPlot::xTop);
2177  if (scale)
2178  {
2179  QwtText t = scale->title();
2180  t.setColor (c);
2181  scale->setTitle (t);
2182  emit modifiedGraph();
2183  }
2184 }
2185 
2186 void Graph::setAxesTitleColor(QStringList l)
2187 {
2188  for (int i=0;i<int(l.count()-1);i++)
2189  {
2190  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(i);
2191  if (scale)
2192  {
2193  QwtText title = scale->title();
2194  title.setColor(QColor(COLORVALUE(l[i+1])));
2195  scale->setTitle(title);
2196  }
2197  }
2198 }
2199 
2201 {
2202  QString s="AxesTitleColors\t";
2203  for (int i=0;i<4;i++)
2204  {
2205  QwtScaleWidget *scale = (QwtScaleWidget *)d_plot->axisWidget(i);
2206  QColor c;
2207  if (scale)
2208  c=scale->title().color();
2209  else
2210  c=QColor(Qt::black);
2211 
2212  s+=COLORNAME(c)+"\t";
2213  }
2214  return s+"\n";
2215 }
2216 
2218 {
2219  QString s="PlotTitle\t";
2220  s += d_plot->title().text().replace("\n", "<br>")+"\t";
2221  s += COLORNAME(d_plot->title().color())+"\t";
2222  s += QString::number(d_plot->title().renderFlags())+"\n";
2223  return s;
2224 }
2225 
2227 {
2228  int a;
2229  QString s="";
2230  for (int i=0; i<4; i++)
2231  {
2232  switch (i)
2233  {
2234  case 0:
2235  a=2;
2236  break;
2237  case 1:
2238  a=0;
2239  break;
2240  case 2:
2241  a=3;
2242  break;
2243  case 3:
2244  a=1;
2245  break;
2246  }
2247  QString title = d_plot->axisTitle(a).text();
2248  if (!title.isEmpty())
2249  s += title.replace("\n", "<br>")+"\t";
2250  else
2251  s += "\t";
2252  }
2253  return s+"\n";
2254 }
2255 
2257 {
2258  QString s="AxesTitleAlignment\t";
2259  QStringList axes;
2260  int i;
2261  for (i=0;i<4;i++)
2262  axes<<QString::number(Qt::AlignHCenter);
2263 
2264  for (i=0;i<4;i++)
2265  {
2266 
2267  if (d_plot->axisEnabled(i))
2268  axes[i]=QString::number(d_plot->axisTitle(i).renderFlags());
2269  }
2270 
2271  s+=axes.join("\t")+"\n";
2272  return s;
2273 }
2274 
2276 {
2277  QString s="PieCurve\t";
2278 
2279  QwtPieCurve *pieCurve=(QwtPieCurve*)curve(0);
2280  s+= pieCurve->title().text()+"\t";
2281  QPen pen=pieCurve->pen();
2282 
2283  s+=QString::number(pen.width())+"\t";
2284  s+=COLORNAME(pen.color())+"\t";
2285  s+=penStyleName(pen.style()) + "\t";
2286 
2287  Qt::BrushStyle pattern=pieCurve->pattern();
2288  int index;
2289  if (pattern == Qt::SolidPattern)
2290  index=0;
2291  else if (pattern == Qt::HorPattern)
2292  index=1;
2293  else if (pattern == Qt::VerPattern)
2294  index=2;
2295  else if (pattern == Qt::CrossPattern)
2296  index=3;
2297  else if (pattern == Qt::BDiagPattern)
2298  index=4;
2299  else if (pattern == Qt::FDiagPattern)
2300  index=5;
2301  else if (pattern == Qt::DiagCrossPattern)
2302  index=6;
2303  else if (pattern == Qt::Dense1Pattern)
2304  index=7;
2305  else if (pattern == Qt::Dense2Pattern)
2306  index=8;
2307  else if (pattern == Qt::Dense3Pattern)
2308  index=9;
2309  else if (pattern == Qt::Dense4Pattern)
2310  index=10;
2311  else if (pattern == Qt::Dense5Pattern)
2312  index=11;
2313  else if (pattern == Qt::Dense6Pattern)
2314  index=12;
2315  else if (pattern == Qt::Dense7Pattern)
2316  index=13;
2317  else
2318  throw std::runtime_error("pattern out of range");
2319 
2320  s+=QString::number(index)+"\t";
2321  s+=QString::number(pieCurve->ray())+"\t";
2322  s+=QString::number(pieCurve->firstColor())+"\t";
2323  s+=QString::number(pieCurve->startRow())+"\t"+QString::number(pieCurve->endRow())+"\t";
2324  s+=QString::number(pieCurve->isVisible())+"\n";
2325  return s;
2326 }
2327 
2328 QString Graph::saveCurveLayout(int index)
2329 {
2330  QString s;
2331  int style = c_type[index];
2332  QwtPlotCurve *c = (QwtPlotCurve*)curve(index);
2333  if (c)
2334  {
2335  s+=QString::number(style)+"\t";
2336  if (style == Spline)
2337  s+="5\t";
2338  else if (style == VerticalSteps)
2339  s+="6\t";
2340  else
2341  s+=QString::number(c->style())+"\t";
2342  s+=COLORNAME(c->pen().color())+"\t";
2343  s+=QString::number(c->pen().style()-1)+"\t";
2344  s+=QString::number(c->pen().width())+"\t";
2345 
2346  const QwtSymbol symbol = c->symbol();
2347  s+=QString::number(symbol.size().width())+"\t";
2348  s+=QString::number(SymbolBox::symbolIndex(symbol.style()))+"\t";
2349  s+=COLORNAME(symbol.pen().color())+"\t";
2350  if (symbol.brush().style() != Qt::NoBrush)
2351  s+=COLORNAME(symbol.brush().color())+"\t";
2352  else
2353  s+=QString::number(-1)+"\t";
2354 
2355  bool filled = c->brush().style() == Qt::NoBrush ? false : true;
2356  s+=QString::number(filled)+"\t";
2357 
2358  s+=COLORNAME(c->brush().color())+"\t";
2359  s+=QString::number(PatternBox::patternIndex(c->brush().style()))+"\t";
2360  if (style <= LineSymbols || style == Box)
2361  s+=QString::number(symbol.pen().width())+"\t";
2362  // extension for custom dash pattern
2363  s+=QString::number(static_cast<int>(c->pen().capStyle()))+"\t";
2364  s+=QString::number(static_cast<int>(c->pen().joinStyle()))+"\t";
2365  QStringList customDash;
2366  for (auto v: c->pen().dashPattern())
2367  customDash << QString::number(v);
2368  s+=customDash.join(" ")+"\t";
2369  }
2370 
2371  if(style == VerticalBars||style == HorizontalBars||style == Histogram)
2372  {
2373  QwtBarCurve *b = (QwtBarCurve*)c;
2374  s+=QString::number(b->gap())+"\t";
2375  s+=QString::number(b->offset())+"\t";
2376  }
2377 
2378  if(style == Histogram)
2379  {
2380  QwtHistogram *h = (QwtHistogram*)c;
2381  s+=QString::number(h->autoBinning())+"\t";
2382  s+=QString::number(h->binSize())+"\t";
2383  s+=QString::number(h->begin())+"\t";
2384  s+=QString::number(h->end())+"\t";
2385  }
2386  else if(style == VectXYXY || style == VectXYAM)
2387  {
2388  VectorCurve *v = (VectorCurve*)c;
2389  s+=COLORNAME(v->color())+"\t";
2390  s+=QString::number(v->width())+"\t";
2391  s+=QString::number(v->headLength())+"\t";
2392  s+=QString::number(v->headAngle())+"\t";
2393  s+=QString::number(v->filledArrowHead())+"\t";
2394 
2395  QStringList colsList = v->plotAssociation().split(",", QString::SkipEmptyParts);
2396  s+=colsList[2].remove("(X)").remove("(A)")+"\t";
2397  s+=colsList[3].remove("(Y)").remove("(M)");
2398  if (style == VectXYAM)
2399  s+="\t"+QString::number(v->position());
2400  s+="\t";
2401  }
2402  else if(style == Box)
2403  {
2404  BoxCurve *b = (BoxCurve*)c;
2405  s+=QString::number(SymbolBox::symbolIndex(b->maxStyle()))+"\t";
2406  s+=QString::number(SymbolBox::symbolIndex(b->p99Style()))+"\t";
2407  s+=QString::number(SymbolBox::symbolIndex(b->meanStyle()))+"\t";
2408  s+=QString::number(SymbolBox::symbolIndex(b->p1Style()))+"\t";
2409  s+=QString::number(SymbolBox::symbolIndex(b->minStyle()))+"\t";
2410  s+=QString::number(b->boxStyle())+"\t";
2411  s+=QString::number(b->boxWidth())+"\t";
2412  s+=QString::number(b->boxRangeType())+"\t";
2413  s+=QString::number(b->boxRange())+"\t";
2414  s+=QString::number(b->whiskersRangeType())+"\t";
2415  s+=QString::number(b->whiskersRange())+"\t";
2416  }
2417 
2418  return s;
2419 }
2420 
2422 {
2423  QString s;
2424  if (isPiePlot())
2425  s+=savePieCurveLayout();
2426  else
2427  {
2428  for (int i=0; i<n_curves; i++)
2429  {
2430  QwtPlotItem *it = plotItem(i);
2431  if (!it)
2432  continue;
2433 
2434  if (it->rtti() == QwtPlotItem::Rtti_PlotSpectrogram)
2435  {
2436  s += ((Spectrogram *)it)->saveToString();
2437  continue;
2438  }
2439 
2440  PlotCurve *c = static_cast<PlotCurve *>(it);
2441  if (c->type() != ErrorBars)
2442  {
2443  if (c->type() == Function) {
2444  s += "FunctionCurve\t";
2445  s += QString::number(static_cast<FunctionCurve*>(c)->functionType()) + ",";
2446  s += c->title().text() + ",";
2447  s += static_cast<FunctionCurve*>(c)->variable() + ",";
2448  s += QString::number(static_cast<FunctionCurve*>(c)->startRange(),'g',15)+",";
2449  s += QString::number(static_cast<FunctionCurve*>(c)->endRange(),'g',15)+"\t";
2450  s += QString::number(static_cast<FunctionCurve*>(c)->dataSize())+"\t\t\t";
2451  //the 2 last tabs are legacy code, kept for compatibility with old project files
2452  } else if (c->type() == Box)
2453  s += "curve\t" + QString::number(c->x(0)) + "\t" + c->title().text() + "\t";
2454  else
2455  s += "curve\t" + static_cast<DataCurve*>(c)->xColumnName() + "\t" + c->title().text() + "\t";
2456 
2457  s += saveCurveLayout(i);
2458  s += QString::number(c->xAxis())+"\t"+QString::number(c->yAxis())+"\t";
2459  s += QString::number(static_cast<DataCurve*>(c)->startRow())+"\t"+QString::number(static_cast<DataCurve*>(c)->endRow())+"\t";
2460  s += QString::number(c->isVisible())+"\n";
2461  if (c->type() == Function) {
2462  s += "<formula>\n" + static_cast<FunctionCurve*>(c)->formulas().join("\n</formula>\n<formula>\n") + "\n</formula>\n";
2463  }
2464  }
2465  else if (c->type() == ErrorBars)
2466  {
2468  s += "ErrorBars\t";
2469  s += QString::number(er->direction())+"\t";
2470  s += er->masterCurve()->xColumnName() + "\t";
2471  s += er->masterCurve()->title().text() + "\t";
2472  s += er->title().text() + "\t";
2473  s += QString::number(er->width())+"\t";
2474  s += QString::number(er->capLength())+"\t";
2475  s += COLORNAME(er->color())+"\t";
2476  s += QString::number(er->throughSymbol())+"\t";
2477  s += QString::number(er->plusSide())+"\t";
2478  s += QString::number(er->minusSide())+"\n";
2479  }
2480  }
2481  }
2482  return s;
2483 }
2484 
2486 {
2487  Legend* mrk = new Legend(d_plot);
2488  mrk->setOrigin(QPoint(10, 10));
2489 
2490  if (isPiePlot())
2491  mrk->setText(pieLegendText());
2492  else
2493  mrk->setText(legendText());
2494 
2496  mrk->setFont(defaultMarkerFont);
2499 
2501  int texts = d_texts.size();
2502  d_texts.resize(++texts);
2503  d_texts[texts-1] = legendMarkerID;
2504 
2505  emit modifiedGraph();
2506  d_plot->replot();
2507  return mrk;
2508 }
2509 
2511 {
2512  Legend* mrk= newLegend(QDateTime::currentDateTime().toString(Qt::LocalDate));
2513  mrk->setOrigin(QPoint(d_plot->canvas()->width()/2, 10));
2514  emit modifiedGraph();
2515  d_plot->replot();
2516 }
2517 
2518 Legend* Graph::newLegend(const QString& text)
2519 {
2520  Legend* mrk = new Legend(d_plot);
2522  if(d_markers_selector)
2523  delete d_markers_selector;
2524 
2525  int texts = d_texts.size();
2526  d_texts.resize(++texts);
2527  d_texts[texts-1] = selectedMarker;
2528 
2529  mrk->setOrigin(QPoint(5,5));
2530  mrk->setText(text);
2532  mrk->setFont(defaultMarkerFont);
2535  return mrk;
2536 }
2537 
2538 void Graph::insertLegend(const QStringList& lst, int fileVersion)
2539 {
2540  legendMarkerID = insertTextMarker(lst, fileVersion);
2541 }
2542 
2543 long Graph::insertTextMarker(const QStringList& list, int fileVersion)
2544 {
2545  QStringList fList=list;
2546  Legend* mrk = new Legend(d_plot);
2547  long key = d_plot->insertMarker(mrk);
2548 
2549  int texts = d_texts.size();
2550  d_texts.resize(++texts);
2551  d_texts[texts-1] = key;
2552 
2553  if (fileVersion < 86)
2554  mrk->setOrigin(QPoint(fList[1].toInt(),fList[2].toInt()));
2555  else
2556  mrk->setOriginCoord(fList[1].toDouble(), fList[2].toDouble());
2557 
2558  QFont fnt=QFont (fList[3],fList[4].toInt(),fList[5].toInt(),fList[6].toInt());
2559  fnt.setUnderline(fList[7].toInt());
2560  fnt.setStrikeOut(fList[8].toInt());
2561  mrk->setFont(fnt);
2562 
2563  mrk->setAngle(fList[11].toInt());
2564 
2565  QString text = QString();
2566  if (fileVersion < 71)
2567  {
2568  int bkg=fList[10].toInt();
2569  if (bkg <= 2)
2570  mrk->setFrameStyle(bkg);
2571  else if (bkg == 3)
2572  {
2573  mrk->setFrameStyle(0);
2574  mrk->setBackgroundColor(QColor(255, 255, 255));
2575  }
2576  else if (bkg == 4)
2577  {
2578  mrk->setFrameStyle(0);
2579  mrk->setBackgroundColor(QColor(Qt::black));
2580  }
2581 
2582  int n =(int)fList.count();
2583  for (int i=0;i<n-12;i++)
2584  text += fList[12+i]+"\n";
2585  }
2586  else if (fileVersion < 90)
2587  {
2588  mrk->setTextColor(QColor(COLORVALUE(fList[9])));
2589  mrk->setFrameStyle(fList[10].toInt());
2590  mrk->setBackgroundColor(QColor(COLORVALUE(fList[12])));
2591 
2592  int n=(int)fList.count();
2593  for (int i=0;i<n-13;i++)
2594  text += fList[13+i]+"\n";
2595  }
2596  else
2597  {
2598  mrk->setTextColor(QColor(COLORVALUE(fList[9])));
2599  mrk->setFrameStyle(fList[10].toInt());
2600  QColor c = QColor(COLORVALUE(fList[12]));
2601  c.setAlpha(fList[13].toInt());
2602  mrk->setBackgroundColor(c);
2603 
2604  int n = (int)fList.count();
2605  for (int i=0; i<n-14; i++)
2606  text += fList[14+i]+"\n";
2607  }
2608  mrk->setText(text.trimmed());
2609  return key;
2610 }
2611 
2612 void Graph::addArrow(QStringList list, int fileVersion)
2613 {
2614  ArrowMarker* mrk = new ArrowMarker();
2615  long mrkID=d_plot->insertMarker(mrk);
2616  int linesOnPlot = (int)d_lines.size();
2617  d_lines.resize(++linesOnPlot);
2618  d_lines[linesOnPlot-1]=mrkID;
2619 
2620  if (fileVersion < 86)
2621  {
2622  mrk->setStartPoint(QPoint(list[1].toInt(), list[2].toInt()));
2623  mrk->setEndPoint(QPoint(list[3].toInt(), list[4].toInt()));
2624  }
2625  else
2626  mrk->setBoundingRect(list[1].toDouble(), list[2].toDouble(),
2627  list[3].toDouble(), list[4].toDouble());
2628 
2629  mrk->setWidth(list[5].toInt());
2630  mrk->setColor(QColor(COLORVALUE(list[6])));
2631  mrk->setStyle(getPenStyle(list[7]));
2632  mrk->drawEndArrow(list[8]=="1");
2633  mrk->drawStartArrow(list[9]=="1");
2634  if (list.count()>10)
2635  {
2636  mrk->setHeadLength(list[10].toInt());
2637  mrk->setHeadAngle(list[11].toInt());
2638  mrk->fillArrowHead(list[12]=="1");
2639  }
2640  if (list.count()>13)
2641  {
2642  mrk->setCapStyle(static_cast<Qt::PenCapStyle>(list[13].toInt()));
2643  mrk->setJoinStyle(static_cast<Qt::PenJoinStyle>(list[14].toInt()));
2644  QVector<qreal> customDash;
2645  for (auto v: list[15].split(" ")) customDash << v.toDouble();
2646  QPen pen = mrk->linePen();
2647  if (mrk->style()==Qt::CustomDashLine)
2648  pen.setDashPattern(customDash);
2649  mrk->setLinePen(pen);
2650  }
2651 }
2652 
2654 {
2655  ArrowMarker* aux = new ArrowMarker();
2656  int linesOnPlot = (int)d_lines.size();
2657  d_lines.resize(++linesOnPlot);
2658  d_lines[linesOnPlot-1] = d_plot->insertMarker(aux);
2659 
2660  aux->setBoundingRect(mrk->startPointCoord().x(), mrk->startPointCoord().y(),
2661  mrk->endPointCoord().x(), mrk->endPointCoord().y());
2662  aux->setWidth(mrk->width());
2663  aux->setColor(mrk->color());
2664  aux->setStyle(mrk->style());
2665  aux->drawEndArrow(mrk->hasEndArrow());
2666  aux->drawStartArrow(mrk->hasStartArrow());
2667  aux->setHeadLength(mrk->headLength());
2668  aux->setHeadAngle(mrk->headAngle());
2669  aux->fillArrowHead(mrk->filledArrowHead());
2670 }
2671 
2673 {
2674  return (ArrowMarker*)d_plot->marker(id);
2675 }
2676 
2678 {
2679  return (ImageMarker*)d_plot->marker(id);
2680 }
2681 
2683 {
2684  return (Legend*)d_plot->marker(id);
2685 }
2686 
2688 {
2689  Legend* aux = new Legend(d_plot);
2691  if(d_markers_selector)
2692  delete d_markers_selector;
2693 
2694  int texts = d_texts.size();
2695  d_texts.resize(++texts);
2696  d_texts[texts-1] = selectedMarker;
2697 
2698  aux->setTextColor(mrk->textColor());
2699  aux->setBackgroundColor(mrk->backgroundColor());
2700  aux->setOriginCoord(mrk->xValue(), mrk->yValue());
2701  aux->setFont(mrk->font());
2702  aux->setFrameStyle(mrk->frameStyle());
2703  aux->setAngle(mrk->angle());
2704  aux->setText(mrk->text());
2705  return selectedMarker;
2706 }
2707 
2709 {
2710  QString s;
2711  int t = d_texts.size(), l = d_lines.size(), im = d_images.size();
2712  for (int i=0; i<im; i++)
2713  {
2715  s += "<image>\t";
2716  s += mrkI->fileName()+"\t";
2717  s += QString::number(mrkI->xValue(), 'g', 15)+"\t";
2718  s += QString::number(mrkI->yValue(), 'g', 15)+"\t";
2719  s += QString::number(mrkI->right(), 'g', 15)+"\t";
2720  s += QString::number(mrkI->bottom(), 'g', 15)+"</image>\n";
2721  }
2722 
2723  for (int i=0; i<l; i++)
2724  {
2726  s+="<line>\t";
2727 
2728  QwtDoublePoint sp = mrkL->startPointCoord();
2729  s+=(QString::number(sp.x(), 'g', 15))+"\t";
2730  s+=(QString::number(sp.y(), 'g', 15))+"\t";
2731 
2732  QwtDoublePoint ep = mrkL->endPointCoord();
2733  s+=(QString::number(ep.x(), 'g', 15))+"\t";
2734  s+=(QString::number(ep.y(), 'g', 15))+"\t";
2735 
2736  s+=QString::number(mrkL->width())+"\t";
2737  s+=COLORNAME(mrkL->color())+"\t";
2738  s+=penStyleName(mrkL->style())+"\t";
2739  s+=QString::number(mrkL->hasEndArrow())+"\t";
2740  s+=QString::number(mrkL->hasStartArrow())+"\t";
2741  s+=QString::number(mrkL->headLength())+"\t";
2742  s+=QString::number(mrkL->headAngle())+"\t";
2743  s+=QString::number(mrkL->filledArrowHead())+"\t";
2744  s+=QString::number(static_cast<int>(mrkL->capStyle()))+"\t";
2745  s+=QString::number(static_cast<int>(mrkL->joinStyle()))+"\t";
2746  QStringList customDash;
2747  for (auto v: mrkL->linePen().dashPattern())
2748  customDash << QString::number(v);
2749  s+=customDash.join(" ");
2750  s+="</line>\n";
2751  }
2752 
2753  for (int i=0; i<t; i++)
2754  {
2755  Legend* mrk=(Legend*) d_plot->marker(d_texts[i]);
2756  if (d_texts[i] != legendMarkerID)
2757  s+="<text>\t";
2758  else
2759  s+="<legend>\t";
2760 
2761  s+=QString::number(mrk->xValue(), 'g', 15)+"\t";
2762  s+=QString::number(mrk->yValue(), 'g', 15)+"\t";
2763 
2764  QFont f=mrk->font();
2765  s+=f.family()+"\t";
2766  s+=QString::number(f.pointSize())+"\t";
2767  s+=QString::number(f.weight())+"\t";
2768  s+=QString::number(f.italic())+"\t";
2769  s+=QString::number(f.underline())+"\t";
2770  s+=QString::number(f.strikeOut())+"\t";
2771  s+=COLORNAME(mrk->textColor())+"\t";
2772  s+=QString::number(mrk->frameStyle())+"\t";
2773  s+=QString::number(mrk->angle())+"\t";
2774  s+=COLORNAME(mrk->backgroundColor())+"\t";
2775  s+=QString::number(mrk->backgroundColor().alpha())+"\t";
2776 
2777  QStringList textList=mrk->text().split("\n", QString::KeepEmptyParts);
2778  s+=textList.join ("\t");
2779  if (d_texts[i]!=legendMarkerID)
2780  s+="</text>\n";
2781  else
2782  s+="</legend>\n";
2783  }
2784  return s;
2785 }
2786 
2788 {
2789  if (d_range_selector)
2790  return d_range_selector->minXValue();
2791  else
2792  return 0;
2793 }
2794 
2796 {
2797  if (d_range_selector)
2798  return d_range_selector->maxXValue();
2799  else
2800  return 0;
2801 }
2802 
2803 QwtPlotItem* Graph::plotItem(int index)
2804 {
2805  if (!n_curves || index >= n_curves || index < 0)
2806  return 0;
2807 
2808  return d_plot->plotItem(c_keys[index]);
2809 }
2810 
2811 int Graph::plotItemIndex(QwtPlotItem *it) const
2812 {
2813  for (int i = 0; i < n_curves; i++)
2814  {
2815  if (d_plot->plotItem(c_keys[i]) == it)
2816  return i;
2817  }
2818  return -1;
2819 }
2820 
2821 QwtPlotCurve *Graph::curve(int index) const
2822 {
2823  if (!n_curves || index >= n_curves || index < 0)
2824  return 0;
2825 
2826  return d_plot->curve(c_keys[index]);
2827 }
2828 
2829 int Graph::curveIndex(QwtPlotCurve *c) const
2830 {
2831  return plotItemIndex(c);
2832 }
2833 
2834 int Graph::range(int index, double *start, double *end)
2835 {
2836  if (d_range_selector && d_range_selector->selectedCurve() == curve(index)) {
2837  *start = d_range_selector->minXValue();
2838  *end = d_range_selector->maxXValue();
2839  return d_range_selector->dataSize();
2840  } else {
2841  QwtPlotCurve *c = curve(index);
2842  if (!c)
2843  return 0;
2844 
2845  *start = c->x(0);
2846  *end = c->x(c->dataSize() - 1);
2847  return c->dataSize();
2848  }
2849 }
2850 
2852 {
2853  CurveLayout cl;
2854  cl.connectType=1;
2855  cl.lStyle=0;
2856  cl.lWidth=1;
2857  cl.sSize=7;
2858  cl.sType=0;
2859  cl.filledArea=0;
2860  cl.aCol=0;
2861  cl.aStyle=0;
2862  cl.lCol=0;
2863  cl.penWidth = 1;
2864  cl.symCol=0;
2865  cl.fillCol=0;
2866  return cl;
2867 }
2868 
2869 CurveLayout Graph::initCurveLayout(int style, int curves)
2870 {
2871  int i = n_curves - 1;
2872 
2874  int color;
2875  guessUniqueCurveLayout(color, cl.sType);
2876 
2877  cl.lCol = color;
2878  cl.symCol = color;
2879  cl.fillCol = color;
2880 
2881  if (style == Graph::Line)
2882  cl.sType = 0;
2883  else if (style == Graph::VerticalDropLines)
2884  cl.connectType=2;
2885  else if (style == Graph::HorizontalSteps || style == Graph::VerticalSteps)
2886  {
2887  cl.connectType=3;
2888  cl.sType = 0;
2889  }
2890  else if (style == Graph::Spline)
2891  cl.connectType=5;
2892  else if (curves && (style == Graph::VerticalBars || style == Graph::HorizontalBars))
2893  {
2894  cl.filledArea=1;
2895  cl.lCol=0;//black color pen
2896  cl.aCol=i+1;
2897  cl.sType = 0;
2898  if (style == Graph::VerticalBars || style == Graph::HorizontalBars)
2899  {
2900  QwtBarCurve *b = (QwtBarCurve*)curve(i);
2901  if (b)
2902  {
2903  b->setGap(qRound(100*(1-1.0/(double)curves)));
2904  b->setOffset(-50*(curves-1) + i*100);
2905  }
2906  }
2907  }
2908  else if (style == Graph::Histogram)
2909  {
2910  cl.filledArea=1;
2911  cl.lCol=i+1;//start with red color pen
2912  cl.aCol=i+1; //start with red fill color
2913  cl.aStyle=4;
2914  cl.sType = 0;
2915  }
2916  else if (style== Graph::Area)
2917  {
2918  cl.filledArea=1;
2919  cl.aCol= color;
2920  cl.sType = 0;
2921  }
2922  return cl;
2923 }
2924 
2925 bool Graph::canConvertTo(QwtPlotCurve *c, CurveType type)
2926 {
2927  if (!c) return false;
2928  // conversion between VectXYXY and VectXYAM is possible, but not implemented
2929  if (dynamic_cast<VectorCurve*>(c))
2930  return false;
2931  // conversion between Pie, Histogram and Box should be possible (all of them take one input column),
2932  // but lots of special-casing in ApplicationWindow and Graph makes this very difficult
2933  if (dynamic_cast<QwtPieCurve*>(c) || dynamic_cast<QwtHistogram*>(c) || dynamic_cast<BoxCurve*>(c))
2934  return false;
2935  // converting error bars doesn't make sense
2936  if (dynamic_cast<QwtErrorPlotCurve*>(c))
2937  return false;
2938  // line/symbol, area and bar curves can be converted to each other
2939  if (dynamic_cast<DataCurve*>(c))
2940  return
2941  type == Line || type == Scatter || type == LineSymbols ||
2942  type == VerticalBars || type == HorizontalBars ||
2943  type == HorizontalSteps || type == VerticalSteps ||
2944  type == Area || type == VerticalDropLines ||
2945  type == Spline;
2946  return false;
2947 }
2948 
2949 void Graph::setCurveType(int curve_index, CurveType type, bool update)
2950 {
2951  if (curve_index>=c_type.size()) return;
2952  CurveType old_type = static_cast<CurveType>(c_type[curve_index]);
2953  // nothing changed
2954  if (type == old_type) return;
2955  // not all types can be modified cleanly
2956  if (type != Line && type != Scatter && type != LineSymbols && type != VerticalBars
2957  && type != Area && type != VerticalDropLines && type != Spline && type != HorizontalSteps
2958  && type != HorizontalBars && type != VerticalSteps)
2959  return;
2960  if (old_type != Line && old_type != Scatter && old_type != LineSymbols && old_type != VerticalBars
2961  && old_type != Area && old_type != VerticalDropLines && old_type != Spline && old_type != HorizontalSteps
2962  && old_type != HorizontalBars && old_type != VerticalSteps)
2963  return;
2964 
2965  if ((type == VerticalBars || type == HorizontalBars)
2966  != (old_type == VerticalBars || old_type == HorizontalBars)) {
2967  // bar curves are represented by a different class than the other curve types, which makes
2968  // changing from/to horizontal or vertical bars more difficult
2969  DataCurve *old_curve = static_cast<DataCurve*>(curve(curve_index));
2970  DataCurve *new_curve = 0;
2971  switch (type) {
2972  case Histogram:
2973  case Box:
2974  case Pie:
2975  return;
2976  case VerticalBars:
2977  new_curve = new QwtBarCurve(QwtBarCurve::Vertical,
2978  old_curve->table(), old_curve->xColumnName(), old_curve->yColumnName(),
2979  old_curve->startRow(), old_curve->endRow());
2980  new_curve->setStyle(QwtPlotCurve::UserCurve);
2981  break;
2982  case HorizontalBars:
2983  new_curve = new QwtBarCurve(QwtBarCurve::Horizontal,
2984  old_curve->table(), old_curve->xColumnName(), old_curve->yColumnName(),
2985  old_curve->startRow(), old_curve->endRow());
2986  new_curve->setStyle(QwtPlotCurve::UserCurve);
2987  break;
2988  default:
2989  new_curve = new DataCurve(
2990  old_curve->table(), old_curve->xColumnName(), old_curve->yColumnName(),
2991  old_curve->startRow(), old_curve->endRow());
2992  break;
2993  }
2994 
2995  old_curve->clearErrorBars();
2996  if (int i = d_fit_curves.indexOf(old_curve) >= 0)
2997  d_fit_curves.replace(i, new_curve);
2998 
2999  d_plot->removeCurve(c_keys[curve_index]);
3000  c_keys[curve_index] = d_plot->insertCurve(new_curve);
3001  new_curve->loadData();
3002 
3003  if (d_range_selector && old_curve == d_range_selector->selectedCurve())
3004  d_range_selector->setSelectedCurve(new_curve);
3005  }
3006 
3007  c_type[curve_index] = type;
3008  if (!update) return;
3009 
3010  CurveLayout cl = initCurveLayout(type, 1);
3011  updateCurveLayout(curve_index, &cl);
3012  updatePlot();
3013 }
3014 
3015 void Graph::updateCurveLayout(int index, const CurveLayout *cL)
3016 {
3017  DataCurve *c = (DataCurve *)this->curve(index);
3018  if (!c)
3019  return;
3020  if (c_type.isEmpty() || (int)c_type.size() < index)
3021  return;
3022 
3023  QPen pen = QPen(ColorButton::color(cL->symCol),cL->penWidth, Qt::SolidLine);
3024  if (cL->symbolFill)
3025  c->setSymbol(QwtSymbol(SymbolBox::style(cL->sType), QBrush(ColorButton::color(cL->fillCol)), pen, QSize(cL->sSize,cL->sSize)));
3026  else
3027  c->setSymbol(QwtSymbol(SymbolBox::style(cL->sType), QBrush(), pen, QSize(cL->sSize,cL->sSize)));
3028 
3029  // custom dash pattern
3030  pen = QPen(ColorButton::color(cL->lCol), cL->lWidth, getPenStyle(cL->lStyle));
3031  pen.setCapStyle(static_cast<Qt::PenCapStyle>(cL->lCapStyle));
3032  pen.setJoinStyle(static_cast<Qt::PenJoinStyle>(cL->lJoinStyle));
3033  QVector<qreal> customDash;
3034  for (auto v: (cL->lCustomDash).split(" ", QString::SkipEmptyParts))
3035  customDash << v.toDouble();
3036  if (pen.style()==Qt::CustomDashLine)
3037  pen.setDashPattern(customDash);
3038  c->setPen(pen);
3039 
3040  int style = c_type[index];
3041  if (style == Scatter)
3042  c->setStyle(QwtPlotCurve::NoCurve);
3043  else if (style == Spline)
3044  {
3045  c->setStyle(QwtPlotCurve::Lines);
3046  c->setCurveAttribute(QwtPlotCurve::Fitted, true);
3047  }
3048  else if (style == VerticalSteps)
3049  {
3050  c->setStyle(QwtPlotCurve::Steps);
3051  c->setCurveAttribute(QwtPlotCurve::Inverted, true);
3052  }
3053  else
3054  c->setStyle((QwtPlotCurve::CurveStyle)cL->connectType);
3055 
3056  QBrush brush = QBrush(ColorButton::color(cL->aCol));
3057  if (cL->filledArea)
3058  brush.setStyle(getBrushStyle(cL->aStyle));
3059  else
3060  brush.setStyle(Qt::NoBrush);
3061  c->setBrush(brush);
3062 }
3063 
3064 void Graph::updateErrorBars(QwtErrorPlotCurve *er, bool xErr, int width, int cap, const QColor& c,
3065  bool plus, bool minus, bool through)
3066 {
3067  if (!er)
3068  return;
3069 
3070  if (er->width() == width &&
3071  er->capLength() == cap &&
3072  er->color() == c &&
3073  er->plusSide() == plus &&
3074  er->minusSide() == minus &&
3075  er->throughSymbol() == through &&
3076  er->xErrors() == xErr)
3077  return;
3078 
3079  er->setWidth(width);
3080  er->setCapLength(cap);
3081  er->setColor(c);
3082  er->setXErrors(xErr);
3083  er->drawThroughSymbol(through);
3084  er->drawPlusSide(plus);
3085  er->drawMinusSide(minus);
3086 
3087  d_plot->replot();
3088  emit modifiedGraph();
3089 }
3090 
3091 bool Graph::addErrorBars(const QString& yColName, Table *errTable, const QString& errColName,
3092  int type, int width, int cap, const QColor& color, bool through, bool minus, bool plus)
3093 {
3094  QList<int> keys = d_plot->curveKeys();
3095  for (int i = 0; i<n_curves; i++ )
3096  {
3097  DataCurve *c = (DataCurve *)d_plot->curve(keys[i]);
3098  if (c && c->title().text() == yColName && c_type[i] != ErrorBars)
3099  {
3100  return addErrorBars(c->xColumnName(), yColName, errTable, errColName,
3101  type, width, cap, color, through, minus, plus);
3102  }
3103  }
3104  return false;
3105 }
3106 
3107 bool Graph::addErrorBars(const QString& xColName, const QString& yColName,
3108  Table *errTable, const QString& errColName, int type, int width, int cap,
3109  const QColor& color, bool through, bool minus, bool plus)
3110 {
3111  DataCurve *master_curve = masterCurve(xColName, yColName);
3112  if (!master_curve)
3113  return false;
3114 
3115  QwtErrorPlotCurve *er = new QwtErrorPlotCurve(type, errTable, errColName);
3116  er->setMasterCurve(master_curve);
3117  er->setCapLength(cap);
3118  er->setColor(color);
3119  er->setWidth(width);
3120  er->drawPlusSide(plus);
3121  er->drawMinusSide(minus);
3122  er->drawThroughSymbol(through);
3123 
3124  c_type.resize(++n_curves);
3125  c_type[n_curves-1] = ErrorBars;
3126 
3127  c_keys.resize(n_curves);
3128  c_keys[n_curves-1] = d_plot->insertCurve(er);
3129 
3130  updatePlot();
3131  return true;
3132 }
3133 
3134 void Graph::plotPie(Table* w, const QString& name, const QPen& pen, int brush,
3135  int size, int firstColor, int startRow, int endRow, bool visible)
3136 {
3137  if (endRow < 0)
3138  endRow = w->numRows() - 1;
3139 
3140  QwtPieCurve *pieCurve = new QwtPieCurve(w, name, startRow, endRow);
3141  pieCurve->loadData();
3142  pieCurve->setPen(pen);
3143  pieCurve->setRay(size);
3144  pieCurve->setFirstColor(firstColor);
3145  pieCurve->setBrushStyle(getBrushStyle(brush));
3146  pieCurve->setVisible(visible);
3147 
3148  c_keys.resize(++n_curves);
3149  c_keys[n_curves-1] = d_plot->insertCurve(pieCurve);
3150 
3151  c_type.resize(n_curves);
3152  c_type[n_curves-1] = Pie;
3153 }
3154 
3155 void Graph::plotPie(Table* w, const QString& name, int startRow, int endRow)
3156 {
3157  int ycol = w->colIndex(name);
3158  int size = 0;
3159  double sum = 0.0;
3160 
3161  Column *y_col_ptr = w->column(ycol);
3162  int yColType = w->columnType(ycol);
3163 
3164  if (endRow < 0)
3165  endRow = w->numRows() - 1;
3166 
3167  for (int i=0; i<QwtPlot::axisCnt; i++)
3168  d_plot->enableAxis(i, false);
3169  scalePicker->refresh();
3170 
3171  d_plot->setTitle(QString());
3172 
3173  static_cast<QwtPlotCanvas*>(d_plot->canvas())->setLineWidth(1);
3174 
3175  QVarLengthArray<double> Y(abs(endRow - startRow) + 1);
3176  for (int row = startRow; row<= endRow && row<y_col_ptr->rowCount(); row++) {
3177  if (!y_col_ptr->isInvalid(row)) {
3178  if (yColType == Table::Text) {
3179  QString yval = y_col_ptr->textAt(row);
3180  bool valid_data = true;
3181  Y[size] = QLocale().toDouble(yval, &valid_data);
3182  if (!valid_data)
3183  continue;
3184  }
3185  else
3186  Y[size] = y_col_ptr->valueAt(row);
3187 
3188  sum += Y[size];
3189  size++;
3190  }
3191  }
3192  if (!size)
3193  return;
3194  Y.resize(size);
3195 
3196  QwtPieCurve *pieCurve = new QwtPieCurve(w, name, startRow, endRow);
3197  pieCurve->setData(Y.data(), Y.data(), size);
3198 
3199  c_keys.resize(++n_curves);
3200  c_keys[n_curves-1] = d_plot->insertCurve(pieCurve);
3201 
3202  c_type.resize(n_curves);
3203  c_type[n_curves-1] = Pie;
3204 
3205  // This has to be synced with QwtPieCurve::drawPie() for now... until we have a clean solution.
3206  QRect canvas_rect = d_plot->plotLayout()->canvasRect();
3207  float radius = 0.45*qMin(canvas_rect.width(), canvas_rect.height());
3208 
3209  double PI = 4*atan(1.0);
3210  double angle = 90;
3211 
3212  for (int i = 0; i<size; i++ ){
3213  const double value = Y[i]/sum*360;
3214  double alabel = (angle - value*0.5)*PI/180.0;
3215 
3216  Legend* aux = new Legend(d_plot);
3217  aux->setFrameStyle(0);
3218  aux->setText(QString::number(Y[i]/sum*100,'g',2)+"%");
3219 
3220  int texts = d_texts.size();
3221  d_texts.resize(++texts);
3222  d_texts[texts-1] = d_plot->insertMarker(aux);
3223 
3224  aux->setOrigin(canvas_rect.center() +
3225  QPoint(int(radius*cos(alabel) - 0.5*aux->rect().width()),
3226  int(-radius*sin(alabel) - 0.5*aux->rect().height())));
3227 
3228  angle -= value;
3229  }
3230 
3231  if (legendMarkerID>=0){
3233  if (mrk){
3234  QString text="";
3235  for (int i=0; i<size; i++){
3236  text+="\\p{";
3237  text+=QString::number(i+1);
3238  text+="} ";
3239  text+=QString::number(i+1);
3240  text+="\n";
3241  }
3242  mrk->setText(text);
3243  }
3244  }
3245 
3246  d_plot->replot();
3247  updateScale();
3248 }
3249 
3250 bool Graph::plotHistogram(Table *w, QStringList names, int startRow, int endRow)
3251 {
3252  if (!w) return false;
3253  if (endRow < 0 || endRow >= w->numRows())
3254  endRow = w->numRows() - 1;
3255 
3256  bool success = false;
3257  foreach(QString col, names) {
3258  Column *col_ptr = w->column(col);
3259  if (!col_ptr || col_ptr->columnMode() != SciDAVis::Numeric) continue;
3260 
3261  QwtHistogram *c = new QwtHistogram(w, col, startRow, endRow);
3262  c->loadData();
3263  c->setStyle(QwtPlotCurve::UserCurve);
3264 
3265  c_type.resize(++n_curves);
3266  c_type[n_curves-1] = Histogram;
3267  c_keys.resize(n_curves);
3268  c_keys[n_curves-1] = d_plot->insertCurve(c);
3269 
3270  CurveLayout cl = initCurveLayout(Histogram, names.size());
3271  updateCurveLayout(n_curves-1, &cl);
3272 
3273  addLegendItem(col);
3274 
3275  success = true;
3276  }
3277 
3278  return success;
3279 }
3280 
3281 void Graph::insertPlotItem(QwtPlotItem *i, int type)
3282 {
3283  c_type.resize(++n_curves);
3284  c_type[n_curves-1] = type;
3285 
3286  c_keys.resize(n_curves);
3287  c_keys[n_curves-1] = d_plot->insertCurve(i);
3288 
3289  if (i->rtti() != QwtPlotItem::Rtti_PlotSpectrogram)
3290  addLegendItem(i->title().text());
3291 }
3292 
3293 bool Graph::insertCurvesList(Table* w, const QStringList& names, int style, int lWidth,
3294  int sSize, int startRow, int endRow)
3295 {
3296  if (style==Graph::Pie)
3297  plotPie(w, names[0], startRow, endRow);
3298  else if (style == Box)
3299  plotBoxDiagram(w, names, startRow, endRow);
3300  else if (style == Histogram)
3301  plotHistogram(w, names, startRow, endRow);
3302  else if (style==Graph::VectXYXY || style==Graph::VectXYAM)
3303  plotVectorCurve(w, names, style, startRow, endRow);
3304  else
3305  {
3306  QStringList errorCurves, otherCurves;
3307  foreach(QString col, names) {
3308  int colIndex = w->colIndex(col);
3309  if (colIndex < 0) continue;
3310  switch (w->colPlotDesignation(colIndex)) {
3311  case SciDAVis::xErr:
3312  case SciDAVis::yErr:
3313  errorCurves << col;
3314  break;
3315  default:
3316  otherCurves << col;
3317  break;
3318  }
3319  }
3320  QStringList lst = otherCurves + errorCurves;
3321 
3322  for (int i=0; i<lst.size(); i++)
3323  {
3324  CurveType type_of_i;
3325  int j = w->colIndex(lst[i]);
3326  if (j < 0) continue;
3327  bool ok = false;
3328  if (i >= otherCurves.size()) {
3329  type_of_i = ErrorBars;
3330  int ycol = -1;
3331  for (int k=j-1; k >= 0; k--) {
3332  if (w->colPlotDesignation(k) == SciDAVis::Y) {
3333  ycol = k;
3334  break;
3335  }
3336  }
3337  if (ycol < 0)
3338  ycol = w->colY(w->colIndex(lst[i]));
3339  if (ycol < 0)
3340  return false;
3341 
3342  if (w->colPlotDesignation(j) == SciDAVis::xErr)
3343  ok = addErrorBars(w->colName(ycol), w, lst[i], (int)QwtErrorPlotCurve::Horizontal);
3344  else
3345  ok = addErrorBars(w->colName(ycol), w, lst[i]);
3346  }
3347  else {
3348  type_of_i = (CurveType) style;
3349  ok = insertCurve(w, lst[i], style, startRow, endRow);
3350  }
3351 
3352  if (ok)
3353  {
3354  CurveLayout cl = initCurveLayout(type_of_i, otherCurves.size());
3355  cl.sSize = sSize;
3356  cl.lWidth = lWidth;
3357  updateCurveLayout(i, &cl);
3358  }
3359  else
3360  return false;
3361  }
3362  }
3363  updatePlot();
3364  return true;
3365 }
3366 
3367 bool Graph::insertCurve(Table* w, const QString& name, int style, int startRow, int endRow)
3368 {//provided for convenience
3369  int ycol = w->colIndex(name);
3370  int xcol = w->colX(ycol);
3371 
3372  bool succes = insertCurve(w, w->colName(xcol), w->colName(ycol), style, startRow, endRow);
3373  if (succes)
3374  emit modifiedGraph();
3375  return succes;
3376 }
3377 
3378 bool Graph::insertCurve(Table* w, int xcol, const QString& name, int style)
3379 {
3380  return insertCurve(w, w->colName(xcol), w->colName(w->colIndex(name)), style);
3381 }
3382 
3383 bool Graph::insertCurve(Table* w, const QString& xColName, const QString& yColName, int style, int startRow, int endRow)
3384 {
3385  if (!w) return false;
3386  DataCurve *c = 0;
3387 
3388  switch (style) {
3389  case Histogram:
3390  case Box:
3391  case Pie:
3392  return false;
3393  case VerticalBars:
3394  c = new QwtBarCurve(QwtBarCurve::Vertical, w, xColName, yColName, startRow, endRow);
3395  c->setStyle(QwtPlotCurve::UserCurve);
3396  break;
3397  case HorizontalBars:
3398  c = new QwtBarCurve(QwtBarCurve::Horizontal, w, xColName, yColName, startRow, endRow);
3399  c->setStyle(QwtPlotCurve::UserCurve);
3400  break;
3401  default:
3402  c = new DataCurve(w, xColName, yColName, startRow, endRow);
3403  break;
3404  };
3405 
3406  c_type.resize(++n_curves);
3407  c_type[n_curves-1] = style;
3408  c_keys.resize(n_curves);
3409  c_keys[n_curves-1] = d_plot->insertCurve(c);
3410 
3411  c->setPen(QPen(Qt::black,widthLine));
3412 
3413  if (!c->loadData())
3414  return false;
3415 
3416  addLegendItem(yColName);
3417  updatePlot();
3418 
3419  return true;
3420 }
3421 
3422 void Graph::plotVectorCurve(Table* w, const QStringList& colList, int style, int startRow, int endRow)
3423 {
3424  if (colList.count() != 4)
3425  return;
3426 
3427  if (endRow < 0)
3428  endRow = w->numRows() - 1;
3429 
3430  VectorCurve *v = 0;
3431  if (style == VectXYAM)
3432  v = new VectorCurve(VectorCurve::XYAM, w, colList[0], colList[1], colList[2], colList[3], startRow, endRow);
3433  else
3434  v = new VectorCurve(VectorCurve::XYXY, w, colList[0], colList[1], colList[2], colList[3], startRow, endRow);
3435 
3436  if (!v)
3437  return;
3438 
3439  v->loadData();
3440  v->setStyle(QwtPlotCurve::NoCurve);
3441 
3442  c_type.resize(++n_curves);
3443  c_type[n_curves-1] = style;
3444 
3445  c_keys.resize(n_curves);
3446  c_keys[n_curves-1] = d_plot->insertCurve(v);
3447 
3448  addLegendItem(colList[1]);
3449  updatePlot();
3450 }
3451 
3452 void Graph::updateVectorsLayout(int curve, const QColor& color, int width,
3453  int arrowLength, int arrowAngle, bool filled, int position,
3454  const QString& xEndColName, const QString& yEndColName)
3455 {
3456  VectorCurve *vect = (VectorCurve *)this->curve(curve);
3457  if (!vect)
3458  return;
3459 
3460  vect->setColor(color);
3461  vect->setWidth(width);
3462  vect->setHeadLength(arrowLength);
3463  vect->setHeadAngle(arrowAngle);
3464  vect->fillArrowHead(filled);
3465  vect->setPosition(position);
3466 
3467  if (!xEndColName.isEmpty() && !yEndColName.isEmpty())
3468  vect->setVectorEnd(xEndColName, yEndColName);
3469 
3470  d_plot->replot();
3471  emit modifiedGraph();
3472 }
3473 
3475 {
3476  if (m_autoscale && !zoomOn() && d_active_tool==NULL) {
3477  for (int i = 0; i < QwtPlot::axisCnt; i++)
3478  d_plot->setAxisAutoScale(i);
3479  }
3480 
3481  d_plot->replot();
3483  updateSecondaryAxis(QwtPlot::xTop);
3484  updateSecondaryAxis(QwtPlot::yRight);
3485 
3486  if (isPiePlot()){
3487  QwtPieCurve *c = (QwtPieCurve *)curve(0);
3488  c->updateBoundingRect();
3489  }
3490 
3491  d_plot->replot();
3492  d_zoomer[0]->setZoomBase();
3493  d_zoomer[1]->setZoomBase();
3494 }
3495 
3497 {
3498  const QwtScaleDiv *scDiv=d_plot->axisScaleDiv(QwtPlot::xBottom);
3499  QwtValueList lst = scDiv->ticks (QwtScaleDiv::MajorTick);
3500 
3501  double step = fabs(lst[1]-lst[0]);
3502 
3503  if (!m_autoscale)
3504 #if QWT_VERSION >= 0x050200
3505  d_plot->setAxisScale (QwtPlot::xBottom, scDiv->lowerBound(), scDiv->upperBound(), step);
3506 #else
3507  d_plot->setAxisScale (QwtPlot::xBottom, scDiv->lBound(), scDiv->hBound(), step);
3508 #endif
3509 
3510  scDiv=d_plot->axisScaleDiv(QwtPlot::yLeft);
3511  lst = scDiv->ticks (QwtScaleDiv::MajorTick);
3512 
3513  step = fabs(lst[1]-lst[0]);
3514 
3515  if (!m_autoscale)
3516 #if QWT_VERSION >= 0x050200
3517  d_plot->setAxisScale (QwtPlot::yLeft, scDiv->lowerBound(), scDiv->upperBound(), step);
3518 #else
3519  d_plot->setAxisScale (QwtPlot::yLeft, scDiv->lBound(), scDiv->hBound(), step);
3520 #endif
3521 
3522  d_plot->replot();
3524  updateSecondaryAxis(QwtPlot::xTop);
3525  updateSecondaryAxis(QwtPlot::yRight);
3526 
3527  d_plot->replot();//TODO: avoid 2nd replot!
3528 }
3529 
3530 void Graph::setBarsGap(int curve, int gapPercent, int offset)
3531 {
3532  QwtBarCurve *bars = (QwtBarCurve *)this->curve(curve);
3533  if (!bars)
3534  return;
3535 
3536  if (bars->gap() == gapPercent && bars->offset() == offset)
3537  return;
3538 
3539  bars->setGap(gapPercent);
3540  bars->setOffset(offset);
3541 }
3542 
3544 {
3545  if (legendMarkerID>=0)
3546  {
3548  if (mrk)
3549  mrk->setText({});
3550  }
3551 
3552  d_plot->removeCurve(c_keys[0]);
3553  d_plot->replot();
3554 
3555  c_keys.resize(0);
3556  c_type.resize(0);
3557  n_curves=0;
3558  emit modifiedGraph();
3559 }
3560 
3561 void Graph::removeCurves(const QString& s)
3562 {
3563  QList<int> keys = d_plot->curveKeys();
3564  for (int i=0; i<(int)keys.count(); i++)
3565  {
3566  QwtPlotItem *it = d_plot->plotItem(keys[i]);
3567  if (!it)
3568  continue;
3569 
3570  if (it->title().text() == s)
3571  {
3572  removeCurve(i);
3573  continue;
3574  }
3575 
3576  if (it->rtti() != QwtPlotItem::Rtti_PlotCurve)
3577  continue;
3578  if (((PlotCurve *)it)->type() == Function)
3579  continue;
3580 
3581  if(((DataCurve *)it)->plotAssociation().contains(QRegExp("\b"+s+"\b")))
3582  removeCurve(i);
3583  }
3584  d_plot->replot();
3585 }
3586 
3587 void Graph::removeCurve(const QString& s)
3588 {
3589  removeCurve(plotItemsList().indexOf(s));
3590 }
3591 
3592 void Graph::removeCurve(int index)
3593 {
3594  if (index < 0 || index >= n_curves)
3595  return;
3596 
3597  QwtPlotItem *it = plotItem(index);
3598  if (!it)
3599  return;
3600 
3601  removeLegendItem(index);
3602 
3603  if (it->rtti() != QwtPlotItem::Rtti_PlotSpectrogram)
3604  {
3605  if (((PlotCurve *)it)->type() == ErrorBars)
3606  ((QwtErrorPlotCurve *)it)->detachFromMasterCurve();
3607  else if (((PlotCurve *)it)->type() != Function)
3608  ((DataCurve *)it)->clearErrorBars();
3609 
3610  if (d_fit_curves.contains((QwtPlotCurve *)it))
3611  {
3612  int i = d_fit_curves.indexOf((QwtPlotCurve *)it);
3613  if (i >= 0 && i < d_fit_curves.size())
3614  d_fit_curves.removeAt(i);
3615  }
3616  }
3617 
3618  if (d_range_selector && curve(index) == d_range_selector->selectedCurve())
3619  {
3620  if (n_curves > 1 && (index - 1) >= 0)
3621  d_range_selector->setSelectedCurve(curve(index - 1));
3622  else if (n_curves > 1 && index + 1 < n_curves)
3623  d_range_selector->setSelectedCurve(curve(index + 1));
3624  else
3625  delete d_range_selector;
3626  }
3627 
3628  d_plot->removeCurve(c_keys[index]);
3629  n_curves--;
3630 
3631  for (int i=index; i<n_curves; i++)
3632  {
3633  c_type[i] = c_type[i+1];
3634  c_keys[i] = c_keys[i+1];
3635  }
3636  c_type.resize(n_curves);
3637  c_keys.resize(n_curves);
3638  emit modifiedGraph();
3639 }
3640 
3642 {
3643  if (legendMarkerID<0 || c_type[index] == ErrorBars)
3644  return;
3645 
3647  if (!mrk)
3648  return;
3649 
3650  if (isPiePlot())
3651  {
3652  mrk->setText({});
3653  return;
3654  }
3655 
3656  QString text=mrk->text();
3657  QStringList items=text.split( "\n", QString::SkipEmptyParts);
3658 
3659  if (index >= (int) items.count())
3660  return;
3661 
3662  QStringList l = items.filter( "\\c{" + QString::number(index+1) + "}" );
3663  if (!l.isEmpty())
3664  items.removeAll(l[0]);//remove the corresponding legend string
3665  text=items.join ( "\n" ) + "\n";
3666 
3667  QRegExp itemCmd("\\\\c\\{(\\d+)\\}");
3668  int pos=0;
3669  while ((pos = itemCmd.indexIn(text, pos)) != -1) {
3670  int nr = itemCmd.cap(1).toInt();
3671  if (nr > index) {
3672  QString subst = QString("\\c{") + QString::number(nr-1) + "}";
3673  text.replace(pos, itemCmd.matchedLength(), subst);
3674  pos += subst.length();
3675  } else
3676  pos += itemCmd.matchedLength();
3677  }
3678 
3679  mrk->setText(text);
3680 }
3681 
3682 void Graph::addLegendItem(const QString& colName)
3683 {
3684  if (legendMarkerID >= 0 ){
3686  if (mrk){
3687  QString text = mrk->text();
3688  if (text.endsWith ( "\n", Qt::CaseSensitive ) )
3689  text.append("\\c{"+QString::number(curves())+"}"+colName+"\n");
3690  else
3691  text.append("\n\\c{"+QString::number(curves())+"}"+colName+"\n");
3692 
3693  mrk->setText(text);
3694  }
3695  }
3696 }
3697 
3698 void Graph::contextMenuEvent(QContextMenuEvent *e)
3699 {
3700  if (selectedMarker>=0) {
3701  emit showMarkerPopupMenu();
3702  return;
3703  }
3704 
3705  QPoint pos = d_plot->canvas()->mapFrom(d_plot, e->pos());
3706  int dist, point;
3707  const long curve = d_plot->closestCurve(pos.x(), pos.y(), dist, point);
3708  const QwtPlotCurve *c = (QwtPlotCurve *)d_plot->curve(curve);
3709 
3710  if (c && dist < 10)//10 pixels tolerance
3712  else
3713  emit showContextMenu();
3714 
3715  e->accept();
3716 }
3717 
3718 void Graph::closeEvent(QCloseEvent *e)
3719 {
3720  emit closedGraph();
3721  e->accept();
3722 
3723 }
3724 
3726 {
3727  return (d_zoomer[0]->isEnabled() || d_zoomer[1]->isEnabled());
3728 }
3729 
3730 void Graph::zoomed (const QwtDoubleRect &)
3731 {
3732  emit modifiedGraph();
3733 }
3734 
3735 void Graph::zoom(bool on)
3736 {
3737  d_zoomer[0]->setEnabled(on);
3738  d_zoomer[1]->setEnabled(on);
3739  for (int i=0; i<n_curves; i++)
3740  {
3741  Spectrogram *sp = (Spectrogram *)this->curve(i);
3742  if (sp && sp->rtti() == QwtPlotItem::Rtti_PlotSpectrogram)
3743  {
3744  if (sp->colorScaleAxis() == QwtPlot::xBottom || sp->colorScaleAxis() == QwtPlot::yLeft)
3745  d_zoomer[0]->setEnabled(false);
3746  else
3747  d_zoomer[1]->setEnabled(false);
3748  }
3749  }
3750 
3751  QCursor cursor=QCursor (QPixmap(":/lens.xpm"),-1,-1);
3752  if (on)
3753  d_plot->canvas()->setCursor(cursor);
3754  else
3755  d_plot->canvas()->setCursor(Qt::ArrowCursor);
3756 }
3757 
3759 {
3760  d_zoomer[0]->zoom(-1);
3761  d_zoomer[1]->zoom(-1);
3762 
3763  updateSecondaryAxis(QwtPlot::xTop);
3764  updateSecondaryAxis(QwtPlot::yRight);
3765 }
3766 
3767 void Graph::drawText(bool on)
3768 {
3769  QCursor c=QCursor(Qt::IBeamCursor);
3770  if (on)
3771  d_plot->canvas()->setCursor(c);
3772  else
3773  d_plot->canvas()->setCursor(Qt::ArrowCursor);
3774 
3775  drawTextOn=on;
3776 }
3777 
3779 {
3780  if (!mrk)
3781  return 0;
3782 
3783  ImageMarker* mrk2 = new ImageMarker(mrk->fileName());
3784 
3785  int imagesOnPlot = d_images.size();
3786  d_images.resize(++imagesOnPlot);
3787  d_images[imagesOnPlot-1]=d_plot->insertMarker(mrk2);
3788 
3789  mrk2->setBoundingRect(mrk->xValue(), mrk->yValue(), mrk->right(), mrk->bottom());
3790  return mrk;
3791 }
3792 
3793 ImageMarker* Graph::addImage(const QString& fileName)
3794 {
3795  if (fileName.isEmpty() || !QFile::exists(fileName)){
3796  QMessageBox::warning(0, tr("File open error"),
3797  tr("Image file: <p><b> %1 </b><p>does not exist anymore!").arg(fileName));
3798  return 0;
3799  }
3800 
3801  ImageMarker* mrk = new ImageMarker(fileName);
3802  int imagesOnPlot = d_images.size();
3803  d_images.resize(++imagesOnPlot);
3804  d_images[imagesOnPlot-1] = d_plot->insertMarker(mrk);
3805 
3806  QSize picSize = mrk->pixmap().size();
3807  int w = d_plot->canvas()->width();
3808  if (picSize.width()>w)
3809  picSize.setWidth(w);
3810 
3811  int h=d_plot->canvas()->height();
3812  if (picSize.height()>h)
3813  picSize.setHeight(h);
3814 
3815  mrk->setSize(picSize);
3816  d_plot->replot();
3817 
3818  emit modifiedGraph();
3819  return mrk;
3820 }
3821 
3822 void Graph::insertImageMarker(const QStringList& lst, int fileVersion)
3823 {
3824  QString fn = lst[1];
3825  if (!QFile::exists(fn)){
3826  QMessageBox::warning(0, tr("File open error"),
3827  tr("Image file: <p><b> %1 </b><p>does not exist anymore!").arg(fn));
3828  } else {
3829  ImageMarker* mrk = new ImageMarker(fn);
3830  if (!mrk)
3831  return;
3832 
3833  int imagesOnPlot = d_images.size();
3834  d_images.resize(++imagesOnPlot);
3835  d_images[imagesOnPlot-1] = d_plot->insertMarker(mrk);
3836 
3837  if (fileVersion < 86){
3838  mrk->setOrigin(QPoint(lst[2].toInt(), lst[3].toInt()));
3839  mrk->setSize(QSize(lst[4].toInt(), lst[5].toInt()));
3840  } else if (fileVersion < 90) {
3841  double left = lst[2].toDouble();
3842  double right = left + lst[4].toDouble();
3843  double top = lst[3].toDouble();
3844  double bottom = top - lst[5].toDouble();
3845  mrk->setBoundingRect(left, top, right, bottom);
3846  } else
3847  mrk->setBoundingRect(lst[2].toDouble(), lst[3].toDouble(), lst[4].toDouble(), lst[5].toDouble());
3848  }
3849 }
3850 
3851 void Graph::drawLine(bool on, bool arrow)
3852 {
3853  drawLineOn=on;
3855  if (!on)
3856  emit drawLineEnded(true);
3857 }
3858 
3859 bool Graph::modifyFunctionCurve(ApplicationWindow * parent, int curve, int type, const QStringList &formulas,
3860  const QString& var,QList<double> &ranges, int points)
3861 {
3862  FunctionCurve *c = (FunctionCurve *)this->curve(curve);
3863  if (!c)
3864  return false;
3865 
3866  if (c->functionType() == type &&
3867  c->variable() == var &&
3868  c->formulas() == formulas &&
3869  c->startRange() == ranges[0] &&
3870  c->endRange() == ranges[1] &&
3871  c->dataSize() == points)
3872  return true;
3873 
3874  FunctionCurve backup(parent);
3875  backup.copy(c);
3876 
3878  c->setRange(ranges[0], ranges[1]);
3879  c->setFormulas(formulas);
3880  c->setVariable(var);
3881  if (!c->loadData(points)) {
3882  c->copy(&backup);
3883  c->loadData(points);
3884  return false;
3885  }
3886 
3887  if (legendMarkerID >= 0)
3888  {//update the legend marker
3890  if (mrk)
3891  {
3892  QString text = (mrk->text()).replace(backup.legend(), c->legend());
3893  mrk->setText(text);
3894  }
3895  }
3896  updatePlot();
3897  emit modifiedGraph();
3898  return true;
3899 }
3900 
3901 QString Graph::generateFunctionName(const QString& name)
3902 {
3903  int index = 1;
3904  QString newName = name + QString::number(index);
3905 
3906  QStringList lst;
3907  for (int i=0; i<n_curves; i++)
3908  {
3909  PlotCurve *c = (PlotCurve*)this->curve(i);
3910  if (!c)
3911  continue;
3912 
3913  if (c->type() == Function)
3914  lst << c->title().text();
3915  }
3916 
3917  while(lst.contains(newName)){
3918  newName = name + QString::number(++index);}
3919  return newName;
3920 }
3921 
3922 bool Graph::addFunctionCurve(ApplicationWindow *parent, int type, const QStringList &formulas, const QString &var,
3923  QList<double> &ranges, int points, const QString& title)
3924 {
3925  QString name;
3926  if (!title.isEmpty())
3927  name = title;
3928  else
3930 
3932  c->setPen(QPen(QColor(Qt::black), widthLine));
3933  c->setRange(ranges[0], ranges[1]);
3934  c->setFormulas(formulas);
3935  c->setVariable(var);
3936  if (!c->loadData(points)) {
3937  delete c;
3938  return false;
3939  }
3940 
3941  c_type.resize(++n_curves);
3942  c_type[n_curves-1] = Line;
3943 
3944  c_keys.resize(n_curves);
3945  c_keys[n_curves-1] = d_plot->insertCurve(c);
3946 
3947  addLegendItem(c->legend());
3948  updatePlot();
3949 
3950  emit modifiedGraph();
3951  return true;
3952 }
3953 
3954 bool Graph::insertFunctionCurve(ApplicationWindow * parent, const QStringList& func_spec, int points, int fileVersion)
3955 {
3956  int type= FunctionCurve::Normal;
3957  QStringList formulas;
3958  QString var, name;
3959  QList<double> ranges;
3960 
3961  QStringList curve = func_spec[0].split(",");
3962  if (fileVersion >= 0x000105) {
3963  // SciDAVis 0.1.4 and 0.2.0 crash when trying to save a function curve;
3964  // thus, it's safe to assume every version from 0.1.5 on uses the new format,
3965  // even though 0.2.0 doesn't actually contain the revised code yet
3966  type = curve[0].toInt();
3967  name = curve[1];
3968  var = curve[2];
3969  ranges += curve[3].toDouble();
3970  ranges += curve[4].toDouble();
3971 
3972  formulas << func_spec[1];
3973  if (type != FunctionCurve::Normal)
3974  formulas << func_spec[2];
3975 
3976  } else if (fileVersion < 87) {
3977  if (curve[0][0]=='f')
3978  {
3979  type = FunctionCurve::Normal;
3980  formulas += curve[0].section('=',1,1);
3981  var = curve[1];
3982  ranges += curve[2].toDouble();
3983  ranges += curve[3].toDouble();
3984  }
3985  else if (curve[0][0]=='X')
3986  {
3988  formulas += curve[0].section('=',1,1);
3989  formulas += curve[1].section('=',1,1);
3990  var = curve[2];
3991  ranges += curve[3].toDouble();
3992  ranges += curve[4].toDouble();
3993  }
3994  else if (curve[0][0]=='R')
3995  {
3996  type = FunctionCurve::Polar;
3997  formulas += curve[0].section('=',1,1);
3998  formulas += curve[1].section('=',1,1);
3999  var = curve[2];
4000  ranges += curve[3].toDouble();
4001  ranges += curve[4].toDouble();
4002  }
4003  }
4004  else
4005  {
4006  type = curve[0].toInt();
4007  name = curve[1];
4008 
4009  if (type == FunctionCurve::Normal)
4010  {
4011  formulas << curve[2];
4012  var = curve[3];
4013  ranges += curve[4].toDouble();
4014  ranges += curve[5].toDouble();
4015  }
4016  else if (type == FunctionCurve::Polar || type == FunctionCurve::Parametric)
4017  {
4018  formulas << curve[2];
4019  formulas << curve[3];
4020  var = curve[4];
4021  ranges += curve[5].toDouble();
4022  ranges += curve[6].toDouble();
4023  }
4024  }
4025  return addFunctionCurve(parent, type, formulas, var, ranges, points, name);
4026 }
4027 
4028 void Graph::createTable(const QString& curveName)
4029 {
4030  if (curveName.isEmpty())
4031  return;
4032 
4033  const QwtPlotCurve* cv = curve(curveName);
4034  if (!cv)
4035  return;
4036 
4037  createTable(cv);
4038 }
4039 
4040 void Graph::createTable(const QwtPlotCurve* curve)
4041 {
4042  if (!curve)
4043  return;
4044 
4045  int size = curve->dataSize();
4046 
4047  Column *xCol = new Column(tr("1", "curve data table x column name"), SciDAVis::Numeric);
4048  Column *yCol = new Column(tr("2", "curve data table y column name"), SciDAVis::Numeric);
4051  for (int i=0; i<size; i++)
4052  {
4053  xCol->setValueAt(i, curve->x(i));
4054  yCol->setValueAt(i, curve->y(i));
4055  }
4056  QString legend = tr("Data set generated from curve") + ": " + curve->title().text();
4057  emit createTable(tr("Curve data %1").arg(1), legend, QList<Column *>() << xCol << yCol);
4058 }
4059 
4060 QString Graph::saveToString(bool saveAsTemplate)
4061 {
4062  QString s="<graph>\n";
4063  s+="ggeometry\t";
4064  s+=QString::number(this->pos().x())+"\t";
4065  s+=QString::number(this->pos().y())+"\t";
4066  s+=QString::number(this->frameGeometry().width())+"\t";
4067  s+=QString::number(this->frameGeometry().height())+"\n";
4068  s+=saveTitle();
4069  s+="<Antialiasing>" + QString::number(d_antialiasing) + "</Antialiasing>\n";
4070  s+="Background\t" + COLORNAME(d_plot->paletteBackgroundColor()) + "\t";
4071  s+=QString::number(d_plot->paletteBackgroundColor().alpha()) + "\n";
4072  s+="Margin\t"+QString::number(d_plot->margin())+"\n";
4073  s+="Border\t"+QString::number(d_plot->lineWidth())+"\t"+COLORNAME(d_plot->frameColor())+"\n";
4074  s+=grid()->saveToString();
4075  s+=saveEnabledAxes();
4076  s+="AxesTitles\t"+saveScaleTitles();
4077  s+=saveAxesTitleColors();
4079  s+=saveFonts();
4080  s+=saveEnabledTickLabels();
4081  s+=saveAxesColors();
4082  s+=saveAxesBaseline();
4083  s+=saveCanvas();
4084 
4085  if (!saveAsTemplate)
4086  s+=saveCurves();
4087 
4088  s+=saveScale();
4089  s+=saveAxesFormulas();
4090  s+=saveLabelsFormat();
4091  s+=saveAxesLabelsType();
4092  s+=saveTicksType();
4093  s+="TicksLength\t"+QString::number(minorTickLength())+"\t"+QString::number(majorTickLength())+"\n";
4094  s+="DrawAxesBackbone\t"+QString::number(drawAxesBackbone)+"\n";
4095  s+="AxesLineWidth\t"+QString::number(d_plot->axesLinewidth())+"\n";
4096  s+=saveLabelsRotation();
4097  s+=saveMarkers();
4098  s+="</graph>\n";
4099  return s;
4100 }
4101 
4103 {
4105  if (!mrk)
4106  return;
4107 
4108  emit createIntensityTable(mrk->fileName());
4109 }
4110 
4112 {
4113  for (int i=0;i<(int)d_lines.size();i++)
4114  {
4115  ArrowMarker* mrkL = (ArrowMarker*)d_plot->marker(d_lines[i]);
4116  if (mrkL)
4117  mrkL->updateBoundingRect();
4118  }
4119  for (int i=0; i<(int)d_texts.size(); i++)
4120  {
4121  Legend* mrkT = (Legend*) d_plot->marker(d_texts[i]);
4122  if (mrkT)
4123  mrkT->updateOrigin();
4124  }
4125 
4126  for (int i=0;i<(int)d_images.size();i++)
4127  {
4128  ImageMarker* mrk = (ImageMarker*) d_plot->marker(d_images[i]);
4129  if (mrk)
4130  mrk->updateBoundingRect();
4131  }
4132  d_plot->replot();
4133 }
4134 void Graph::hideEvent(QHideEvent *e)
4135 {
4136  Q_UNUSED(e);
4137  hidden_size = size();
4138 }
4139 
4140 void Graph::resizeEvent ( QResizeEvent *e )
4141 {
4142  if (ignoreResize)
4143  return;
4144  QSize oldSize=e->oldSize();
4145  if (!this->isVisible() || !oldSize.isValid())
4146  oldSize = hidden_size;
4147  if (!oldSize.isValid())
4148  return;
4149 
4150  if (autoScaleFonts)
4151  {
4152  QSize size=e->size();
4153 
4154  double ratio=(double)size.height()/(double)oldSize.height();
4155  scaleFonts(ratio);
4156  }
4157 
4158  d_plot->resize(e->size());
4159 }
4160 
4161 void Graph::scaleFonts(double factor)
4162 {
4163  for (int i=0;i<(int)d_texts.size();i++)
4164  {
4165  Legend* mrk = (Legend*) d_plot->marker(d_texts[i]);
4166  QFont font = mrk->font();
4167  font.setPointSizeF(factor*font.pointSizeF());
4168  mrk->setFont(font);
4169  }
4170  for (int i = 0; i<QwtPlot::axisCnt; i++)
4171  {
4172  QFont font = axisFont(i);
4173  font.setPointSizeF(factor*font.pointSizeF());
4174  d_plot->setAxisFont(i, font);
4175 
4176  QwtText title = d_plot->axisTitle(i);
4177  font = title.font();
4178  font.setPointSizeF(factor*font.pointSizeF());
4179  title.setFont(font);
4180  d_plot->setAxisTitle(i, title);
4181  }
4182 
4183  QwtText title = d_plot->title();
4184  QFont font = title.font();
4185  font.setPointSizeF(factor*font.pointSizeF());
4186  title.setFont(font);
4187  d_plot->setTitle(title);
4188 
4189  d_plot->replot();
4190 }
4191 
4192 void Graph::setMargin (int d)
4193 {
4194  if (d_plot->margin() == d)
4195  return;
4196 
4197  d_plot->setMargin(d);
4198  emit modifiedGraph();
4199 }
4200 
4201 void Graph::setFrame (int width, const QColor& color)
4202 {
4203  if (d_plot->frameColor() == color && width == d_plot->lineWidth())
4204  return;
4205 
4206  QPalette pal = d_plot->palette();
4207  pal.setColor(QPalette::WindowText, color);
4208  d_plot->setPalette(pal);
4209 
4210  d_plot->setLineWidth(width);
4211 }
4212 
4213 void Graph::setBackgroundColor(const QColor& color)
4214 {
4215  QPalette p = d_plot->palette();
4216  p.setColor(QPalette::Window, color);
4217  d_plot->setPalette(p);
4218 
4219  d_plot->setAutoFillBackground(true);
4220  emit modifiedGraph();
4221 }
4222 
4223 void Graph::setCanvasBackground(const QColor& color)
4224 {
4225  d_plot->setCanvasBackground(color);
4226  emit modifiedGraph();
4227 }
4228 
4229 Qt::BrushStyle Graph::getBrushStyle(int style)
4230 {
4231  Qt::BrushStyle brushStyle;
4232  switch (style)
4233  {
4234  case 0:
4235  brushStyle=Qt::SolidPattern;
4236  break;
4237  case 1:
4238  brushStyle=Qt::HorPattern;
4239  break;
4240  case 2:
4241  brushStyle=Qt::VerPattern;
4242  break;
4243  case 3:
4244  brushStyle=Qt::CrossPattern;
4245  break;
4246  case 4:
4247  brushStyle=Qt::BDiagPattern;
4248  break;
4249  case 5:
4250  brushStyle=Qt::FDiagPattern;
4251  break;
4252  case 6:
4253  brushStyle=Qt::DiagCrossPattern;
4254  break;
4255  case 7:
4256  brushStyle=Qt::Dense1Pattern;
4257  break;
4258  case 8:
4259  brushStyle=Qt::Dense2Pattern;
4260  break;
4261  case 9:
4262  brushStyle=Qt::Dense3Pattern;
4263  break;
4264  case 10:
4265  brushStyle=Qt::Dense4Pattern;
4266  break;
4267  case 11:
4268  brushStyle=Qt::Dense5Pattern;
4269  break;
4270  case 12:
4271  brushStyle=Qt::Dense6Pattern;
4272  break;
4273  case 13:
4274  brushStyle=Qt::Dense7Pattern;
4275  break;
4276  default:
4277  throw runtime_error("invalid brush style");
4278  }
4279  return brushStyle;
4280 }
4281 
4282 QString Graph::penStyleName(Qt::PenStyle style)
4283 {
4284  if (style==Qt::SolidLine)
4285  return "SolidLine";
4286  else if (style==Qt::DashLine)
4287  return "DashLine";
4288  else if (style==Qt::DotLine)
4289  return "DotLine";
4290  else if (style==Qt::DashDotLine)
4291  return "DashDotLine";
4292  else if (style==Qt::DashDotDotLine)
4293  return "DashDotDotLine";
4294  else if (style==Qt::CustomDashLine)
4295  return "CustomDashLine";
4296  else
4297  return "SolidLine";
4298 }
4299 
4300 Qt::PenStyle Graph::getPenStyle(int style)
4301 {
4302  Qt::PenStyle linePen;
4303  switch (style)
4304  {
4305  case 0:
4306  linePen=Qt::SolidLine;
4307  break;
4308  case 1:
4309  linePen=Qt::DashLine;
4310  break;
4311  case 2:
4312  linePen=Qt::DotLine;
4313  break;
4314  case 3:
4315  linePen=Qt::DashDotLine;
4316  break;
4317  case 4:
4318  linePen=Qt::DashDotDotLine;
4319  break;
4320  case 5:
4321  linePen=Qt::CustomDashLine;
4322  break;
4323  default:
4324  throw runtime_error("invalid pen style");
4325  }
4326  return linePen;
4327 }
4328 
4329 Qt::PenStyle Graph::getPenStyle(const QString& s)
4330 {
4331  Qt::PenStyle style=Qt::SolidLine;
4332  if (s=="SolidLine")
4333  style=Qt::SolidLine;
4334  else if (s=="DashLine")
4335  style=Qt::DashLine;
4336  else if (s=="DotLine")
4337  style=Qt::DotLine;
4338  else if (s=="DashDotLine")
4339  style=Qt::DashDotLine;
4340  else if (s=="DashDotDotLine")
4341  style=Qt::DashDotDotLine;
4342  else if (s=="CustomDashLine")
4343  style=Qt::CustomDashLine;
4344  return style;
4345 }
4346 
4348 {
4349  if (type <= 4)
4350  return type+1;
4351  else
4352  return type+2;
4353 }
4354 
4355 int Graph::curveType(int curveIndex)
4356 {
4357  if (curveIndex < (int)c_type.size() && curveIndex >= 0)
4358  return c_type[curveIndex];
4359  else
4360  return -1;
4361 }
4362 
4363 void Graph::showPlotErrorMessage(QWidget *parent, const QStringList& emptyColumns)
4364 {
4365  QApplication::restoreOverrideCursor();
4366 
4367  int n = (int)emptyColumns.count();
4368  if (n > 1)
4369  {
4370  QString columns;
4371  for (int i = 0; i < n; i++)
4372  columns += "<p><b>" + emptyColumns[i] + "</b></p>";
4373 
4374  QMessageBox::warning(parent, tr("Warning"),
4375  tr("The columns") + ": " + columns + tr("are empty and will not be added to the plot!"));
4376  }
4377  else if (n == 1)
4378  QMessageBox::warning(parent, tr("Warning"),
4379  tr("The column") + " <b>" + emptyColumns[0] + "</b> " + tr("is empty and will not be added to the plot!"));
4380 }
4381 
4383 {
4384  QMenu titleMenu(this);
4385  titleMenu.addAction(QPixmap(":/cut.xpm"), tr("&Cut"),this, SLOT(cutTitle()));
4386  titleMenu.addAction(QPixmap(":/copy.xpm"), tr("&Copy"),this, SLOT(copyTitle()));
4387  titleMenu.addAction(tr("&Delete"),this, SLOT(removeTitle()));
4388  titleMenu.addSeparator();
4389  titleMenu.addAction(tr("&Properties..."), this, SIGNAL(viewTitleDialog()));
4390  titleMenu.exec(QCursor::pos());
4391 }
4392 
4394 {
4395  QApplication::clipboard()->setText(d_plot->title().text(), QClipboard::Clipboard);
4396  removeTitle();
4397 }
4398 
4400 {
4401  QApplication::clipboard()->setText(d_plot->title().text(), QClipboard::Clipboard);
4402 }
4403 
4405 {
4406  int axis = (selectedAxis + 2)%4;//inconsistent notation in Qwt enumerations between
4407  //QwtScaleDraw::alignment and QwtPlot::Axis
4408  d_plot->setAxisTitle(axis, QString());
4409  d_plot->replot();
4410  emit modifiedGraph();
4411 }
4412 
4414 {
4415  copyAxisTitle();
4416  removeAxisTitle();
4417 }
4418 
4420 {
4421  int axis = (selectedAxis + 2)%4;//unconsistent notation in Qwt enumerations between
4422  //QwtScaleDraw::alignment and QwtPlot::Axis
4423  QApplication::clipboard()->setText(d_plot->axisTitle(axis).text(), QClipboard::Clipboard);
4424  }
4425 
4427 {
4428  selectedAxis = axis;
4429 
4430  QMenu titleMenu(this);
4431  titleMenu.addAction(QPixmap(":/cut.xpm"), tr("&Cut"), this, SLOT(cutAxisTitle()));
4432  titleMenu.addAction(QPixmap(":/copy.xpm"), tr("&Copy"), this, SLOT(copyAxisTitle()));
4433  titleMenu.addAction(tr("&Delete"),this, SLOT(removeAxisTitle()));
4434  titleMenu.addSeparator();
4435  switch (axis)
4436  {
4437  case QwtScaleDraw::BottomScale:
4438  titleMenu.addAction(tr("&Properties..."), this, SIGNAL(xAxisTitleDblClicked()));
4439  break;
4440 
4441  case QwtScaleDraw::LeftScale:
4442  titleMenu.addAction(tr("&Properties..."), this, SIGNAL(yAxisTitleDblClicked()));
4443  break;
4444 
4445  case QwtScaleDraw::TopScale:
4446  titleMenu.addAction(tr("&Properties..."), this, SIGNAL(topAxisTitleDblClicked()));
4447  break;
4448 
4449  case QwtScaleDraw::RightScale:
4450  titleMenu.addAction(tr("&Properties..."), this, SIGNAL(rightAxisTitleDblClicked()));
4451  break;
4452  }
4453 
4454  titleMenu.exec(QCursor::pos());
4455 }
4456 
4458 {
4459  selectedAxis = axis;
4460 
4461  QMenu menu(this);
4462  menu.addAction(QPixmap(":/unzoom.xpm"), tr("&Rescale to show all"), this, SLOT(setAutoScale()), tr("Ctrl+Shift+R"));
4463  menu.addSeparator();
4464  menu.addAction(tr("&Hide axis"), this, SLOT(hideSelectedAxis()));
4465 
4466  QAction * gridsID = menu.addAction(tr("&Show grids"), this, SLOT(showGrids()));
4467  if (axis == QwtScaleDraw::LeftScale || axis == QwtScaleDraw::RightScale)
4468  {
4469  if (d_plot->grid()->yEnabled())
4470  gridsID->setChecked(true);
4471  }
4472  else
4473  {
4474  if (d_plot->grid()->xEnabled())
4475  gridsID->setChecked(true);
4476  }
4477 
4478  menu.addSeparator();
4479  menu.addAction(tr("&Scale..."), this, SLOT(showScaleDialog()));
4480  menu.addAction(tr("&Properties..."), this, SLOT(showAxisDialog()));
4481  menu.exec(QCursor::pos());
4482 }
4483 
4485 {
4487 }
4488 
4490 {
4492 }
4493 
4495 {
4496  int axis = -1;
4497  if (selectedAxis == QwtScaleDraw::LeftScale || selectedAxis == QwtScaleDraw::RightScale)
4498  axis = selectedAxis - 2;
4499  else
4500  axis = selectedAxis + 2;
4501 
4502  d_plot->enableAxis(axis, false);
4503  scalePicker->refresh();
4504  emit modifiedGraph();
4505 }
4506 
4508 {
4510 }
4511 
4513 {
4514  showGrid(QwtScaleDraw::LeftScale);
4515  showGrid(QwtScaleDraw::BottomScale);
4516 }
4517 
4518 void Graph::showGrid(int axis)
4519 {
4520  Grid *grid = d_plot->grid();
4521  if (!grid)
4522  return;
4523 
4524  if (axis == QwtScaleDraw::LeftScale || axis == QwtScaleDraw::RightScale){
4525  grid->enableY(!grid->yEnabled());
4526  grid->enableYMin(!grid->yMinEnabled());
4527  } else if (axis == QwtScaleDraw::BottomScale || axis == QwtScaleDraw::TopScale){
4528  grid->enableX(!grid->xEnabled());
4529  grid->enableXMin(!grid->xMinEnabled());
4530  } else
4531  return;
4532 
4533  d_plot->replot();
4534  emit modifiedGraph();
4535 }
4536 
4538 {
4539  int i;
4540  Plot *plot = g->plotWidget();
4541  d_plot->setMargin(plot->margin());
4542 
4545 
4547  setFrame(plot->lineWidth(), plot->frameColor());
4548  setCanvasBackground(plot->canvasBackground());
4549 
4550  enableAxes(g->enabledAxes());
4551  setAxesColors(g->axesColors());
4554 
4555  grid()->copy(g->grid());
4556 
4557 
4558  d_plot->setTitle (g->plotWidget()->title());
4559 
4561 
4562  for (i=0;i<4;i++)
4563  {
4564  setAxisTitle(i, g->axisTitle(i));
4565  setAxisFont(i,g->axisFont(i));
4566  }
4567 
4571 
4575 
4579 
4583 
4585  removeLegend();
4586 
4587  for (i=0; i<g->curves(); i++)
4588  {
4589  QwtPlotItem *it = (QwtPlotItem *)g->plotItem(i);
4590  if (it->rtti() == QwtPlotItem::Rtti_PlotCurve)
4591  {
4592  DataCurve *cv = (DataCurve *)it;
4593  int n = cv->dataSize();
4594  int style = ((PlotCurve *)it)->type();
4595  QVector<double> x(n);
4596  QVector<double> y(n);
4597  for (int j=0; j<n; j++)
4598  {
4599  x[j]=cv->x(j);
4600  y[j]=cv->y(j);
4601  }
4602 
4603  PlotCurve *c = 0;
4604  if (style == Pie)
4605  {
4606  c = new QwtPieCurve(cv->table(), cv->title().text(), cv->startRow(), cv->endRow());
4607  ((QwtPieCurve*)c)->setRay(((QwtPieCurve*)cv)->ray());
4608  ((QwtPieCurve*)c)->setFirstColor(((QwtPieCurve*)cv)->firstColor());
4609  }
4610  else if (style == Function)
4611  {
4612  c = new FunctionCurve(parent, cv->title().text());
4613  static_cast<FunctionCurve*>(c)->copy(static_cast<FunctionCurve*>(it));
4614  }
4615  else if (style == VerticalBars || style == HorizontalBars)
4616  {
4617  c = new QwtBarCurve(((QwtBarCurve*)cv)->orientation(), cv->table(), cv->xColumnName(),
4618  cv->title().text(), cv->startRow(), cv->endRow());
4619  ((QwtBarCurve*)c)->copy((const QwtBarCurve*)cv);
4620  }
4621  else if (style == ErrorBars)
4622  {
4624  DataCurve *master_curve = masterCurve(er);
4625  if (master_curve)
4626  {
4627  c = new QwtErrorPlotCurve(cv->table(), cv->title().text());
4628  ((QwtErrorPlotCurve*)c)->copy(er);
4629  ((QwtErrorPlotCurve*)c)->setMasterCurve(master_curve);
4630  }
4631  }
4632  else if (style == Histogram)
4633  {
4634  c = new QwtHistogram(cv->table(), cv->title().text(), cv->startRow(), cv->endRow());
4635  ((QwtHistogram *)c)->copy((const QwtHistogram*)cv);
4636  }
4637  else if (style == VectXYXY || style == VectXYAM)
4638  {
4640  if (style == VectXYAM)
4641  vs = VectorCurve::XYAM;
4642  c = new VectorCurve(vs, cv->table(), cv->xColumnName(), cv->title().text(),
4643  ((VectorCurve *)cv)->vectorEndXAColName(),
4644  ((VectorCurve *)cv)->vectorEndYMColName(),
4645  cv->startRow(), cv->endRow());
4646  ((VectorCurve *)c)->copy((const VectorCurve *)cv);
4647  }
4648  else if (style == Box)
4649  {
4650  c = new BoxCurve(cv->table(), cv->title().text(), cv->startRow(), cv->endRow());
4651  ((BoxCurve*)c)->copy((const BoxCurve *)cv);
4652  QwtSingleArrayData dat(x[0], y, n);
4653  c->setData(dat);
4654  }
4655  else
4656  c = new DataCurve(cv->table(), cv->xColumnName(), cv->title().text(), cv->startRow(), cv->endRow());
4657 
4658  c_keys.resize(++n_curves);
4659  c_keys[i] = d_plot->insertCurve(c);
4660 
4661  c_type.resize(n_curves);
4662  c_type[i] = g->curveType(i);
4663 
4664  if (c_type[i] != Box && c_type[i] != ErrorBars)
4665  c->setData(x.data(), y.data(), n);
4666 
4667  c->setPen(cv->pen());
4668  c->setBrush(cv->brush());
4669  c->setStyle(cv->style());
4670  c->setSymbol(cv->symbol());
4671 
4672  if (cv->testCurveAttribute (QwtPlotCurve::Fitted))
4673  c->setCurveAttribute(QwtPlotCurve::Fitted, true);
4674  else if (cv->testCurveAttribute (QwtPlotCurve::Inverted))
4675  c->setCurveAttribute(QwtPlotCurve::Inverted, true);
4676 
4677  c->setAxis(cv->xAxis(), cv->yAxis());
4678  c->setVisible(cv->isVisible());
4679 
4680  QList<QwtPlotCurve *>lst = g->fitCurvesList();
4681  if (lst.contains((QwtPlotCurve *)it))
4682  d_fit_curves << c;
4683  }
4684  else if (it->rtti() == QwtPlotItem::Rtti_PlotSpectrogram)
4685  {
4686  Spectrogram *sp = ((Spectrogram *)it)->copy();
4687  c_keys.resize(++n_curves);
4688  c_keys[i] = d_plot->insertCurve(sp);
4689 
4690  sp->showColorScale(((Spectrogram *)it)->colorScaleAxis(), ((Spectrogram *)it)->hasColorScale());
4691  sp->setColorBarWidth(((Spectrogram *)it)->colorBarWidth());
4692  sp->setVisible(it->isVisible());
4693 
4694  c_type.resize(n_curves);
4695  c_type[i] = g->curveType(i);
4696  }
4697  }
4698 
4700  axisType = g->axisType;
4702  axisType = g->axisType;
4703 
4704  for (i=0; i<QwtPlot::axisCnt; i++)
4705  {
4706  QwtScaleWidget *sc = g->plotWidget()->axisWidget(i);
4707  if (!sc)
4708  continue;
4709 
4710  QwtScaleDraw *sd = g->plotWidget()->axisScaleDraw (i);
4711  if (sd->hasComponent(QwtAbstractScaleDraw::Labels))
4712  {
4713  if (axisType[i] == Graph::Numeric)
4715  else if (axisType[i] == Graph::Day)
4716  setLabelsDayFormat(i, axesFormatInfo[i].toInt());
4717  else if (axisType[i] == Graph::Month)
4718  setLabelsMonthFormat(i, axesFormatInfo[i].toInt());
4719  else if (axisType[i] == Graph::Time || axisType[i] == Graph::Date || axisType[i] == Graph::DateTime)
4721  else
4722  {
4723  QwtTextScaleDraw *sd = (QwtTextScaleDraw *)plot->axisScaleDraw (i);
4724  d_plot->setAxisScaleDraw(i, new QwtTextScaleDraw(sd->labelsMap()));
4725  }
4726  }
4727  else
4728  {
4729  sd = d_plot->axisScaleDraw (i);
4730  sd->enableComponent (QwtAbstractScaleDraw::Labels, false);
4731  }
4732  }
4733  for (i=0; i<QwtPlot::axisCnt; i++)
4734  {//set same scales
4735  const QwtScaleEngine *se = plot->axisScaleEngine(i);
4736  if (!se)
4737  continue;
4738 
4739  QwtScaleEngine *sc_engine = 0;
4740  if (se->transformation()->type() == QwtScaleTransformation::Log10)
4741  sc_engine = new QwtLog10ScaleEngine();
4742  else if (se->transformation()->type() == QwtScaleTransformation::Linear)
4743  sc_engine = new QwtLinearScaleEngine();
4744 
4745  int majorTicks = plot->axisMaxMajor(i);
4746  int minorTicks = plot->axisMaxMinor(i);
4747  d_plot->setAxisMaxMajor (i, majorTicks);
4748  d_plot->setAxisMaxMinor (i, minorTicks);
4749 
4750  const QwtScaleDiv *sd = plot->axisScaleDiv(i);
4751  QwtValueList lst = sd->ticks (QwtScaleDiv::MajorTick);
4752 
4753  d_user_step[i] = g->axisStep(i);
4754 
4755 #if QWT_VERSION >= 0x050200
4756  QwtScaleDiv div = sc_engine->divideScale (qMin(sd->lowerBound(), sd->upperBound()),
4757  qMax(sd->lowerBound(), sd->upperBound()), majorTicks, minorTicks, d_user_step[i]);
4758 #else
4759  QwtScaleDiv div = sc_engine->divideScale (qMin(sd->lBound(), sd->hBound()),
4760  qMax(sd->lBound(), sd->hBound()), majorTicks, minorTicks, d_user_step[i]);
4761 #endif
4762 
4763  if (se->testAttribute(QwtScaleEngine::Inverted))
4764  {
4765  sc_engine->setAttribute(QwtScaleEngine::Inverted);
4766  div.invert();
4767  }
4768 
4769  d_plot->setAxisScaleEngine (i, sc_engine);
4770  d_plot->setAxisScaleDiv (i, div);
4771  }
4772 
4777 
4778  setAxisLabelRotation(QwtPlot::xBottom, g->labelsRotation(QwtPlot::xBottom));
4779  setAxisLabelRotation(QwtPlot::xTop, g->labelsRotation(QwtPlot::xTop));
4780 
4781  QVector<int> imag = g->imageMarkerKeys();
4782  for (i=0; i<(int)imag.size(); i++)
4783  addImage((ImageMarker*)g->imageMarker(imag[i]));
4784 
4785  QVector<int> txtMrkKeys=g->textMarkerKeys();
4786  for (i=0; i<(int)txtMrkKeys.size(); i++){
4787  Legend* mrk = (Legend*)g->textMarker(txtMrkKeys[i]);
4788  if (!mrk)
4789  continue;
4790 
4791  if (txtMrkKeys[i] == g->legendMarkerID)
4793  else
4794  insertTextMarker(mrk);
4795  }
4796 
4797  QVector<int> l = g->lineMarkerKeys();
4798  for (i=0; i<(int)l.size(); i++){
4799  ArrowMarker* lmrk=(ArrowMarker*)g->arrow(l[i]);
4800  if (lmrk)
4801  addArrow(lmrk);
4802  }
4803  d_plot->replot();
4804 
4805  if (isPiePlot()){
4806  QwtPieCurve *c = (QwtPieCurve *)curve(0);
4807  c->updateBoundingRect();
4808  }
4809 }
4810 
4811 void Graph::plotBoxDiagram(Table *w, const QStringList& names, int startRow, int endRow)
4812 {
4813  if (endRow < 0)
4814  endRow = w->numRows() - 1;
4815 
4816  for (int j = 0; j <(int)names.count(); j++){
4817  BoxCurve *c = new BoxCurve(w, names[j], startRow, endRow);
4818  c->setData(QwtSingleArrayData(double(j+1), QwtArray<double>(), 0));
4819  c->loadData();
4820 
4821  c_keys.resize(++n_curves);
4822  c_keys[n_curves-1] = d_plot->insertCurve(c);
4823  c_type.resize(n_curves);
4824  c_type[n_curves-1] = Box;
4825 
4826  c->setPen(QPen(ColorButton::color(j), 1));
4827  c->setSymbol(QwtSymbol(QwtSymbol::NoSymbol, QBrush(), QPen(ColorButton::color(j), 1), QSize(7,7)));
4828  }
4829 
4831  if (mrk)
4832  mrk->setText(legendText());
4833 
4834  axisType[QwtPlot::xBottom] = ColHeader;
4835  d_plot->setAxisScaleDraw (QwtPlot::xBottom, new QwtTextScaleDraw(w->selectedYLabels()));
4836  d_plot->setAxisMaxMajor(QwtPlot::xBottom, names.count()+1);
4837  d_plot->setAxisMaxMinor(QwtPlot::xBottom, 0);
4838 
4839  axisType[QwtPlot::xTop] = ColHeader;
4840  d_plot->setAxisScaleDraw (QwtPlot::xTop, new QwtTextScaleDraw(w->selectedYLabels()));
4841  d_plot->setAxisMaxMajor(QwtPlot::xTop, names.count()+1);
4842  d_plot->setAxisMaxMinor(QwtPlot::xTop, 0);
4843 
4844  axesFormatInfo[QwtPlot::xBottom] = w->name();
4845  axesFormatInfo[QwtPlot::xTop] = w->name();
4846 }
4847 
4848 void Graph::setCurveStyle(int index, int s)
4849 {
4850  QwtPlotCurve *c = curve(index);
4851  if (!c)
4852  return;
4853 
4854  if (s == 5)//ancient spline style in Qwt 4.2.0
4855  {
4856  s = QwtPlotCurve::Lines;
4857  c->setCurveAttribute(QwtPlotCurve::Fitted, true);
4858  c_type[index] = Spline;
4859  }
4860  else if (s == QwtPlotCurve::Lines)
4861  c->setCurveAttribute(QwtPlotCurve::Fitted, false);
4862  else if (s == 6)// Vertical Steps
4863  {
4864  s = QwtPlotCurve::Steps;
4865  c->setCurveAttribute(QwtPlotCurve::Inverted, true);
4866  c_type[index] = VerticalSteps;
4867  }
4868  else if (s == QwtPlotCurve::Steps)// Horizontal Steps
4869  {
4870  c->setCurveAttribute(QwtPlotCurve::Inverted, false);
4871  c_type[index] = HorizontalSteps;
4872  }
4873  c->setStyle((QwtPlotCurve::CurveStyle)s);
4874 }
4875 
4876 void Graph::setCurveSymbol(int index, const QwtSymbol& s)
4877 {
4878  QwtPlotCurve *c = curve(index);
4879  if (!c)
4880  return;
4881 
4882  c->setSymbol(s);
4883 }
4884 
4885 void Graph::setCurvePen(int index, const QPen& p)
4886 {
4887  QwtPlotCurve *c = curve(index);
4888  if (!c)
4889  return;
4890 
4891  c->setPen(p);
4892 }
4893 
4894 void Graph::setCurveBrush(int index, const QBrush& b)
4895 {
4896  QwtPlotCurve *c = curve(index);
4897  if (!c)
4898  return;
4899 
4900  c->setBrush(b);
4901 }
4902 
4903 void Graph::openBoxDiagram(Table *w, const QStringList& l, int fileVersion)
4904 {
4905  if (!w)
4906  return;
4907 
4908  int s_offset = 0;
4909  int startRow = 0;
4910  int endRow = w->numRows()-1;
4911  if (fileVersion >= 90)
4912  {
4913  startRow = l[l.count()-3].toInt();
4914  endRow = l[l.count()-2].toInt();
4915  }
4916 
4917  BoxCurve *c = new BoxCurve(w, l[2], startRow, endRow);
4918  c->setData(QwtSingleArrayData(l[1].toDouble(), QwtArray<double>(), 0));
4919  c->setData(QwtSingleArrayData(l[1].toDouble(), QwtArray<double>(), 0));
4920  c->loadData();
4921 
4922  c_keys.resize(++n_curves);
4923  c_keys[n_curves-1] = d_plot->insertCurve(c);
4924  c_type.resize(n_curves);
4925  c_type[n_curves-1] = Box;
4926 
4927  if (fileVersion >= 0x011800) // 1.24.0
4928  {
4929  s_offset = 3;
4930  }
4931  c->setMaxStyle(SymbolBox::style(l[16+s_offset].toInt()));
4932  c->setP99Style(SymbolBox::style(l[17+s_offset].toInt()));
4933  c->setMeanStyle(SymbolBox::style(l[18+s_offset].toInt()));
4934  c->setP1Style(SymbolBox::style(l[19+s_offset].toInt()));
4935  c->setMinStyle(SymbolBox::style(l[20+s_offset].toInt()));
4936 
4937  c->setBoxStyle(l[21+s_offset].toInt());
4938  c->setBoxWidth(l[22+s_offset].toInt());
4939  c->setBoxRange(l[23+s_offset].toInt(), l[24+s_offset].toDouble());
4940  c->setWhiskersRange(l[25+s_offset].toInt(), l[26+s_offset].toDouble());
4941 }
4942 
4944  if (d_active_tool) delete d_active_tool;
4945  d_active_tool = tool;
4946  if (d_range_selector) {
4947  if (tool)
4948  // we want to use tool now, so disable range selection
4949  d_range_selector->setEnabled(false);
4950  else
4951  // re-enable range selection
4952  d_range_selector->setEnabled(true);
4953  }
4954 }
4955 
4957 {
4958  if (zoomOn())
4959  zoom(false);
4960  if (drawLineActive())
4961  drawLine(false);
4962  setActiveTool(NULL);
4963  if (d_range_selector)
4964  delete d_range_selector;
4965 }
4966 
4967 bool Graph::enableRangeSelectors(const QObject *status_target, const char *status_slot)
4968 {
4969  // disable other tools, otherwise it's undefined what tool should handle mouse clicks
4970  disableTools();
4971  d_range_selector = new RangeSelectorTool(this, status_target, status_slot);
4972  connect(d_range_selector, SIGNAL(changed()), this, SIGNAL(dataRangeChanged()));
4973  return true;
4974 }
4975 
4976 void Graph::setTextMarkerDefaults(int f, const QFont& font,
4977  const QColor& textCol, const QColor& backgroundCol)
4978 {
4979  defaultMarkerFont = font;
4980  defaultMarkerFrame = f;
4981  defaultTextMarkerColor = textCol;
4982  defaultTextMarkerBackground = backgroundCol;
4983 }
4984 
4985 void Graph::setArrowDefaults(int lineWidth, const QColor& c, Qt::PenStyle style,
4986  int headLength, int headAngle, bool fillHead)
4987 {
4988  defaultArrowLineWidth = lineWidth;
4989  defaultArrowColor = c;
4990  defaultArrowLineStyle = style;
4991  defaultArrowHeadLength = headLength;
4992  defaultArrowHeadAngle = headAngle;
4993  defaultArrowHeadFill = fillHead;
4994 }
4995 
4997 {
4998  QWidget *w = (QWidget *)parent()->parent()->parent();
4999  return QString(w->objectName());
5000 }
5001 
5002 void Graph::guessUniqueCurveLayout(int& colorIndex, int& symbolIndex)
5003 {
5004  colorIndex = 0;
5005  symbolIndex = 0;
5006 
5007  int curve_index = n_curves - 1;
5008  if (curve_index >= 0 && c_type[curve_index] == ErrorBars)
5009  {// find out the pen color of the master curve
5010  QwtErrorPlotCurve *er = (QwtErrorPlotCurve *)d_plot->curve(c_keys[curve_index]);
5011  DataCurve *master_curve = er->masterCurve();
5012  if (master_curve)
5013  {
5014  colorIndex = ColorButton::colorIndex(master_curve->pen().color());
5015  return;
5016  }
5017  }
5018 
5019  for (int i=0; i<n_curves; i++)
5020  {
5021  const QwtPlotCurve *c = curve(i);
5022  if (c && c->rtti() == QwtPlotItem::Rtti_PlotCurve)
5023  {
5024  int index = ColorButton::colorIndex(c->pen().color());
5025  if (index > colorIndex)
5026  colorIndex = index;
5027 
5028  QwtSymbol symb = c->symbol();
5029  index = SymbolBox::symbolIndex(symb.style());
5030  if (index > symbolIndex)
5031  symbolIndex = index;
5032  }
5033  }
5034  if (n_curves > 1)
5035  colorIndex = (colorIndex+1)%16;
5036  if (colorIndex == 13) //avoid white invisible curves
5037  colorIndex = 0;
5038 
5039  symbolIndex = (symbolIndex+1)%15;
5040  if (!symbolIndex)
5041  symbolIndex = 1;
5042 }
5043 
5044 void Graph::addFitCurve(QwtPlotCurve *c)
5045 {
5046  if (c)
5047  d_fit_curves << c;
5048 }
5049 
5051 {
5052  QList<int> keys = d_plot->curveKeys();
5053  foreach(QwtPlotCurve *c, d_fit_curves)
5054  removeCurve(curveIndex(c));
5055 
5056  d_plot->replot();
5057 }
5058 
5060 {
5061  if (type != GrayMap && type != ColorMap && type != ContourMap)
5062  return;
5063 
5064  Spectrogram *d_spectrogram = new Spectrogram(m);
5065  if (type == GrayMap)
5066  d_spectrogram->setGrayScale();
5067  else if (type == ContourMap)
5068  {
5069  d_spectrogram->setDisplayMode(QwtPlotSpectrogram::ImageMode, false);
5070  d_spectrogram->setDisplayMode(QwtPlotSpectrogram::ContourMode, true);
5071  }
5072  else if (type == ColorMap)
5073  {
5074  d_spectrogram->setDefaultColorMap();
5075  d_spectrogram->setDisplayMode(QwtPlotSpectrogram::ContourMode, true);
5076  }
5077 
5078  c_keys.resize(++n_curves);
5079  c_keys[n_curves-1] = d_plot->insertCurve(d_spectrogram);
5080 
5081  c_type.resize(n_curves);
5082  c_type[n_curves-1] = type;
5083 
5084  QwtScaleWidget *rightAxis = d_plot->axisWidget(QwtPlot::yRight);
5085  rightAxis->setColorBarEnabled(type != ContourMap);
5086  rightAxis->setColorMap(d_spectrogram->data().range(), d_spectrogram->colorMap());
5087 
5088  d_plot->setAxisScale(QwtPlot::xBottom, m->xStart(), m->xEnd());
5089  d_plot->setAxisScale(QwtPlot::yLeft, m->yStart(), m->yEnd());
5090 
5091  d_plot->setAxisScale(QwtPlot::yRight,
5092  d_spectrogram->data().range().minValue(),
5093  d_spectrogram->data().range().maxValue());
5094  d_plot->enableAxis(QwtPlot::yRight, type != ContourMap);
5095 
5096  d_plot->replot();
5097 }
5098 
5099 void Graph::restoreSpectrogram(ApplicationWindow *app, const QStringList& lst)
5100 {
5101  QStringList::const_iterator line = lst.begin();
5102  QString s = (*line).trimmed();
5103  QString matrixName = s.remove("<matrix>").remove("</matrix>");
5104  Matrix *m = app->matrix(matrixName);
5105  if (!m)
5106  return;
5107 
5108  Spectrogram *sp = new Spectrogram(m);
5109 
5110  c_type.resize(++n_curves);
5112  c_keys.resize(n_curves);
5113  c_keys[n_curves-1] = d_plot->insertCurve(sp);
5114 
5115  for (line++; line != lst.end(); line++)
5116  {
5117  QString s = *line;
5118  if (s.contains("<ColorPolicy>"))
5119  {
5120  int color_policy = s.remove("<ColorPolicy>").remove("</ColorPolicy>").trimmed().toInt();
5121  if (color_policy == Spectrogram::GrayScale)
5122  sp->setGrayScale();
5123  else if (color_policy == Spectrogram::Default)
5124  sp->setDefaultColorMap();
5125  }
5126  else if (s.contains("<ColorMap>"))
5127  {
5128  s = *(++line);
5129  int mode = s.remove("<Mode>").remove("</Mode>").trimmed().toInt();
5130  s = *(++line);
5131  QColor color1 = QColor(COLORVALUE(s.remove("<MinColor>").remove("</MinColor>").trimmed()));
5132  s = *(++line);
5133  QColor color2 = QColor(COLORVALUE(s.remove("<MaxColor>").remove("</MaxColor>").trimmed()));
5134 
5135  QwtLinearColorMap colorMap = QwtLinearColorMap(color1, color2);
5136  colorMap.setMode((QwtLinearColorMap::Mode)mode);
5137 
5138  s = *(++line);
5139  int stops = s.remove("<ColorStops>").remove("</ColorStops>").trimmed().toInt();
5140  for (int i = 0; i < stops; i++)
5141  {
5142  s = (*(++line)).trimmed();
5143  QStringList l = s.remove("<Stop>").remove("</Stop>").split("\t");
5144  colorMap.addColorStop(l[0].toDouble(), QColor(COLORVALUE(l[1])));
5145  }
5146  sp->setCustomColorMap(colorMap);
5147  line++;
5148  }
5149  else if (s.contains("<Image>"))
5150  {
5151  int mode = s.remove("<Image>").remove("</Image>").trimmed().toInt();
5152  sp->setDisplayMode(QwtPlotSpectrogram::ImageMode, mode);
5153  }
5154  else if (s.contains("<ContourLines>"))
5155  {
5156  int contours = s.remove("<ContourLines>").remove("</ContourLines>").trimmed().toInt();
5157  sp->setDisplayMode(QwtPlotSpectrogram::ContourMode, contours);
5158  if (contours)
5159  {
5160  s = (*(++line)).trimmed();
5161  int levels = s.remove("<Levels>").remove("</Levels>").toInt();
5162  sp->setLevelsNumber(levels);
5163 
5164  s = (*(++line)).trimmed();
5165  int defaultPen = s.remove("<DefaultPen>").remove("</DefaultPen>").toInt();
5166  if (!defaultPen)
5167  sp->setDefaultContourPen(Qt::NoPen);
5168  else
5169  {
5170  s = (*(++line)).trimmed();
5171  QColor c = QColor(COLORVALUE(s.remove("<PenColor>").remove("</PenColor>")));
5172  s = (*(++line)).trimmed();
5173  int width = s.remove("<PenWidth>").remove("</PenWidth>").toInt();
5174  s = (*(++line)).trimmed();
5175  int style = s.remove("<PenStyle>").remove("</PenStyle>").toInt();
5176  sp->setDefaultContourPen(QPen(c, width, Graph::getPenStyle(style)));
5177  }
5178  }
5179  }
5180  else if (s.contains("<ColorBar>"))
5181  {
5182  s = *(++line);
5183  int color_axis = s.remove("<axis>").remove("</axis>").trimmed().toInt();
5184  s = *(++line);
5185  int width = s.remove("<width>").remove("</width>").trimmed().toInt();
5186 
5187  QwtScaleWidget *colorAxis = d_plot->axisWidget(color_axis);
5188  if (colorAxis)
5189  {
5190  colorAxis->setColorBarWidth(width);
5191  colorAxis->setColorBarEnabled(true);
5192  }
5193  line++;
5194  }
5195  else if (s.contains("<Visible>"))
5196  {
5197  int on = s.remove("<Visible>").remove("</Visible>").trimmed().toInt();
5198  sp->setVisible(on);
5199  }
5200  }
5201 }
5202 
5204 {
5205  if (!n_curves)
5206  {
5207  QMessageBox::warning(const_cast<Graph*>(this), tr("Warning"), tr("There are no curves available on this plot!"));
5208  return false;
5209  }
5210  else
5211  {
5212  for (int i=0; i < n_curves; i++)
5213  {
5214  QwtPlotItem *item = curve(i);
5215  if(item && item->rtti() != QwtPlotItem::Rtti_PlotSpectrogram)
5216  {
5217  QwtPlotCurve *c = (QwtPlotCurve *)item;
5218  if (c->dataSize() >= 2)
5219  return true;
5220  }
5221  }
5222  QMessageBox::warning(const_cast<Graph*>(this), tr("Error"),
5223  tr("There are no curves with more than two points on this plot. Operation aborted!"));
5224  return false;
5225  }
5226 }
5227 
5229 {
5230  setActiveTool(NULL);
5231  if (d_range_selector)
5232  delete d_range_selector;
5233  delete titlePicker;
5234  delete scalePicker;
5235  delete cp;
5236  delete d_plot;
5237 }
5238 
5239 void Graph::setAntialiasing(bool on, bool update)
5240 {
5241  if (d_antialiasing == on)
5242  return;
5243 
5244  d_antialiasing = on;
5245 
5246  if (update)
5247  {
5248  QList<int> curve_keys = d_plot->curveKeys();
5249  for (int i=0; i<(int)curve_keys.count(); i++)
5250  {
5251  QwtPlotItem *c = d_plot->curve(curve_keys[i]);
5252  if (c)
5253  c->setRenderHint(QwtPlotItem::RenderAntialiased, d_antialiasing);
5254  }
5255  QList<int> marker_keys = d_plot->markerKeys();
5256  for (int i=0; i<(int)marker_keys.count(); i++)
5257  {
5258  QwtPlotMarker *m = d_plot->marker(marker_keys[i]);
5259  if (m)
5260  m->setRenderHint(QwtPlotItem::RenderAntialiased, d_antialiasing);
5261  }
5262  d_plot->replot();
5263  }
5264 }
5265 
5267 {
5268  QList<int> mrkKeys = d_plot->markerKeys();
5269  int n = mrkKeys.size();
5270  if (n < 2)
5271  return false;
5272 
5273  int min_key = mrkKeys[0], max_key = mrkKeys[0];
5274  for (int i = 0; i<n; i++ )
5275  {
5276  if (mrkKeys[i] >= max_key)
5277  max_key = mrkKeys[i];
5278  if (mrkKeys[i] <= min_key)
5279  min_key = mrkKeys[i];
5280  }
5281 
5282  int key = selectedMarker;
5283  if (key >= 0)
5284  {
5285  key++;
5286  if ( key > max_key )
5287  key = min_key;
5288  } else
5289  key = min_key;
5290 
5291  cp->disableEditing();
5292 
5293  setSelectedMarker(key);
5294  return true;
5295 }
5296 
5297 QString Graph::axisFormatInfo(int axis)
5298 {
5299  if (axis < 0 || axis >= QwtPlot::axisCnt)
5300  return QString();
5301  else
5302  return axesFormatInfo[axis];
5303 }
5304 
5305 void Graph::updateCurveNames(const QString& oldName, const QString& newName, bool updateTableName)
5306 {
5307  //update plotted curves list
5308  QList<int> keys = d_plot->curveKeys();
5309  for (int i=0; i<(int)keys.count(); i++){
5310  QwtPlotItem *it = d_plot->plotItem(keys[i]);
5311  if (!it)
5312  continue;
5313  if (it->rtti() != QwtPlotItem::Rtti_PlotCurve)
5314  continue;
5315 
5316  DataCurve *c = (DataCurve *)it;
5317  if (c->type() != Function && c->plotAssociation().contains(oldName))
5318  c->updateColumnNames(oldName, newName, updateTableName);
5319  }
5320 
5321  if (legendMarkerID >= 0 )
5322  {//update legend
5323  Legend * mrk = (Legend*) d_plot->marker(legendMarkerID);
5324  if (mrk)
5325  {
5326  QStringList lst = mrk->text().split("\n", QString::SkipEmptyParts);
5327  lst.replaceInStrings(oldName, newName);
5328  mrk->setText(lst.join("\n"));
5329  d_plot->replot();
5330  }
5331  }
5332 }
5333 
5334 void Graph::setCurveFullRange(int curveIndex)
5335 {
5337  if (c)
5338  {
5339  c->setFullRange();
5340  updatePlot();
5341  emit modifiedGraph();
5342  }
5343 }
5344 
5346 {
5347  QList<int> keys = d_plot->curveKeys();
5348  for (int i=0; i<(int)keys.count(); i++)
5349  {
5350  QwtPlotItem *it = d_plot->plotItem(keys[i]);
5351  if (!it)
5352  continue;
5353  if (it->rtti() == QwtPlotItem::Rtti_PlotSpectrogram)
5354  continue;
5355  if (((PlotCurve *)it)->type() == Function)
5356  continue;
5357 
5358  if (((DataCurve *)it)->plotAssociation() == er->masterCurve()->plotAssociation())
5359  return (DataCurve *)it;
5360  }
5361  return 0;
5362 }
5363 
5364 DataCurve* Graph::masterCurve(const QString& xColName, const QString& yColName)
5365 {
5366  QString master_curve = xColName + "(X)," + yColName + "(Y)";
5367  QList<int> keys = d_plot->curveKeys();
5368  for (int i=0; i<(int)keys.count(); i++)
5369  {
5370  QwtPlotItem *it = d_plot->plotItem(keys[i]);
5371  if (!it)
5372  continue;
5373  if (it->rtti() == QwtPlotItem::Rtti_PlotSpectrogram)
5374  continue;
5375  if (((PlotCurve *)it)->type() == Function)
5376  continue;
5377 
5378  if (((DataCurve *)it)->plotAssociation() == master_curve)
5379  return (DataCurve *)it;
5380  }
5381  return 0;
5382 }
5383 
5384 void Graph::showCurve(int index, bool visible)
5385 {
5386  QwtPlotItem *it = plotItem(index);
5387  if (it)
5388  it->setVisible(visible);
5389 
5390  emit modifiedGraph();
5391 }
5392 
5394 {
5395  int c = 0;
5396  QList<int> keys = d_plot->curveKeys();
5397  for (int i=0; i<(int)keys.count(); i++)
5398  {
5399  QwtPlotItem *it = d_plot->plotItem(keys[i]);
5400  if (it && it->isVisible())
5401  c++;
5402  }
5403  return c;
5404 }
5405 
5406 QPrinter::PageSize Graph::minPageSize(const QPrinter& printer, const QRect& r)
5407 {
5408  double x_margin = 0.2/2.54*printer.logicalDpiX(); // 2 mm margins
5409  double y_margin = 0.2/2.54*printer.logicalDpiY();
5410  double w_mm = 2*x_margin + (double)(r.width())/(double)printer.logicalDpiX() * 25.4;
5411  double h_mm = 2*y_margin + (double)(r.height())/(double)printer.logicalDpiY() * 25.4;
5412 
5413  int w, h;
5414  if (w_mm/h_mm > 1)
5415  {
5416  w = (int)ceil(w_mm);
5417  h = (int)ceil(h_mm);
5418  }
5419  else
5420  {
5421  h = (int)ceil(w_mm);
5422  w = (int)ceil(h_mm);
5423  }
5424 
5425  QPrinter::PageSize size = QPrinter::A5;
5426  if (w < 45 && h < 32)
5427  size = QPrinter::B10;
5428  else if (w < 52 && h < 37)
5429  size = QPrinter::A9;
5430  else if (w < 64 && h < 45)
5431  size = QPrinter::B9;
5432  else if (w < 74 && h < 52)
5433  size = QPrinter::A8;
5434  else if (w < 91 && h < 64)
5435  size = QPrinter::B8;
5436  else if (w < 105 && h < 74)
5437  size = QPrinter::A7;
5438  else if (w < 128 && h < 91)
5439  size = QPrinter::B7;
5440  else if (w < 148 && h < 105)
5441  size = QPrinter::A6;
5442  else if (w < 182 && h < 128)
5443  size = QPrinter::B6;
5444  else if (w < 210 && h < 148)
5445  size = QPrinter::A5;
5446  else if (w < 220 && h < 110)
5447  size = QPrinter::DLE;
5448  else if (w < 229 && h < 163)
5449  size = QPrinter::C5E;
5450  else if (w < 241 && h < 105)
5451  size = QPrinter::Comm10E;
5452  else if (w < 257 && h < 182)
5453  size = QPrinter::B5;
5454  else if (w < 279 && h < 216)
5455  size = QPrinter::Letter;
5456  else if (w < 297 && h < 210)
5457  size = QPrinter::A4;
5458  else if (w < 330 && h < 210)
5459  size = QPrinter::Folio;
5460  else if (w < 356 && h < 216)
5461  size = QPrinter::Legal;
5462  else if (w < 364 && h < 257)
5463  size = QPrinter::B4;
5464  else if (w < 420 && h < 297)
5465  size = QPrinter::A3;
5466  else if (w < 515 && h < 364)
5467  size = QPrinter::B3;
5468  else if (w < 594 && h < 420)
5469  size = QPrinter::A2;
5470  else if (w < 728 && h < 515)
5471  size = QPrinter::B2;
5472  else if (w < 841 && h < 594)
5473  size = QPrinter::A1;
5474  else if (w < 1030 && h < 728)
5475  size = QPrinter::B1;
5476  else if (w < 1189 && h < 841)
5477  size = QPrinter::A0;
5478  else if (w < 1456 && h < 1030)
5479  size = QPrinter::B0;
5480 
5481  return size;
5482 }
5483 
5484 int Graph::mapToQwtAxis(int axis)
5485 {
5486  int a=-1;
5487  switch(axis)
5488  {
5489  case 0:
5490  a = QwtPlot::xBottom;
5491  break;
5492  case 1:
5493  a = QwtPlot::yLeft;
5494  break;
5495  case 2:
5496  a = QwtPlot::xTop;
5497  break;
5498  case 3:
5499  a = QwtPlot::yRight;
5500  break;
5501  }
5502  return a;
5503 }
5504 
5505 void Graph::print(QPainter *painter, const QRect &plotRect,
5506  const QwtPlotPrintFilter &pfilter)
5507 {
5508  d_plot->print(painter, plotRect, pfilter);
5509 }
5510 
5512 {
5513  deselectMarker();
5514  scalePicker->deselect();
5515  titlePicker->setSelected(false);
5516 }
5517 
PlotToolInterface
Definition: PlotToolInterface.h:60
Graph::insertFunctionCurve
bool insertFunctionCurve(ApplicationWindow *parent, const QStringList &func_spec, int points, int fileVersion)
Used when reading from a project file.
Definition: Graph.cpp:3954
Matrix
Matrix worksheet class.
Definition: Matrix.h:52
Graph::getBrushStyle
static Qt::BrushStyle getBrushStyle(int style)
Definition: Graph.cpp:4229
QwtErrorPlotCurve::plusSide
bool plusSide()
Definition: QwtErrorPlotCurve.h:70
Plot::curveKeys
QList< int > curveKeys()
Definition: Plot.h:55
Graph::setCurveSymbol
void setCurveSymbol(int index, const QwtSymbol &s)
Definition: Graph.cpp:4876
Graph::showMarkerPopupMenu
void showMarkerPopupMenu()
Graph::addArrow
void addArrow(ArrowMarker *mrk)
Definition: Graph.cpp:2653
Matrix::yStart
double yStart()
Return the Y value corresponding to row 1.
Definition: Matrix.h:267
TimeScaleDraw
Definition: ScaleDraw.h:99
Graph::print
void print()
Definition: Graph.cpp:1429
Graph::widthLine
int widthLine
Definition: Graph.h:767
QwtErrorPlotCurve::setXErrors
void setXErrors(bool yes)
Definition: QwtErrorPlotCurve.cpp:202
PatternBox::patternIndex
static int patternIndex(const Qt::BrushStyle &style)
Definition: PatternBox.cpp:178
Graph::saveMarkers
QString saveMarkers()
Definition: Graph.cpp:2708
FunctionCurve::Parametric
@ Parametric
Definition: FunctionCurve.h:41
Graph::setXAxisTitleFont
void setXAxisTitleFont(const QFont &fnt)
Definition: Graph.cpp:892
Graph::setAntialiasing
void setAntialiasing(bool on=true, bool update=true)
Enables/Disables antialiasing of plot items.
Definition: Graph.cpp:5239
QwtHistogram::autoBinning
bool autoBinning()
Definition: QwtHistogram.h:42
Graph::plotItemIndex
int plotItemIndex(QwtPlotItem *it) const
get plot item by index
Definition: Graph.cpp:2811
Table::column
Column * column(int index) const
Return column number 'index'.
Definition: Table.h:121
QwtHistogram::loadData
virtual bool loadData()
Definition: QwtHistogram.cpp:99
Graph::cutTitle
void cutTitle()
Definition: Graph.cpp:4393
Graph::contextMenuEvent
void contextMenuEvent(QContextMenuEvent *)
Definition: Graph.cpp:3698
Graph::createIntensityTable
void createIntensityTable(const QString &)
Graph::enableAxes
void enableAxes(QVector< bool > axesOn)
Definition: Graph.cpp:321
Table::Text
@ Text
Definition: Table.h:57
Graph::saveAxesColors
QString saveAxesColors()
Definition: Graph.cpp:970
Graph::visibleCurves
int visibleCurves()
Definition: Graph.cpp:5393
Graph::insertTextMarker
long insertTextMarker(Legend *mrk)
Definition: Graph.cpp:2687
Spectrogram::Default
@ Default
Definition: Spectrogram.h:48
FunctionCurve::setFunctionType
void setFunctionType(const FunctionType &t)
Definition: FunctionCurve.h:60
VectorCurve::setVectorEnd
void setVectorEnd(const QString &xColName, const QString &yColName)
Definition: VectorCurve.cpp:185
Table::Date
@ Date
Definition: Table.h:57
Graph::drawLine
void drawLine(bool on, bool arrow=false)
Draws a line/arrow depending on the value of "arrow".
Definition: Graph.cpp:3851
Table::colPlotDesignation
SciDAVis::PlotDesignation colPlotDesignation(int col)
Definition: Table.cpp:1277
QwtSingleArrayData
Single array data (extension to QwtData)
Definition: BoxCurve.h:97
Graph::topAxisTitleDblClicked
void topAxisTitleDblClicked()
BoxCurve::setMeanStyle
void setMeanStyle(QwtSymbol::Style s)
Definition: BoxCurve.h:55
Table::columnCount
int columnCount()
Definition: Table.cpp:902
Graph::setRightAxisTitleFont
void setRightAxisTitleFont(const QFont &fnt)
Definition: Graph.cpp:901
Graph::showTitleContextMenu
void showTitleContextMenu()
Definition: Graph.cpp:4382
Graph::exportToFile
void exportToFile(const QString &fileName)
Provided for convenience in scripts.
Definition: Graph.cpp:1357
FunctionCurve::setFormulas
void setFormulas(const QStringList &lst)
Definition: FunctionCurve.h:51
Graph::insertImageMarker
void insertImageMarker(const QStringList &lst, int fileVersion)
Definition: Graph.cpp:3822
Spectrogram::setLevelsNumber
void setLevelsNumber(int levels)
Definition: Spectrogram.cpp:84
Graph::drawLineActive
bool drawLineActive()
Definition: Graph.h:382
Matrix::xEnd
double xEnd()
Return the X value corresponding to the last column.
Definition: Matrix.h:265
ArrowMarker::filledArrowHead
bool filledArrowHead()
Definition: ArrowMarker.h:104
Graph::removeLegend
void removeLegend()
Definition: Graph.cpp:1758
Grid::copy
void copy(Grid *)
Definition: Grid.cpp:231
Graph::zoom
void zoom(bool on)
Definition: Graph.cpp:3735
Graph::cutMarker
void cutMarker()
Definition: Graph.cpp:1595
Table::DateTime
@ DateTime
Definition: Table.h:57
Graph::arrowMarkerSelected
bool arrowMarkerSelected()
Definition: Graph.cpp:1601
FunctionCurve.h
Graph::setTitleFont
void setTitleFont(const QFont &fnt)
Definition: Graph.cpp:1073
Plot::insertMarker
int insertMarker(QwtPlotMarker *m)
Definition: Plot.cpp:471
Graph::setAxisTitle
void setAxisTitle(int axis, const QString &text)
Definition: Graph.cpp:1164
Graph::loadAxesOptions
void loadAxesOptions(const QString &s)
used when opening a project file
Definition: Graph.cpp:1993
BoxCurve::p99Style
QwtSymbol::Style p99Style()
Definition: BoxCurve.h:59
Plot::Automatic
@ Automatic
Definition: Plot.h:52
Graph::deleteFitCurves
void deleteFitCurves()
Definition: Graph.cpp:5050
Plot::closestCurve
int closestCurve(int xpos, int ypos, int &dist, int &point)
Definition: Plot.cpp:427
Graph::setYAxisTitleColor
void setYAxisTitleColor(const QColor &c)
Definition: Graph.cpp:2150
ArrowMarker
Draws lines and arrows on a QwtPlot.
Definition: ArrowMarker.h:44
Graph::curveKey
long curveKey(int curve)
Definition: Graph.h:198
Graph::exportImage
void exportImage(const QString &fileName, int quality=-1)
Definition: Graph.cpp:1382
SciDAVis::yErr
@ yErr
y errors
Definition: globals.h:61
QwtErrorPlotCurve::drawMinusSide
void drawMinusSide(bool yes)
Definition: QwtErrorPlotCurve.h:74
Graph::auxArrowHeadLength
int auxArrowHeadLength
Definition: Graph.h:770
Graph::setActiveTool
void setActiveTool(PlotToolInterface *tool)
Change the active tool, deleting the old one if it exists.
Definition: Graph.cpp:4943
Graph::auxMrkWidth
int auxMrkWidth
Definition: Graph.h:769
Graph::openBoxDiagram
void openBoxDiagram(Table *w, const QStringList &l, int fileVersion)
Definition: Graph.cpp:4903
Graph::auxFilledArrowHead
bool auxFilledArrowHead
Definition: Graph.h:774
Graph::canvasFrameColor
QColor canvasFrameColor()
Definition: Graph.cpp:1916
Graph::deselectMarker
void deselectMarker()
Reset any selection states on markers.
Definition: Graph.cpp:203
VectorCurve::setWidth
void setWidth(int w)
Definition: VectorCurve.cpp:206
Graph::addTimeStamp
void addTimeStamp()
Definition: Graph.cpp:2510
Graph::mapToQwtAxis
static int mapToQwtAxis(int axis)
Definition: Graph.cpp:5484
Graph::Function
@ Function
Definition: Graph.h:131
QwtErrorPlotCurve::width
int width()
Definition: QwtErrorPlotCurve.h:55
Plot::axesLinewidth
int axesLinewidth() const
Definition: Plot.cpp:379
Graph::imageMarkerKeys
QVector< int > imageMarkerKeys()
Definition: Graph.h:399
Plot::Scientific
@ Scientific
Definition: Plot.h:52
Graph::insertPlotItem
void insertPlotItem(QwtPlotItem *i, int type)
Definition: Graph.cpp:3281
QwtSupersciptsScaleDraw
Definition: ScaleDraw.h:192
CurveLayout::fillCol
unsigned int fillCol
symbol fill color
Definition: Graph.h:80
Graph::loadAxesLinewidth
void loadAxesLinewidth(int width)
used when opening a project file
Definition: Graph.cpp:2033
Graph::hideSelectedAxis
void hideSelectedAxis()
Definition: Graph.cpp:4494
QwtErrorPlotCurve
Error bars curve.
Definition: QwtErrorPlotCurve.h:37
Graph::setMajorTicksType
void setMajorTicksType(const QList< int > &lst)
Definition: Graph.cpp:530
Column.h
Graph::minPageSize
static QPrinter::PageSize minPageSize(const QPrinter &printer, const QRect &r)
Definition: Graph.cpp:5406
BoxCurve::minStyle
QwtSymbol::Style minStyle()
Definition: BoxCurve.h:49
CurveLayout::lCapStyle
int lCapStyle
line CapStyle
Definition: Graph.h:72
Graph::setCurvePen
void setCurvePen(int index, const QPen &p)
Definition: Graph.cpp:4885
Graph::defaultArrowColor
QColor defaultArrowColor
Definition: Graph.h:777
Table::colLabel
QString colLabel(int col)
Definition: Table.cpp:1272
Graph::viewImageDialog
void viewImageDialog()
Graph::exportSVG
void exportSVG(const QString &fname)
Definition: Graph.cpp:1487
Graph::d_images
QVector< int > d_images
Images on plot keys.
Definition: Graph.h:755
QwtErrorPlotCurve::masterCurve
DataCurve * masterCurve()
Returns the master curve to which this error bars curve is attached.
Definition: QwtErrorPlotCurve.h:77
SciDAVis::xErr
@ xErr
x errors
Definition: globals.h:60
Legend::text
QString text()
Definition: Legend.h:64
FunctionCurve::setVariable
void setVariable(const QString &s)
Definition: FunctionCurve.h:57
Graph::setYAxisTitleFont
void setYAxisTitleFont(const QFont &fnt)
Definition: Graph.cpp:883
ArrowMarker::headAngle
int headAngle()
The angle of the arrow head.
Definition: ArrowMarker.h:100
ScalePicker::deselect
void deselect()
Definition: ScalePicker.cpp:280
Graph::setAxisTitleFont
void setAxisTitleFont(int axis, const QFont &fnt)
Definition: Graph.cpp:919
FunctionCurve::formulas
QStringList formulas()
Definition: FunctionCurve.h:50
Graph::setXAxisTitle
void setXAxisTitle(const QString &text)
Definition: Graph.cpp:1089
SciDAVis::Y
@ Y
y values
Definition: globals.h:58
Graph::Date
@ Date
Definition: Graph.h:127
SymbolBox::symbolIndex
static int symbolIndex(const QwtSymbol::Style &style)
Definition: SymbolBox.cpp:176
Graph::defaultArrowHeadFill
bool defaultArrowHeadFill
Definition: Graph.h:779
QwtErrorPlotCurve::setColor
void setColor(const QColor &c)
Definition: QwtErrorPlotCurve.cpp:217
Graph::saveTitle
QString saveTitle()
Definition: Graph.cpp:2217
Matrix::xStart
double xStart()
Return the X value corresponding to column 1.
Definition: Matrix.h:263
Graph::deselect
void deselect()
Definition: Graph.cpp:5511
Graph::defaultArrowLineStyle
Qt::PenStyle defaultArrowLineStyle
Definition: Graph.h:780
Graph::setLabelsMonthFormat
void setLabelsMonthFormat(int axis, int format)
Definition: Graph.cpp:740
ArrowMarker::updateBoundingRect
void updateBoundingRect()
Recalculates the bounding rectangle in values coordinates using the pixel coordinats when the scales ...
Definition: ArrowMarker.cpp:377
DataCurve::setVisible
void setVisible(bool on)
Definition: PlotCurve.cpp:333