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)  

Legend.cpp
Go to the documentation of this file.
1 
11 
29 #include "Legend.h"
30 #include "QwtPieCurve.h"
31 #include "VectorCurve.h"
32 
33 #include <QPainter>
34 #include <QPolygon>
35 #include <QMessageBox>
36 
37 #include <qwt_plot.h>
38 #include <qwt_scale_widget.h>
39 #include <qwt_painter.h>
40 #include <qwt_plot_layout.h>
41 #include <qwt_plot_canvas.h>
42 #include <qwt_layout_metrics.h>
43 #include <qwt_symbol.h>
44 
46  d_plot(plot),
47  d_frame (0),
48  d_angle(0)
49 {
50  d_text = new QwtText(QString::null, QwtText::RichText);
51  d_text->setFont(QFont("Arial",12, QFont::Normal, false));
52  d_text->setRenderFlags(Qt::AlignTop|Qt::AlignLeft);
53  d_text->setBackgroundBrush(QBrush(Qt::NoBrush));
54  d_text->setColor(Qt::black);
55  d_text->setBackgroundPen (QPen(Qt::NoPen));
56  d_text->setPaintAttribute(QwtText::PaintBackground);
57 
58  hspace = 30;
59  left_margin = 10;
60  top_margin = 5;
61  d_shadow_size_x = 5;
62  d_shadow_size_y = 5;
63 }
64 
65 void Legend::draw(QPainter *p, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRect &) const
66 {
67  const int x = xMap.transform(xValue());
68  const int y = yMap.transform(yValue());
69 
70  QwtPainter::setMetricsMap(plot(), p->device());
71  const QwtMetricsMap map = QwtPainter::metricsMap();
72 
73  const int symbolLineLength = symbolsMaxLineLength();
74 
75  int width, height;
76  QwtArray<long> heights = itemsHeight(map.deviceToLayoutY(y), symbolLineLength, width, height);
77 
78  QRect rs = QRect(map.deviceToLayout(QPoint(x, y)), QSize(width, height));
79 
80  drawFrame(p, d_frame, rs);
81  drawSymbols(p, rs, heights, symbolLineLength);
82  drawLegends(p, rs, heights, symbolLineLength);
83 }
84 
85 void Legend::setText(const QString& s)
86 {
87  d_text->setText(s);
88 }
89 
90 void Legend::setFrameStyle(int style)
91 {
92  if (d_frame == style)
93  return;
94 
95  d_frame = style;
96 }
97 
98 void Legend::setBackgroundColor(const QColor& c)
99 {
100  if (d_text->backgroundBrush().color() == c)
101  return;
102 
103  d_text->setBackgroundBrush(QBrush(c));
104 }
105 
106 QRect Legend::rect() const
107 {
108  const QwtScaleMap &xMap = d_plot->canvasMap(xAxis());
109  const QwtScaleMap &yMap = d_plot->canvasMap(yAxis());
110 
111  const int x = xMap.transform(xValue());
112  const int y = yMap.transform(yValue());
113 
114  int width, height;
115  itemsHeight(y, symbolsMaxLineLength(), width, height);
116 
117  return QRect(QPoint(x, y), QSize(width - 1, height - 1));
118 }
119 
120 QwtDoubleRect Legend::boundingRect() const
121 {
122  QRect bounding_rect = rect();
123  const QwtScaleMap &x_map = d_plot->canvasMap(xAxis());
124  const QwtScaleMap &y_map = d_plot->canvasMap(yAxis());
125 
126  double left = x_map.invTransform(bounding_rect.left());
127  double right = x_map.invTransform(bounding_rect.right());
128  double top = y_map.invTransform(bounding_rect.top());
129  double bottom = y_map.invTransform(bounding_rect.bottom());
130 
131  return QwtDoubleRect(left, top, qAbs(right-left), qAbs(bottom-top));
132 }
133 
134 void Legend::setTextColor(const QColor& c)
135 {
136  if ( c == d_text->color() )
137  return;
138 
139  d_text->setColor(c);
140 }
141 
142 void Legend::setOrigin( const QPoint & p )
143 {
144  d_pos = p;
145 
146  const QwtScaleMap &xMap = d_plot->canvasMap(xAxis());
147  const QwtScaleMap &yMap = d_plot->canvasMap(yAxis());
148 
149  setXValue (xMap.invTransform(p.x()));
150  setYValue (yMap.invTransform(p.y()));
151 }
152 
154 {
155  if (!d_plot)
156  return;
157 
158  const QwtScaleMap &xMap = d_plot->canvasMap(xAxis());
159  const QwtScaleMap &yMap = d_plot->canvasMap(yAxis());
160 
161  const QwtScaleDiv *xScDiv = d_plot->axisScaleDiv (xAxis());
162  double xVal = xMap.invTransform(d_pos.x());
163  if (!xScDiv->contains(xVal))
164  return;
165 
166  const QwtScaleDiv *yScDiv = d_plot->axisScaleDiv (yAxis());
167  double yVal = yMap.invTransform(d_pos.y());
168  if (!yScDiv->contains(yVal))
169  return;
170 
171  setXValue (xVal);
172  setYValue (yVal);
173 }
174 
175 void Legend::setOriginCoord(double x, double y)
176 {
177  if (xValue() == x && yValue() == y)
178  return;
179 
180  setXValue(x);
181  setYValue(y);
182 
183  const QwtScaleMap &xMap = d_plot->canvasMap(xAxis());
184  const QwtScaleMap &yMap = d_plot->canvasMap(yAxis());
185 
186  d_pos = QPoint(xMap.transform(x), yMap.transform(y));
187 }
188 
189 void Legend::setFont(const QFont& font)
190 {
191  if ( font == d_text->font() )
192  return;
193 
194  d_text->setFont(font);
195 }
196 
197 void Legend::drawFrame(QPainter *p, int type, const QRect& rect) const
198 {
199  p->save();
200  p->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin));
201  if (type == None)
202  QwtPainter::fillRect (p, rect, d_text->backgroundBrush());
203 
204  if (type == Line)
205  {
206  // drawing/filling in one go broken for PDF export:
207  // pen "inherits" alpha value of background brush
208  QwtPainter::fillRect(p, rect, d_text->backgroundBrush());
209  QwtPainter::drawRect(p, rect);
210  }
211  else if (type == Shadow)
212  {
213  QwtPainter::fillRect(p, rect, d_text->backgroundBrush());
214  QwtPainter::drawRect(p,rect);
215 
216  QRect shadow_right = QRect(rect.right(), rect.y() + d_shadow_size_y, d_shadow_size_x, rect.height()-1);
217  QRect shadow_bottom = QRect(rect.x() + d_shadow_size_x, rect.bottom(), rect.width()-1, d_shadow_size_y);
218  QwtPainter::fillRect(p, shadow_right, QBrush(Qt::black));
219  QwtPainter::fillRect(p, shadow_bottom, QBrush(Qt::black));
220  }
221  p->restore();
222 }
223 
224 void Legend::drawVector(QPainter *p, int x, int y, int l, int curveIndex) const
225 {
226  Graph *g = (Graph *)d_plot->parent();
227  if (!g)
228  return;
229 
230  VectorCurve *v = (VectorCurve*)g->curve(curveIndex);
231  if (!v)
232  return;
233 
234  p->save();
235 
236  QPen pen(v->color(), v->width(), Qt::SolidLine);
237  p->setPen(pen);
238  QwtPainter::drawLine(p, x, y, x + l, y);
239 
240  p->translate(x+l, y);
241 
242  double pi=4*atan(-1.0);
243  int headLength = v->headLength();
244  int d=qRound(headLength*tan(pi*(double)v->headAngle()/180.0));
245 
246  QPolygon endArray(3);
247  endArray[0] = QPoint(0, 0);
248  endArray[1] = QPoint(-headLength, d);
249  endArray[2] = QPoint(-headLength, -d);
250 
251  if (v->filledArrowHead())
252  p->setBrush(QBrush(pen.color(), Qt::SolidPattern));
253 
254  QwtPainter::drawPolygon(p,endArray);
255  p->restore();
256 }
257 
258 void Legend::drawSymbols(QPainter *p, const QRect& rect,
259  QwtArray<long> height, int symbolLineLength) const
260 {
261  Graph *g = (Graph *) d_plot->parent();
262 
263  int w = rect.x() + left_margin;
264  int l = symbolLineLength + 2*left_margin;
265 
266  QString text = d_text->text().trimmed();
267  QStringList titles = text.split("\n", QString::KeepEmptyParts);
268 
269  for (int i=0;i<(int)titles.count();i++)
270  {
271  if (titles[i].contains("\\c{") || titles[i].contains("\\l("))
272  {
273  QString aux;
274  if (titles[i].contains("\\c{"))
275  {//SciDAVis symbol specification
276  int pos=titles[i].indexOf("{",0);
277  int pos2=titles[i].indexOf("}",pos);
278  aux=titles[i].mid(pos+1,pos2-pos-1);
279  }
280  else if (titles[i].contains("\\l("))
281  {//Origin project legend
282  int pos=titles[i].indexOf("(",0);
283  int pos2=titles[i].indexOf(")",pos);
284  aux=titles[i].mid(pos+1,pos2-pos-1);
285  }
286 
287  int cv = aux.toInt() - 1;
288  if (cv < 0)
289  continue;
290 
291  if (g->curveType(cv) == Graph :: VectXYXY || g->curveType(cv) == Graph :: VectXYAM)
292  drawVector(p, w, height[i], l, cv);
293  else
294  {
295  const QwtPlotCurve *curve = g->curve(cv);
296  if (curve && curve->rtti() != QwtPlotItem::Rtti_PlotSpectrogram)
297  {
298  QwtSymbol symb=curve->symbol();
299  const QBrush br=curve->brush();
300  QPen pen=curve->pen();
301 
302  p->save();
303 
304  if (curve->style()!=0)
305  {
306  p->setPen (pen);
307  if (br.style() != Qt::NoBrush || g->curveType(cv) == Graph::Box)
308  {
309  QRect lr=QRect(w,height[i]-4,l,10);
310  p->setBrush(br);
311  QwtPainter::drawRect(p, lr);
312  }
313  else
314  QwtPainter::drawLine(p, w,height[i],w+l,height[i]);
315  }
316  int symb_size = symb.size().width();
317  if (symb_size > 15)
318  symb_size = 15;
319  else if (symb_size < 3)
320  symb_size = 3;
321  symb.setSize(symb_size);
322  symb.draw(p,w+l/2,height[i]);
323  p->restore();
324  }
325  }
326  }
327  else if (titles[i].contains("\\p{"))
328  {
329  int pos=titles[i].indexOf("{",0);
330  int pos2=titles[i].indexOf("}",pos);
331  QString aux=titles[i].mid(pos+1,pos2-pos-1);
332 
333  int id=aux.toInt();
334 
335  Graph* g=(Graph*)d_plot->parent();
336  if (g->isPiePlot())
337  {
338  QwtPieCurve *curve = (QwtPieCurve *)d_plot->curve(1);
339  if (curve)
340  {
341  const QBrush br=QBrush(curve->color(id-1), curve->pattern());
342  QPen pen=curve->pen();
343 
344  p->save();
345  p->setPen (QPen(pen.color(),1,Qt::SolidLine));
346  QRect lr=QRect(w,height[i]-4,l,10);
347  p->setBrush(br);
348  QwtPainter::drawRect(p, lr);
349  p->restore();
350  }
351  }
352  }
353  }
354 }
355 
356 void Legend::drawLegends(QPainter *p, const QRect& rect,
357  QwtArray<long> height, int symbolLineLength) const
358 {
359  int w = rect.x() + left_margin;
360 
361  QString text = d_text->text().trimmed();
362  QStringList titles=text.split("\n", QString::KeepEmptyParts);
363 
364  for (int i=0; i<(int)titles.count(); i++)
365  {
366  QString str = titles[i];
367  int x = w;
368  if (str.contains("\\c{") || str.contains("\\p{") || str.contains("\\l("))
369  x += symbolLineLength + hspace;
370 
371  QwtText aux(parse(str));
372  aux.setFont(d_text->font());
373  aux.setColor(d_text->color());
374 
375  QSize size = aux.textSize();
376  // bug in Qwt; workaround in QwtText::textSize() only works for short texts.
377  // Thus, we work around the workaround.
378  const QwtMetricsMap map = QwtPainter::metricsMap();
379  if (!map.isIdentity()) {
380  int screen_width = map.layoutToScreenX(size.width());
381  screen_width -= 3;
382  screen_width *= 1.1;
383  size = QSize(map.screenToLayoutX(screen_width), size.height());
384  }
385 
386  QRect tr = QRect(QPoint(x, height[i] - size.height()/2), size);
387  aux.draw(p, tr);
388  }
389 }
390 
391 QwtArray<long> Legend::itemsHeight(int y, int symbolLineLength, int &width, int &height) const
392 {
393  int maxL=0;
394 
395  width = 0;
396  height = 0;
397 
398  QString text = d_text->text().trimmed();
399  QStringList titles = text.split("\n", QString::KeepEmptyParts);
400  int n=(int)titles.count();
401  QwtArray<long> heights(n);
402 
403  int h = top_margin;
404 
405  for (int i=0; i<n; i++)
406  {
407  QString str=titles[i];
408  int textL=0;
409  if (str.contains("\\c{") || str.contains("\\p{") || str.contains("\\l("))
410  textL = symbolLineLength + hspace;
411 
412  QwtText aux(parse(str));
413  QSize size = aux.textSize(d_text->font());
414  // bug in Qwt; workaround in QwtText::textSize() only works for short texts.
415  // Thus, we work around the workaround.
416  const QwtMetricsMap map = QwtPainter::metricsMap();
417  if (!map.isIdentity()) {
418  int screen_width = map.layoutToScreenX(size.width());
419  screen_width -= 3;
420  screen_width *= 1.1;
421  size = QSize(map.screenToLayoutX(screen_width), size.height());
422  }
423  textL += size.width();
424  if (textL > maxL)
425  maxL = textL;
426 
427  int textH = size.height();
428  height += textH;
429 
430  heights[i] = y + h + textH/2;
431  h += textH;
432  }
433 
434  height += 2*top_margin;
435  width = 2*left_margin + maxL;
436 
437  return heights;
438 }
439 
441 {
442  QList<int> cvs = d_plot->curveKeys();
443 
444  int maxL=0;
445  QString text = d_text->text().trimmed();
446  QStringList titles = text.split("\n", QString::KeepEmptyParts);
447  for (int i=0;i<(int)titles.count();i++){
448  if (titles[i].contains("\\c{") && (int)cvs.size()>0){
449  QString aux;
450  if (titles[i].contains("\\c{")){//SciDAVis symbol specification
451  int pos=titles[i].indexOf("{", 0);
452  int pos2=titles[i].indexOf("}", pos);
453  aux=titles[i].mid(pos+1, pos2-pos-1);
454  } else if (titles[i].contains("\\l(")){//Origin project legend
455  int pos=titles[i].indexOf("(", 0);
456  int pos2=titles[i].indexOf(")", pos);
457  aux=titles[i].mid(pos+1, pos2-pos-1);
458  }
459 
460  int cv = aux.toInt()-1;
461  if (cv < 0 || cv >= cvs.count())
462  continue;
463 
464  const QwtPlotCurve *c = (QwtPlotCurve *)d_plot->curve(cvs[cv]);
465  if (c && c->rtti() != QwtPlotItem::Rtti_PlotSpectrogram) {
466  int l=c->symbol().size().width();
467  if (l < 3)
468  l = 3;
469  else if (l > 15)
470  l = 15;
471  if (l>maxL && c->symbol().style() != QwtSymbol::NoSymbol)
472  maxL=l;
473  }
474  }
475 
476  if (titles[i].contains("\\p{"))
477  maxL=10;
478  }
479  return maxL;
480 }
481 
482 QString Legend::parse(const QString& str) const
483 {
484  QString s = str;
485  if (s.contains("\\c{") || s.contains("\\p{") || s.contains("\\l(")){
486  int pos = s.indexOf("}",0);
487  if (s.contains("\\l("))
488  pos = s.indexOf(")",0);
489  s = s.right(s.length()-pos-1);
490  }
491 
492  if (s.contains("%(")){//curve name specification
493  int pos = s.indexOf("%(",0);
494  int pos2 = s.indexOf(")",pos);
495  int cv = s.mid(pos+2, pos2-pos-2).toInt() - 1;
496  if (cv >= 0){
497  Graph *g = (Graph *)d_plot->parent();
498  if (g){
499  const QwtPlotCurve *c = (QwtPlotCurve *)g->curve(cv);
500  if (c)
501  s = s.replace(pos, pos2-pos+1, c->title().text());
502  }
503  }
504  }
505  return s;
506 }
507 
509 {
510  delete d_text;
511 }
Legend::drawFrame
void drawFrame(QPainter *p, int type, const QRect &rect) const
Definition: Legend.cpp:197
QwtPieCurve::color
QColor color(int i) const
Definition: QwtPieCurve.cpp:98
Plot::curveKeys
QList< int > curveKeys()
Definition: Plot.h:55
PlotEnrichement::size
QSize size()
Return d_size.
Definition: PlotEnrichement.h:86
Legend::Line
@ Line
Definition: Legend.h:62
Legend::d_pos
QPoint d_pos
TopLeft position in pixels.
Definition: Legend.h:123
Legend::text
QString text()
Definition: Legend.h:64
Legend::~Legend
~Legend()
Definition: Legend.cpp:508
str
#define str(x)
Definition: PythonScripting.cpp:41
Legend::d_shadow_size_y
int d_shadow_size_y
Definition: Legend.h:131
Legend::parse
QString parse(const QString &str) const
Definition: Legend.cpp:482
Legend::symbolsMaxLineLength
int symbolsMaxLineLength() const
Definition: Legend.cpp:440
Legend::d_text
QwtText * d_text
Pointer to the QwtText object.
Definition: Legend.h:120
Plot::curve
QwtPlotCurve * curve(int index)
Definition: Plot.cpp:418
QwtPieCurve::pattern
Qt::BrushStyle pattern()
Definition: QwtPieCurve.h:44
Graph::VectXYAM
@ VectXYAM
Definition: Graph.h:131
Legend::hspace
int hspace
Distance between symbols and legend text.
Definition: Legend.h:126
QwtPieCurve.h
Legend::left_margin
int left_margin
Distance between frame and content.
Definition: Legend.h:129
VectorCurve::headAngle
int headAngle()
Definition: VectorCurve.h:76
Legend::drawLegends
void drawLegends(QPainter *p, const QRect &rect, QwtArray< long > height, int symbolLineLength) const
Definition: Legend.cpp:356
PlotEnrichement::bottom
double bottom()
Definition: PlotEnrichement.h:78
Legend::setOriginCoord
void setOriginCoord(double x, double y)
Sets the position of the top left corner in axis coordinates.
Definition: Legend.cpp:175
Graph::VectXYXY
@ VectXYXY
Definition: Graph.h:130
Legend::Shadow
@ Shadow
Definition: Legend.h:62
Legend::updateOrigin
void updateOrigin()
Keep the markers on screen each time the scales are modified by adding/removing curves.
Definition: Legend.cpp:153
Legend::top_margin
int top_margin
Definition: Legend.h:129
Legend::setTextColor
void setTextColor(const QColor &c)
Definition: Legend.cpp:134
VectorCurve::headLength
int headLength()
Definition: VectorCurve.h:73
Legend::setFont
void setFont(const QFont &font)
Definition: Legend.cpp:189
Legend::setFrameStyle
void setFrameStyle(int style)
Definition: Legend.cpp:90
PlotEnrichement::right
double right()
Definition: PlotEnrichement.h:77
Legend::draw
void draw(QPainter *p, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRect &r) const
Definition: Legend.cpp:65
VectorCurve::color
QColor color()
Definition: VectorCurve.cpp:211
VectorCurve.h
Plot
Plot window class.
Definition: Plot.h:44
Legend.h
Legend::setText
void setText(const QString &s)
Definition: Legend.cpp:85
Legend::font
QFont font()
Definition: Legend.h:89
Legend::boundingRect
virtual QwtDoubleRect boundingRect() const
Bounding rectangle in plot coordinates.
Definition: Legend.cpp:120
Graph::curveType
int curveType(int curveIndex)
Definition: Graph.cpp:4355
Legend::rect
QRect rect() const
Bounding rectangle in paint coordinates.
Definition: Legend.cpp:106
Legend::d_frame
int d_frame
Frame type.
Definition: Legend.h:114
Legend::d_shadow_size_x
int d_shadow_size_x
Definition: Legend.h:131
Legend::setOrigin
void setOrigin(const QPoint &p)
Definition: Legend.cpp:142
Legend::setBackgroundColor
void setBackgroundColor(const QColor &c)
Definition: Legend.cpp:98
VectorCurve::filledArrowHead
bool filledArrowHead()
Definition: VectorCurve.h:79
VectorCurve
Vector curve class.
Definition: VectorCurve.h:39
Graph
A 2D-plotting widget.
Definition: Graph.h:119
Legend::Legend
Legend(Plot *)
Definition: Legend.cpp:45
Graph::Box
@ Box
Definition: Graph.h:131
Graph::isPiePlot
bool isPiePlot() const
Returns true if this Graph is a pie plot, false otherwise.
Definition: Graph.h:161
Legend::itemsHeight
QwtArray< long > itemsHeight(int y, int symbolLineLength, int &width, int &height) const
Definition: Legend.cpp:391
Legend::drawVector
void drawVector(QPainter *p, int x, int y, int l, int curveIndex) const
Definition: Legend.cpp:224
Legend::drawSymbols
void drawSymbols(QPainter *p, const QRect &rect, QwtArray< long > height, int symbolLineLength) const
Definition: Legend.cpp:258
QwtPieCurve
Pie plot class.
Definition: QwtPieCurve.h:34
Legend::None
@ None
Definition: Legend.h:62
Graph::curve
QwtPlotCurve * curve(int index) const
get curve by index
Definition: Graph.cpp:2821
VectorCurve::width
int width()
Definition: VectorCurve.cpp:201
Legend::d_plot
Plot * d_plot
Parent plot.
Definition: Legend.h:111