1 /***************************************************************************
2 	File                 : Spectrogram.cpp
3 	Project              : QtiPlot
4 --------------------------------------------------------------------
5 	Copyright            : (C) 2006 by Ion Vasilief
6 	Email (use @ for *)  : ion_vasilief*yahoo.fr
7 	Description          : QtiPlot's Spectrogram Class
8  ***************************************************************************/
9 
10 /***************************************************************************
11  *                                                                         *
12  *  This program is free software; you can redistribute it and/or modify   *
13  *  it under the terms of the GNU General Public License as published by   *
14  *  the Free Software Foundation; either version 2 of the License, or      *
15  *  (at your option) any later version.                                    *
16  *                                                                         *
17  *  This program is distributed in the hope that it will be useful,        *
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
20  *  GNU General Public License for more details.                           *
21  *                                                                         *
22  *   You should have received a copy of the GNU General Public License     *
23  *   along with this program; if not, write to the Free Software           *
24  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
25  *   Boston, MA  02110-1301  USA                                           *
26  *                                                                         *
27  ***************************************************************************/
28 #include <Spectrogram.h>
29 #include <Graph.h>
30 #include <MultiLayer.h>
31 #include <ApplicationWindow.h>
32 #include <PlotCurve.h>
33 #include <PenStyleBox.h>
34 
35 #include <math.h>
36 #include <QPen>
37 #include <QPainter>
38 #include <qwt_scale_widget.h>
39 #include <qwt_painter.h>
40 
Spectrogram(Graph * graph,Matrix * m)41 Spectrogram::Spectrogram(Graph *graph, Matrix *m):
42 	QwtPlotSpectrogram(QString(m->objectName())),
43 	d_graph(graph),
44 	d_matrix(m),
45 	color_axis(QwtPlot::yRight),
46 	color_map_policy(Default),
47 	color_map(LinearColorMap()),
48 	d_show_labels(true),
49 	d_labels_color(Qt::black),
50 	d_labels_font(QFont()),
51 	d_white_out_labels(false),
52 	d_labels_angle(0.0),
53 	d_labels_x_offset(0),
54 	d_labels_y_offset(0),
55 	d_selected_label(NULL),
56 	d_use_matrix_formula(false),
57 	d_color_map_pen(false)
58 {
59 	setData(MatrixData(m));
60 
61 	double step = fabs(data().range().maxValue() - data().range().minValue())/5.0;
62 
63 	QwtValueList contourLevels;
64 	for ( double level = data().range().minValue() + step;
65 		level < data().range().maxValue(); level += step )
66 		contourLevels += level;
67 
68 	setContourLevels(contourLevels);
69 }
70 
updateData()71 void Spectrogram::updateData()
72 {
73 	if (!d_matrix || !d_graph)
74 		return;
75 
76 	setData(MatrixData(d_matrix, d_use_matrix_formula));
77 
78 	QwtScaleWidget *colorAxis = d_graph->axisWidget(color_axis);
79 	if (colorAxis)
80 		colorAxis->setColorMap(range(), colorMap());
81 
82 	d_graph->setAxisScale(color_axis, range().minValue(), range().maxValue());
83 	d_graph->replot();
84 }
85 
range() const86 QwtDoubleInterval Spectrogram::range() const
87 {
88 	if (color_map.intensityRange().isValid())
89 		return color_map.intensityRange();
90 
91 	double mmin, mmax;
92 	d_matrix->range(&mmin, &mmax);
93 	return QwtDoubleInterval(mmin, mmax);
94 }
95 
setMatrix(Matrix * m,bool useFormula)96 bool Spectrogram::setMatrix(Matrix *m, bool useFormula)
97 {
98 	if (!m)
99 		return false;
100 
101 	if (m == d_matrix && useFormula == d_use_matrix_formula)
102 		return true;
103 
104 	bool changedUseFormula = (useFormula != d_use_matrix_formula) ? true : false;
105 	bool canCalculate = false;
106 	if (useFormula){
107 		canCalculate = m->canCalculate();
108 		if (!canCalculate){
109 			QMessageBox::warning(d_graph->multiLayer(), QObject::tr("QtiPlot - Script Error"),
110 			QObject::tr("Python-like syntax is not supported in this case since it severely reduces drawing speed!"));
111 			changedUseFormula = false;
112 			d_use_matrix_formula = false;
113 		}
114 	}
115 
116 	if (changedUseFormula)
117 		d_use_matrix_formula = useFormula;
118 
119 	bool changedMatrix = (d_matrix != m) ? true : false;
120 	if (changedMatrix)
121 		d_matrix = m;
122 
123 	if (changedMatrix || changedUseFormula)
124 		updateData();
125 
126 	if (!canCalculate)
127 		return false;
128 	return true;
129 }
130 
setLevelsNumber(int levels)131 void Spectrogram::setLevelsNumber(int levels)
132 {
133 	if (levels <= 0)
134 		return;
135 
136 	double step = fabs(range().maxValue() - range().minValue())/(double)levels;
137 
138 	QwtValueList contourLevels;
139 	for ( double level = range().minValue() + 0.5*step;
140 		level < range().maxValue(); level += step )
141 		contourLevels += level;
142 
143 	setContourLevels(contourLevels);
144 }
145 
setContourLevels(const QwtValueList & levels)146 void Spectrogram::setContourLevels (const QwtValueList & levels)
147 {
148 	QwtPlotSpectrogram::setContourLevels(levels);
149 	createLabels();
150 }
151 
hasColorScale()152 bool Spectrogram::hasColorScale()
153 {
154 	if (!d_graph)
155 		return false;
156 
157 	if (!d_graph->axisEnabled (color_axis))
158 		return false;
159 
160 	QwtScaleWidget *colorAxis = d_graph->axisWidget(color_axis);
161 	if (colorAxis)
162 		return colorAxis->isColorBarEnabled();
163 
164 	return false;
165 }
166 
showColorScale(int axis,bool on)167 void Spectrogram::showColorScale(int axis, bool on)
168 {
169 if (hasColorScale() == on && color_axis == axis)
170 	return;
171 
172 if (!d_graph)
173 	return;
174 
175 QwtScaleWidget *colorAxis = d_graph->axisWidget(color_axis);
176 colorAxis->setColorBarEnabled(false);
177 
178 color_axis = axis;
179 
180 // We must switch main and the color scale axes and their respective scales
181 	int xAxis = this->xAxis();
182 	int yAxis = this->yAxis();
183 	int oldMainAxis = QwtPlot::xBottom;
184 	if (axis == QwtPlot::xBottom || axis == QwtPlot::xTop){
185 		oldMainAxis = xAxis;
186 		xAxis = 5 - color_axis;
187 	} else if (axis == QwtPlot::yLeft || axis == QwtPlot::yRight){
188 		oldMainAxis = yAxis;
189 		yAxis = 1 - color_axis;
190 	}
191 
192 // First we switch axes
193 setAxis(xAxis, yAxis);
194 
195 // Next we switch axes scales
196 QwtScaleDiv *scDiv = d_graph->axisScaleDiv(oldMainAxis);
197 if (axis == QwtPlot::xBottom || axis == QwtPlot::xTop)
198 	d_graph->setAxisScale(xAxis, scDiv->lowerBound(), scDiv->upperBound());
199 else if (axis == QwtPlot::yLeft || color_axis == QwtPlot::yRight)
200 	d_graph->setAxisScale(yAxis, scDiv->lowerBound(), scDiv->upperBound());
201 
202 colorAxis = d_graph->axisWidget(color_axis);
203 d_graph->setAxisScale(color_axis, range().minValue(), range().maxValue());
204 colorAxis->setColorBarEnabled(on);
205 colorAxis->setColorMap(range(), colorMap());
206 if (!d_graph->axisEnabled(color_axis))
207 	d_graph->enableAxis(color_axis);
208 colorAxis->show();
209 d_graph->updateLayout();
210 }
211 
colorBarWidth()212 int Spectrogram::colorBarWidth()
213 {
214 	if (!d_graph)
215 		return 0;
216 
217 	QwtScaleWidget *colorAxis = d_graph->axisWidget(color_axis);
218 	return colorAxis->colorBarWidth();
219 }
220 
setColorBarWidth(int width)221 void Spectrogram::setColorBarWidth(int width)
222 {
223 	if (!d_graph)
224 		return;
225 
226 	QwtScaleWidget *colorAxis = d_graph->axisWidget(color_axis);
227 	colorAxis->setColorBarWidth(width);
228 }
229 
copy(Graph * g)230 Spectrogram* Spectrogram::copy(Graph *g)
231 {
232 	Spectrogram *new_s = new Spectrogram(g, matrix());
233 	new_s->setDisplayMode(QwtPlotSpectrogram::ImageMode, testDisplayMode(QwtPlotSpectrogram::ImageMode));
234 	new_s->setDisplayMode(QwtPlotSpectrogram::ContourMode, testDisplayMode(QwtPlotSpectrogram::ContourMode));
235 	new_s->setCustomColorMap(color_map);
236 	new_s->setAxis(xAxis(), yAxis());
237 	new_s->setDefaultContourPen(defaultContourPen());
238 	new_s->color_map_policy = color_map_policy;
239 	new_s->d_show_labels = d_show_labels;
240 	new_s->d_labels_angle = d_labels_angle;
241 	new_s->d_labels_color = d_labels_color;
242 	new_s->d_white_out_labels = d_white_out_labels;
243 	new_s->d_labels_font = d_labels_font;
244 	new_s->d_labels_x_offset = d_labels_x_offset;
245 	new_s->d_labels_y_offset = d_labels_y_offset;
246 	new_s->setContourLevels(contourLevels());
247 
248 	if (defaultContourPen().style() == Qt::NoPen && !d_color_map_pen)
249 		new_s->setContourPenList(d_pen_list);
250 	else
251 		new_s->d_color_map_pen = d_color_map_pen;
252 
253 	if (d_labels_list.isEmpty()){
254 		new_s->clearLabels();
255 		return new_s;
256 	}
257 
258 	QList <PlotMarker *> lst = new_s->labelsList();
259 	int count = lst.size();
260 	for(int i = 0; i < count; i++){
261 		PlotMarker *m = lst[i];
262 		PlotMarker *mrk = d_labels_list[i];
263 		if (m && mrk)
264 			m->setLabelOffset(mrk->xLabelOffset(), mrk->yLabelOffset());
265 	}
266 
267 	return new_s;
268 }
269 
setGrayScale()270 void Spectrogram::setGrayScale()
271 {
272 	color_map = LinearColorMap(Qt::black, Qt::white);
273 	setColorMap(color_map);
274 	color_map_policy = GrayScale;
275 
276 	if (!d_graph)
277 		return;
278 
279 	QwtScaleWidget *colorAxis = d_graph->axisWidget(color_axis);
280 	if (colorAxis)
281 		colorAxis->setColorMap(range(), colorMap());
282 }
283 
setDefaultColorMap()284 void Spectrogram::setDefaultColorMap()
285 {
286 	if (!d_graph)
287 		return;
288 
289 	color_map = d_graph->multiLayer()->applicationWindow()->d_3D_color_map;
290 	setColorMap(color_map);
291 	color_map_policy = Default;
292 
293 	QwtScaleWidget *colorAxis = d_graph->axisWidget(color_axis);
294 	if (colorAxis)
295 		colorAxis->setColorMap(range(), colorMap());
296 }
297 
setCustomColorMap(const LinearColorMap & map)298 void Spectrogram::setCustomColorMap(const LinearColorMap& map)
299 {
300 	setColorMap(map);
301 	color_map = map;
302 	color_map_policy = Custom;
303 
304 	if (!d_graph)
305 		return;
306 
307 	QwtScaleWidget *colorAxis = d_graph->axisWidget(color_axis);
308 	if (colorAxis)
309 		colorAxis->setColorMap(range(), colorMap());
310 }
311 
saveToString()312 QString Spectrogram::saveToString()
313 {
314 QString s = "<spectrogram>\n";
315 s += "\t<matrix>" + QString(d_matrix->objectName()) + "</matrix>\n";
316 s += "\t<useMatrixFormula>" + QString::number(d_use_matrix_formula) + "</useMatrixFormula>\n";
317 s += "\t<xAxis>" + QString::number(xAxis()) + "</xAxis>\n";
318 s += "\t<yAxis>" + QString::number(yAxis()) + "</yAxis>\n";
319 
320 if (color_map_policy != Custom)
321 	s += "\t<ColorPolicy>" + QString::number(color_map_policy) + "</ColorPolicy>\n";
322 else
323 	s += color_map.toXmlString();
324 s += "\t<Image>"+QString::number(testDisplayMode(QwtPlotSpectrogram::ImageMode))+"</Image>\n";
325 
326 bool contourLines = testDisplayMode(QwtPlotSpectrogram::ContourMode);
327 s += "\t<ContourLines>"+QString::number(contourLines)+"</ContourLines>\n";
328 if (contourLines){
329 	QwtValueList levels = contourLevels();
330 	s += "\t\t<Levels>" + QString::number(levels.size()) + "</Levels>\n";
331 	for (int i = 0; i < levels.size(); i++)
332 		s += "\t\t<z>" + QString::number(levels[i]) + "</z>\n";
333 
334 	bool defaultPen = defaultContourPen().style() != Qt::NoPen;
335 	s += "\t\t<DefaultPen>" + QString::number(defaultPen) + "</DefaultPen>\n";
336 	if (defaultPen){
337 		s += "\t\t\t<PenColor>" + defaultContourPen().color().name() + "</PenColor>\n";
338 		s += "\t\t\t<PenWidth>" + QString::number(defaultContourPen().widthF()) + "</PenWidth>\n";
339 		s += "\t\t\t<PenStyle>" + QString::number(defaultContourPen().style() - 1) + "</PenStyle>\n";
340 	} else if (!d_color_map_pen && !d_pen_list.isEmpty()){
341 		s += "\t\t<PenList>\n";
342 		for (int i = 0; i < d_pen_list.size(); i++){
343 			QPen pen = d_pen_list[i];
344 			s += "\t\t\t<pen>" + pen.color().name () + "," + QString::number(pen.widthF()) + ",";
345 			s += QString::number(PenStyleBox::styleIndex(pen.style())) + "</pen>\n";
346 		}
347 		s += "\t\t</PenList>\n";
348 	}
349 
350 	if (d_show_labels){
351 		s += "\t\t<Labels>\n";
352 		s += "\t\t\t<Color>" + d_labels_color.name() + "</Color>\n";
353 		s += "\t\t\t<WhiteOut>" + QString::number(d_white_out_labels) +"</WhiteOut>\n";
354 		s += "\t\t\t<Angle>" + QString::number(d_labels_angle) + "</Angle>\n";
355 		s += "\t\t\t<xOffset>" + QString::number(d_labels_x_offset) + "</xOffset>\n";
356 		s += "\t\t\t<yOffset>" + QString::number(d_labels_y_offset) + "</yOffset>\n";
357 		s += "\t\t\t<Font>" + d_labels_font.toString() + "</Font>\n";
358 		foreach(PlotMarker *m, d_labels_list){
359 			if (m->xLabelOffset() != 0.0 || m->xLabelOffset() != 0.0){
360 				s += "\t\t\t<offset>" + QString::number(m->index()) + ",";
361 				s += QString::number(m->xLabelOffset()) + ",";
362 				s += QString::number(m->yLabelOffset()) + "</offset>\n";
363 			}
364 		}
365 		s += "\t\t</Labels>\n";
366 	}
367 }
368 
369 QwtScaleWidget *colorAxis = d_graph->axisWidget(color_axis);
370 if (colorAxis && colorAxis->isColorBarEnabled()){
371 	s += "\t<ColorBar>\n\t\t<axis>" + QString::number(color_axis) + "</axis>\n";
372 	s += "\t\t<width>" + QString::number(colorAxis->colorBarWidth()) + "</width>\n";
373 	s += "\t</ColorBar>\n";
374 	}
375 s += "\t<Visible>"+ QString::number(isVisible()) + "</Visible>\n";
376 return s+"</spectrogram>\n";
377 }
378 
boundingRect() const379 QwtDoubleRect Spectrogram::boundingRect() const
380 {
381 	return d_matrix->boundingRect();
382 }
383 
createLabels()384 void Spectrogram::createLabels()
385 {
386 	clearLabels();
387 
388 	QwtValueList levels = contourLevels();
389 	const int numLevels = levels.size();
390     for (int l = 0; l < numLevels; l++){
391 		PlotMarker *m = new PlotMarker(l, d_labels_angle);
392 
393 		QwtText t = QwtText(QString::number(levels[l]));
394 		t.setColor(d_labels_color);
395 		t.setFont(d_labels_font);
396 
397 		if (d_white_out_labels)
398 			t.setBackgroundBrush(QBrush(Qt::white));
399         else
400             t.setBackgroundBrush(QBrush(Qt::transparent));
401 		m->setLabel(t);
402 
403         int x_axis = xAxis();
404         int y_axis = yAxis();
405 		m->setAxis(x_axis, y_axis);
406 
407         if (d_graph && d_show_labels)
408 			m->attach(d_graph);
409 		d_labels_list << m;
410 	}
411 }
412 
showContourLineLabels(bool show)413 void Spectrogram::showContourLineLabels(bool show)
414 {
415 	if (show == d_show_labels)
416         return;
417 
418     d_show_labels = show;
419 
420     foreach(PlotMarker *m, d_labels_list){
421     	if (d_show_labels)
422 			m->attach(d_graph);
423 		else
424 			m->detach();
425 	}
426 }
427 
drawContourLines(QPainter * p,const QwtScaleMap & xMap,const QwtScaleMap & yMap,const QwtRasterData::ContourLines & contourLines) const428 void Spectrogram::drawContourLines (QPainter *p, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QwtRasterData::ContourLines &contourLines) const
429 {
430 	QwtValueList levels = contourLevels();
431     const int numLevels = (int)levels.size();
432     for (int l = 0; l < numLevels; l++){
433         const double level = levels[l];
434 
435         QPen pen = defaultContourPen();
436         if ( pen.style() == Qt::NoPen )
437             pen = contourPen(level);
438 
439         if ( pen.style() == Qt::NoPen )
440             continue;
441 
442         p->setPen(QwtPainter::scaledPen(pen));
443 
444         const QPolygonF &lines = contourLines[level];
445         for ( int i = 0; i < (int)lines.size(); i += 2 ){
446             const QPointF p1( xMap.xTransform(lines[i].x()),
447                 yMap.transform(lines[i].y()) );
448             const QPointF p2( xMap.xTransform(lines[i + 1].x()),
449                 yMap.transform(lines[i + 1].y()) );
450 
451             p->drawLine(p1, p2);
452         }
453     }
454 
455 	if (d_show_labels)
456 		updateLabels(p, xMap, yMap, contourLines);
457 }
458 
updateLabels(QPainter * p,const QwtScaleMap &,const QwtScaleMap &,const QwtRasterData::ContourLines & contourLines) const459 void Spectrogram::updateLabels(QPainter *p, const QwtScaleMap &, const QwtScaleMap &,
460 		const QwtRasterData::ContourLines &contourLines) const
461 {
462 	QwtValueList levels = contourLevels();
463 	const int numLevels = levels.size();
464 	int x_axis = xAxis();
465 	int y_axis = yAxis();
466 	for (int l = 0; l < numLevels; l++){
467 		const double level = levels[l];
468 		const QPolygonF &lines = contourLines[level];
469 		if (lines.isEmpty())
470 			continue;
471 
472 		PlotMarker *mrk = d_labels_list[l];
473 		if (!mrk)
474 			return;
475 
476 		QSize size = mrk->label().textSize();
477 		int dx = int((d_labels_x_offset + mrk->xLabelOffset())*0.01*size.height());
478 		int dy = -int(((d_labels_y_offset + mrk->yLabelOffset())*0.01 + 0.5)*size.height());
479 
480 		int i = (int)lines.size()/2;
481 		double x = lines[i].x();
482 		double y = lines[i].y();
483 
484 		int x2 = d_graph->transform(x_axis, x) + dx;
485 		int y2 = d_graph->transform(y_axis, y) + dy;
486 
487 		if (p->device()->logicalDpiX() == plot()->logicalDpiX() ||
488 			p->device()->logicalDpiY() == plot()->logicalDpiY())
489 			mrk->setValue(d_graph->invTransform(x_axis, x2),
490 							d_graph->invTransform(y_axis, y2));
491 	}
492 }
493 
setLabelsFont(const QFont & font)494 void Spectrogram::setLabelsFont(const QFont& font)
495 {
496 	if (font == d_labels_font)
497         return;
498 
499     d_labels_font = font;
500 
501     foreach(QwtPlotMarker *m, d_labels_list){
502 		QwtText t = m->label();
503 		t.setFont(font);
504 		m->setLabel(t);
505 	}
506 }
507 
setLabelsColor(const QColor & c)508 void Spectrogram::setLabelsColor(const QColor& c)
509 {
510     if (c == d_labels_color)
511         return;
512 
513     d_labels_color = c;
514 
515     foreach(QwtPlotMarker *m, d_labels_list){
516 		QwtText t = m->label();
517 		t.setColor(c);
518 		m->setLabel(t);
519 	}
520 }
521 
setLabelsWhiteOut(bool whiteOut)522 void Spectrogram::setLabelsWhiteOut(bool whiteOut)
523 {
524     if (whiteOut == d_white_out_labels)
525         return;
526 
527     d_white_out_labels = whiteOut;
528 
529     foreach(QwtPlotMarker *m, d_labels_list){
530 		QwtText t = m->label();
531 		if (whiteOut)
532 			t.setBackgroundBrush(QBrush(Qt::white));
533         else
534             t.setBackgroundBrush(QBrush(Qt::transparent));
535 		m->setLabel(t);
536 	}
537 }
538 
setLabelsOffset(double x,double y)539 void Spectrogram::setLabelsOffset(double x, double y)
540 {
541     if (x == d_labels_x_offset && y == d_labels_y_offset)
542         return;
543 
544     d_labels_x_offset = x;
545     d_labels_y_offset = y;
546 }
547 
setLabelOffset(int index,double x,double y)548 void Spectrogram::setLabelOffset(int index, double x, double y)
549 {
550 	if (index < 0 || index >= d_labels_list.size())
551 		return;
552 
553 	PlotMarker *m = d_labels_list[index];
554 	if (!m)
555 		return;
556 
557 	m->setLabelOffset(x, y);
558 }
559 
setLabelsRotation(double angle)560 void Spectrogram::setLabelsRotation(double angle)
561 {
562     if (angle == d_labels_angle)
563         return;
564 
565     d_labels_angle = angle;
566 
567     foreach(PlotMarker *m, d_labels_list)
568 		m->setAngle(angle);
569 }
570 
selectedLabels(const QPoint & pos)571 bool Spectrogram::selectedLabels(const QPoint& pos)
572 {
573 	d_selected_label = NULL;
574 
575 	if (d_graph->hasActiveTool())
576 		return false;
577 
578     foreach(PlotMarker *m, d_labels_list){
579         int x = d_graph->transform(xAxis(), m->xValue());
580         int y = d_graph->transform(yAxis(), m->yValue());
581 
582         QMatrix wm;
583         wm.translate(x, y);
584 		wm.rotate(-d_labels_angle);
585         if (wm.mapToPolygon(QRect(QPoint(0, 0), m->label().textSize())).containsPoint(pos, Qt::OddEvenFill)){
586 			d_selected_label = m;
587 			d_click_pos_x = d_graph->invTransform(xAxis(), pos.x());
588 			d_click_pos_y = d_graph->invTransform(yAxis(), pos.y());
589             selectLabel(true);
590             return true;
591         }
592 	}
593 	return false;
594 }
595 
selectLabel(bool on)596 void Spectrogram::selectLabel(bool on)
597 {
598 	if (on){
599 		d_graph->deselect();
600 		d_graph->notifyFontChange(d_labels_font);
601 		d_graph->notifyColorChange(d_labels_color);
602 	}
603 
604 	foreach(PlotMarker *m, d_labels_list){
605 		QwtText t = m->label();
606 		if(t.text().isEmpty())
607 			return;
608 
609 		if (d_selected_label && m == d_selected_label && on)
610 			t.setBackgroundPen(QPen(Qt::blue));
611 		else
612 			t.setBackgroundPen(QPen(Qt::NoPen));
613 
614 		m->setLabel(t);
615 	}
616 
617 	d_graph->replot();
618 }
619 
hasSelectedLabels()620 bool Spectrogram::hasSelectedLabels()
621 {
622     /*if (d_labels_list.isEmpty())
623         return false;
624 
625     foreach(PlotMarker *m, d_labels_list){
626         if (m->label().backgroundPen() == QPen(Qt::blue))
627             return true;
628         else
629             return false;
630     }
631     return false;*/
632 
633     if (d_selected_label)
634 		return true;
635 	return false;
636 }
637 
moveLabel(const QPoint & pos)638 void Spectrogram::moveLabel(const QPoint& pos)
639 {
640 	if (!d_selected_label || d_labels_list.isEmpty())
641 		return;
642 
643     d_graph->replot();
644     int x_axis = xAxis();
645     int y_axis = yAxis();
646 
647     int d_x = pos.x() - d_graph->transform(x_axis, d_click_pos_x);
648 	int d_y = pos.y() - d_graph->transform(y_axis, d_click_pos_y);
649 
650 	int height = d_selected_label->label().textSize().height();
651 	double x_offset = d_selected_label->xLabelOffset() + d_x*100.0/(double)height;
652     double y_offset = d_selected_label->yLabelOffset() - d_y*100.0/(double)height;
653 
654 	d_selected_label->setLabelOffset(x_offset, y_offset);
655 
656 	d_graph->replot();
657     d_graph->notifyChanges();
658 
659 	d_click_pos_x = d_graph->invTransform(x_axis, pos.x());
660 	d_click_pos_y = d_graph->invTransform(y_axis, pos.y());
661 }
662 
clearLabels()663 void Spectrogram::clearLabels()
664 {
665 	foreach(PlotMarker *m, d_labels_list){
666 		m->detach();
667 		delete m;
668 	}
669 	d_labels_list.clear();
670 }
671 
setVisible(bool on)672 void Spectrogram::setVisible(bool on)
673 {
674 	QwtPlotItem::setVisible(on);
675 	foreach(PlotMarker *m, d_labels_list)
676 		m->setVisible(on);
677 }
678 
contourPen(double level) const679 QPen Spectrogram::contourPen (double level) const
680 {
681 	if (d_color_map_pen)
682 		return QwtPlotSpectrogram::contourPen(level);
683 
684 	QwtValueList levels = contourLevels();
685 	int index = levels.indexOf (level);
686 	if (index >= 0 && index < d_pen_list.size())
687 		return d_pen_list[index];
688 
689 	return QPen();
690 }
691 
setColorMapPen(bool on)692 void Spectrogram::setColorMapPen(bool on)
693 {
694 	d_color_map_pen = on;
695 	if (on) {
696 		setDefaultContourPen(Qt::NoPen);
697 		d_pen_list.clear();
698 	}
699 }
700 
setContourPenList(QList<QPen> lst)701 void Spectrogram::setContourPenList(QList<QPen> lst)
702 {
703 	d_pen_list = lst;
704 	setDefaultContourPen(Qt::NoPen);
705 	d_color_map_pen = false;
706 }
707 
setContourLinePen(int index,const QPen & pen)708 void Spectrogram::setContourLinePen(int index, const QPen &pen)
709 {
710 	QwtValueList levels = contourLevels();
711 	if (index < 0 || index >= levels.size())
712 		return;
713 
714 	if (d_pen_list.isEmpty()){
715 		QPen p = defaultContourPen();
716 		for (int i = 0; i < levels.size(); i++){
717 			if (p.style() == Qt::NoPen)
718 				d_pen_list << contourPen(levels[i]);
719 			else
720 				d_pen_list << p;
721 		}
722 	}
723 
724 	d_pen_list[index] = pen;
725 	setDefaultContourPen(Qt::NoPen);
726 	d_color_map_pen = false;
727 	d_graph->replot();
728 }
729 
setUseMatrixFormula(bool on)730 bool Spectrogram::setUseMatrixFormula(bool on)
731 {
732 	if (on && !d_matrix->canCalculate())
733 		return false;
734 
735 	d_use_matrix_formula = on;
736 	updateData();
737 	return true;
738 }
739 
renderImage(const QwtScaleMap & xMap,const QwtScaleMap & yMap,const QwtDoubleRect & area) const740 QImage Spectrogram::renderImage(const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QwtDoubleRect &area) const
741 {
742 	if (area.isEmpty())
743 		return QImage();
744 
745 	QRect rect = transform(xMap, yMap, area);
746 
747 	QwtScaleMap xxMap = xMap;
748 	QwtScaleMap yyMap = yMap;
749 
750 	MatrixData *d_data = (MatrixData *)data().copy();
751 	const QSize res = d_data->rasterHint(area);
752 	if (res.isValid()){
753 		rect.setSize(rect.size().boundedTo(res));
754 
755 		int px1 = rect.x();
756 		int px2 = rect.x() + rect.width();
757 		if ( xMap.p1() > xMap.p2() )
758 			qSwap(px1, px2);
759 
760 		double sx1 = area.x();
761 		double sx2 = area.x() + area.width();
762 		if ( xMap.s1() > xMap.s2() )
763 			qSwap(sx1, sx2);
764 
765 		int py1 = rect.y();
766 		int py2 = rect.y() + rect.height();
767 		if ( yMap.p1() > yMap.p2() )
768 			qSwap(py1, py2);
769 
770 		double sy1 = area.y();
771 		double sy2 = area.y() + area.height();
772 		if ( yMap.s1() > yMap.s2() )
773 			qSwap(sy1, sy2);
774 
775 		xxMap.setPaintInterval(px1, px2);
776 		xxMap.setScaleInterval(sx1, sx2);
777 		yyMap.setPaintInterval(py1, py2);
778 		yyMap.setScaleInterval(sy1, sy2);
779 	}
780 
781 	QImage image(rect.size(), QImage::Format_ARGB32);
782 
783 	const QwtDoubleInterval intensityRange = range();
784 	if(!intensityRange.isValid())
785 		return image;
786 
787 	d_data->initRaster(area, rect.size());
788 
789 	for (int y = rect.top(); y <= rect.bottom(); y++){
790 		const double ty = yyMap.invTransform(y);
791 		QRgb *line = (QRgb *)image.scanLine(y - rect.top());
792 		for (int x = rect.left(); x <= rect.right(); x++){
793 			const double tx = xxMap.invTransform(x);
794 			*line++ = color_map.rgb(intensityRange, d_data->value(tx, ty));
795 		}
796 	}
797 
798 	d_data->discardRaster();
799 
800 	// Mirror the image in case of inverted maps
801 	const bool hInvert = xxMap.p1() > xxMap.p2();
802 	const bool vInvert = yyMap.p1() < yyMap.p2();
803 	if (hInvert || vInvert)
804 		image = image.mirrored(hInvert, vInvert);
805 
806 	return image;
807 }
808 
value(double x,double y) const809 double MatrixData::value(double x, double y) const
810 {
811 	x += 0.5*dx;
812 	y -= 0.5*dy;
813 
814 	int i = qRound(fabs((y - y_start)/dy));
815 	int j = qRound(fabs((x - x_start)/dx));
816 
817 	if (d_mup){
818 		*d_y = y;
819 		*d_x = x;
820 		*d_ri = i;
821 		*d_rr = i;
822 		*d_cj = j;
823 		*d_cc = j;
824 
825 		if (d_mup->codeLines() == 1)
826 			return d_mup->evalSingleLine();
827 		else
828 			return d_mup->eval().toDouble();
829 	} else
830 		return d_matrix->cell(i, j);
831 
832 	return 0.0;
833 }
834