1 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
2  * Qwt Widget Library
3  * Copyright (C) 1997   Josef Wilgen
4  * Copyright (C) 2002   Uwe Rathmann
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the Qwt License, Version 1.0
8  *****************************************************************************/
9 
10 // vim: expandtab
11 
12 #include <qmap.h>
13 #include "qwt_plot.h"
14 #include "qwt_plot_grid.h"
15 #include "qwt_plot_curve.h"
16 #include "qwt_plot_marker.h"
17 #include "qwt_symbol.h"
18 #include "qwt_legend.h"
19 #include "qwt_legend_item.h"
20 #include "qwt_scale_widget.h"
21 #include "qwt_text_label.h"
22 #include "qwt_plot_canvas.h"
23 #include "qwt_plot_printfilter.h"
24 
25 #if QT_VERSION < 0x040000
26 typedef QColorGroup Palette;
27 #else
28 typedef QPalette Palette;
29 #endif
30 
hasBackgroundColor(const QWidget * widget)31 static bool hasBackgroundColor( const QWidget *widget )
32 {
33 #if QT_VERSION < 0x040000
34     return ( widget->backgroundMode() != Qt::FixedPixmap );
35 #else
36     const QBrush brush =
37         widget->palette().brush( widget->backgroundRole() );
38     return ( brush.style() <= Qt::DiagCrossPattern );
39 #endif
40 }
41 
42 class QwtPlotPrintFilter::PrivateData
43 {
44 public:
PrivateData()45     PrivateData():
46         options(QwtPlotPrintFilter::PrintAll),
47         cache(NULL)
48     {
49     }
50 
~PrivateData()51     ~PrivateData()
52     {
53         delete cache;
54     }
55 
56     class Cache
57     {
58     public:
59         QColor titleColor;
60         QFont titleFont;
61 
62         QwtText scaleTitle[QwtPlot::axisCnt];
63         QColor scaleColor[QwtPlot::axisCnt];
64         QFont scaleFont[QwtPlot::axisCnt];
65         QColor scaleTitleColor[QwtPlot::axisCnt];
66         QFont scaleTitleFont[QwtPlot::axisCnt];
67 
68         QMap<QWidget *, QFont> legendFonts;
69 
70         QColor widgetBackground;
71         QColor canvasBackground;
72         QColor gridColors[2];
73 
74         QMap<const QwtPlotItem *, QColor> curveColors;
75         QMap<const QwtPlotItem *, QColor> curveSymbolBrushColors;
76         QMap<const QwtPlotItem *, QColor> curveSymbolPenColors;
77 
78         QMap<const QwtPlotItem *, QFont> markerFonts;
79         QMap<const QwtPlotItem *, QColor> markerLabelColors;
80         QMap<const QwtPlotItem *, QColor> markerLineColors;
81         QMap<const QwtPlotItem *, QColor> markerSymbolBrushColors;
82         QMap<const QwtPlotItem *, QColor> markerSymbolPenColors;
83     };
84 
85     int options;
86     mutable Cache *cache;
87 };
88 
89 
90 /*!
91   Sets filter options to PrintAll
92 */
93 
QwtPlotPrintFilter()94 QwtPlotPrintFilter::QwtPlotPrintFilter()
95 {
96     d_data = new PrivateData;
97 }
98 
99 //! Destructor
~QwtPlotPrintFilter()100 QwtPlotPrintFilter::~QwtPlotPrintFilter()
101 {
102     delete d_data;
103 }
104 
105 /*!
106   \brief Set plot print options
107   \param options Or'd QwtPlotPrintFilter::Options values
108 
109   \sa options()
110 */
setOptions(int options)111 void QwtPlotPrintFilter::setOptions(int options)
112 {
113     d_data->options = options;
114 }
115 
116 /*!
117   \brief Get plot print options
118   \sa setOptions()
119 */
options() const120 int QwtPlotPrintFilter::options() const
121 {
122     return d_data->options;
123 }
124 
125 /*!
126   \brief Modifies a color for printing
127   \param c Color to be modified
128   \param item Type of item where the color belongs
129   \return Modified color.
130 
131   In case of !(QwtPlotPrintFilter::options() & PrintBackground)
132   MajorGrid is modified to Qt::darkGray, MinorGrid to Qt::gray.
133   All other colors are returned unmodified.
134 */
135 
color(const QColor & c,Item item) const136 QColor QwtPlotPrintFilter::color(const QColor &c, Item item) const
137 {
138     if ( !(options() & PrintBackground))
139     {
140         switch(item)
141         {
142             case MajorGrid:
143                 return Qt::darkGray;
144             case MinorGrid:
145                 return Qt::gray;
146             default:;
147         }
148     }
149     return c;
150 }
151 
152 /*!
153   \brief Modifies a font for printing
154   \param f Font to be modified
155   \param item Type of item where the font belongs
156 
157   All fonts are returned unmodified
158 */
159 
font(const QFont & f,Item) const160 QFont QwtPlotPrintFilter::font(const QFont &f, Item) const
161 {
162     return f;
163 }
164 
165 /*!
166   Change color and fonts of a plot
167   \sa apply()
168 */
apply(QwtPlot * plot) const169 void QwtPlotPrintFilter::apply(QwtPlot *plot) const
170 {
171     const bool doAutoReplot = plot->autoReplot();
172     plot->setAutoReplot(false);
173 
174     delete d_data->cache;
175     d_data->cache = new PrivateData::Cache;
176 
177     PrivateData::Cache &cache = *d_data->cache;
178 
179     if ( plot->titleLabel() )
180     {
181         QwtTextLabel* title = plot->titleLabel();
182         if ( title->text().testPaintAttribute(QwtText::PaintUsingTextColor) )
183         {
184             QwtText text = title->text();
185             cache.titleColor = text.color();
186             text.setColor(color(cache.titleColor, Title));
187             title->setText(text);
188         }
189         else
190         {
191             QPalette palette = title->palette();
192             cache.titleColor = palette.color(
193                 QPalette::Active, Palette::Text);
194             title->setPalette(palette);
195             palette.setColor(QPalette::Active, Palette::Text,
196                 color(cache.titleColor, Title));
197             title->setPalette(palette);
198         }
199 
200         if ( title->text().testPaintAttribute(QwtText::PaintUsingTextFont) )
201         {
202             QwtText text = title->text();
203             cache.titleFont = text.font();
204             text.setFont(font(cache.titleFont, Title));
205             title->setText(text);
206         }
207         else
208         {
209             cache.titleFont = title->font();
210             title->setFont(font(cache.titleFont, Title));
211         }
212     }
213     if ( plot->legend() )
214     {
215 #if QT_VERSION < 0x040000
216         QValueList<QWidget *> list = plot->legend()->legendItems();
217         for ( QValueListIterator<QWidget *> it = list.begin();
218             it != list.end(); ++it )
219 #else
220         QList<QWidget *> list = plot->legend()->legendItems();
221         for ( QList<QWidget*>::iterator it = list.begin();
222             it != list.end(); ++it )
223 #endif
224         {
225             QWidget *w = *it;
226 
227             cache.legendFonts.insert(w, w->font());
228             w->setFont(font(w->font(), Legend));
229 
230             if ( w->inherits("QwtLegendItem") )
231             {
232                 QwtLegendItem *label = (QwtLegendItem *)w;
233 
234                 QwtSymbol symbol = label->symbol();
235                 QPen pen = symbol.pen();
236                 QBrush brush = symbol.brush();
237 
238                 pen.setColor(color(pen.color(), CurveSymbol));
239                 brush.setColor(color(brush.color(), CurveSymbol));
240 
241                 symbol.setPen(pen);
242                 symbol.setBrush(brush);
243                 label->setSymbol(symbol);
244 
245                 pen = label->curvePen();
246                 pen.setColor(color(pen.color(), Curve));
247                 label->setCurvePen(pen);
248             }
249         }
250     }
251     for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
252     {
253         QwtScaleWidget *scaleWidget = plot->axisWidget(axis);
254         if ( scaleWidget )
255         {
256             cache.scaleColor[axis] = scaleWidget->palette().color(
257                 QPalette::Active, Palette::WindowText);
258             QPalette palette = scaleWidget->palette();
259             palette.setColor(QPalette::Active, Palette::WindowText,
260                              color(cache.scaleColor[axis], AxisScale));
261             scaleWidget->setPalette(palette);
262 
263             cache.scaleFont[axis] = scaleWidget->font();
264             scaleWidget->setFont(font(cache.scaleFont[axis], AxisScale));
265 
266             cache.scaleTitle[axis] = scaleWidget->title();
267 
268             QwtText scaleTitle = scaleWidget->title();
269             if ( scaleTitle.testPaintAttribute(QwtText::PaintUsingTextColor) )
270             {
271                 cache.scaleTitleColor[axis] = scaleTitle.color();
272                 scaleTitle.setColor(
273                     color(cache.scaleTitleColor[axis], AxisTitle));
274             }
275 
276             if ( scaleTitle.testPaintAttribute(QwtText::PaintUsingTextFont) )
277             {
278                 cache.scaleTitleFont[axis] = scaleTitle.font();
279                 scaleTitle.setFont(
280                     font(cache.scaleTitleFont[axis], AxisTitle));
281             }
282 
283             scaleWidget->setTitle(scaleTitle);
284 
285             int startDist, endDist;
286             scaleWidget->getBorderDistHint(startDist, endDist);
287             scaleWidget->setBorderDist(startDist, endDist);
288         }
289     }
290 
291     if ( hasBackgroundColor(plot) )
292     {
293         QPalette p = plot->palette();
294         cache.widgetBackground = plot->palette().color(
295             QPalette::Active, Palette::Window);
296         p.setColor(QPalette::Active, Palette::Window,
297             color(cache.widgetBackground, WidgetBackground));
298         plot->setPalette(p);
299     }
300 
301     if ( hasBackgroundColor(plot->canvas()))
302     {
303         cache.canvasBackground = plot->canvasBackground();
304         plot->setCanvasBackground(color(cache.canvasBackground, CanvasBackground));
305     }
306 
307     const QwtPlotItemList& itmList = plot->itemList();
308     for ( QwtPlotItemIterator it = itmList.begin();
309         it != itmList.end(); ++it )
310     {
311         apply(*it);
312     }
313 
314     plot->setAutoReplot(doAutoReplot);
315 }
316 
apply(QwtPlotItem * item) const317 void QwtPlotPrintFilter::apply(QwtPlotItem *item) const
318 {
319     PrivateData::Cache &cache = *d_data->cache;
320 
321     switch(item->rtti())
322     {
323         case QwtPlotItem::Rtti_PlotGrid:
324         {
325             QwtPlotGrid *grid = (QwtPlotGrid *)item;
326 
327             QPen pen = grid->majPen();
328             cache.gridColors[0] = pen.color();
329             pen.setColor(color(pen.color(), MajorGrid));
330             grid->setMajPen(pen);
331 
332             pen = grid->minPen();
333             cache.gridColors[1] = pen.color();
334             pen.setColor(color(pen.color(), MinorGrid));
335             grid->setMinPen(pen);
336 
337             break;
338         }
339         case QwtPlotItem::Rtti_PlotCurve:
340         {
341             QwtPlotCurve *c = (QwtPlotCurve *)item;
342 
343             QwtSymbol symbol = c->symbol();
344 
345             QPen pen = symbol.pen();
346             cache.curveSymbolPenColors.insert(c, pen.color());
347             pen.setColor(color(pen.color(), CurveSymbol));
348             symbol.setPen(pen);
349 
350             QBrush brush = symbol.brush();
351             cache.curveSymbolBrushColors.insert(c, brush.color());
352             brush.setColor(color(brush.color(), CurveSymbol));
353             symbol.setBrush(brush);
354 
355             c->setSymbol(symbol);
356 
357             pen = c->pen();
358             cache.curveColors.insert(c, pen.color());
359             pen.setColor(color(pen.color(), Curve));
360             c->setPen(pen);
361 
362             break;
363         }
364         case QwtPlotItem::Rtti_PlotMarker:
365         {
366             QwtPlotMarker *m = (QwtPlotMarker *)item;
367 
368             QwtText label = m->label();
369             cache.markerFonts.insert(m, label.font());
370             label.setFont(font(label.font(), Marker));
371             cache.markerLabelColors.insert(m, label.color());
372             label.setColor(color(label.color(), Marker));
373             m->setLabel(label);
374 
375             QPen pen = m->linePen();
376             cache.markerLineColors.insert(m, pen.color());
377             pen.setColor(color(pen.color(), Marker));
378             m->setLinePen(pen);
379 
380             QwtSymbol symbol = m->symbol();
381 
382             pen = symbol.pen();
383             cache.markerSymbolPenColors.insert(m, pen.color());
384             pen.setColor(color(pen.color(), MarkerSymbol));
385             symbol.setPen(pen);
386 
387             QBrush brush = symbol.brush();
388             cache.markerSymbolBrushColors.insert(m, brush.color());
389             brush.setColor(color(brush.color(), MarkerSymbol));
390             symbol.setBrush(brush);
391 
392             m->setSymbol(symbol);
393 
394             break;
395         }
396         default:
397             break;
398     }
399 }
400 
401 /*!
402    Reset color and fonts of a plot
403    \sa apply()
404 */
reset(QwtPlot * plot) const405 void QwtPlotPrintFilter::reset(QwtPlot *plot) const
406 {
407     if ( d_data->cache == 0 )
408         return;
409 
410     const bool doAutoReplot = plot->autoReplot();
411     plot->setAutoReplot(false);
412 
413     const PrivateData::Cache &cache = *d_data->cache;
414 
415     if ( plot->titleLabel() )
416     {
417         QwtTextLabel* title = plot->titleLabel();
418         if ( title->text().testPaintAttribute(QwtText::PaintUsingTextColor) )
419         {
420             QwtText text = title->text();
421             text.setColor(cache.titleColor);
422             title->setText(text);
423         }
424         else
425         {
426             QPalette palette = title->palette();
427             palette.setColor(
428                 QPalette::Active, Palette::Text, cache.titleColor);
429             title->setPalette(palette);
430         }
431 
432         if ( title->text().testPaintAttribute(QwtText::PaintUsingTextFont) )
433         {
434             QwtText text = title->text();
435             text.setFont(cache.titleFont);
436             title->setText(text);
437         }
438         else
439         {
440             title->setFont(cache.titleFont);
441         }
442     }
443 
444     if ( plot->legend() )
445     {
446 #if QT_VERSION < 0x040000
447         QValueList<QWidget *> list = plot->legend()->legendItems();
448         for ( QValueListIterator<QWidget *> it = list.begin();
449             it != list.end(); ++it )
450 #else
451         QList<QWidget *> list = plot->legend()->legendItems();
452         for ( QList<QWidget*>::iterator it = list.begin();
453             it != list.end(); ++it )
454 #endif
455         {
456             QWidget *w = *it;
457 
458             if ( cache.legendFonts.contains(w) )
459                 w->setFont(cache.legendFonts[w]);
460 
461             if ( w->inherits("QwtLegendItem") )
462             {
463                 QwtLegendItem *label = (QwtLegendItem *)w;
464                 const QwtPlotItem *plotItem =
465                     (const QwtPlotItem*)plot->legend()->find(label);
466 
467                 QwtSymbol symbol = label->symbol();
468                 if ( cache.curveSymbolPenColors.contains(plotItem) )
469                 {
470                     QPen pen = symbol.pen();
471                     pen.setColor(cache.curveSymbolPenColors[plotItem]);
472                     symbol.setPen(pen);
473                 }
474 
475                 if ( cache.curveSymbolBrushColors.contains(plotItem) )
476                 {
477                     QBrush brush = symbol.brush();
478                     brush.setColor(cache.curveSymbolBrushColors[plotItem]);
479                     symbol.setBrush(brush);
480                 }
481                 label->setSymbol(symbol);
482 
483                 if ( cache.curveColors.contains(plotItem) )
484                 {
485                     QPen pen = label->curvePen();
486                     pen.setColor(cache.curveColors[plotItem]);
487                     label->setCurvePen(pen);
488                 }
489             }
490         }
491     }
492     for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
493     {
494         QwtScaleWidget *scaleWidget = plot->axisWidget(axis);
495         if ( scaleWidget )
496         {
497             QPalette palette = scaleWidget->palette();
498             palette.setColor(QPalette::Active, Palette::WindowText,
499                              cache.scaleColor[axis]);
500             scaleWidget->setPalette(palette);
501 
502             scaleWidget->setFont(cache.scaleFont[axis]);
503             scaleWidget->setTitle(cache.scaleTitle[axis]);
504 
505             int startDist, endDist;
506             scaleWidget->getBorderDistHint(startDist, endDist);
507             scaleWidget->setBorderDist(startDist, endDist);
508         }
509     }
510 
511     if ( hasBackgroundColor(plot) )
512     {
513         QPalette p = plot->palette();
514         p.setColor(QPalette::Active, Palette::Window, cache.widgetBackground);
515         plot->setPalette(p);
516     }
517 
518     if ( hasBackgroundColor(plot->canvas()) )
519     {
520         plot->setCanvasBackground(cache.canvasBackground);
521     }
522 
523     const QwtPlotItemList& itmList = plot->itemList();
524     for ( QwtPlotItemIterator it = itmList.begin();
525         it != itmList.end(); ++it )
526     {
527         reset(*it);
528     }
529 
530     delete d_data->cache;
531     d_data->cache = 0;
532 
533     plot->setAutoReplot(doAutoReplot);
534 }
535 
reset(QwtPlotItem * item) const536 void QwtPlotPrintFilter::reset(QwtPlotItem *item) const
537 {
538     if ( d_data->cache == 0 )
539         return;
540 
541     const PrivateData::Cache &cache = *d_data->cache;
542 
543     switch(item->rtti())
544     {
545         case QwtPlotItem::Rtti_PlotGrid:
546         {
547             QwtPlotGrid *grid = (QwtPlotGrid *)item;
548 
549             QPen pen = grid->majPen();
550             pen.setColor(cache.gridColors[0]);
551             grid->setMajPen(pen);
552 
553             pen = grid->minPen();
554             pen.setColor(cache.gridColors[1]);
555             grid->setMinPen(pen);
556 
557             break;
558         }
559         case QwtPlotItem::Rtti_PlotCurve:
560         {
561             QwtPlotCurve *c = (QwtPlotCurve *)item;
562 
563             QwtSymbol symbol = c->symbol();
564 
565             if ( cache.curveSymbolPenColors.contains(c) )
566             {
567                 symbol.setPen(cache.curveSymbolPenColors[c]);
568             }
569 
570             if ( cache.curveSymbolBrushColors.contains(c) )
571             {
572                 QBrush brush = symbol.brush();
573                 brush.setColor(cache.curveSymbolBrushColors[c]);
574                 symbol.setBrush(brush);
575             }
576             c->setSymbol(symbol);
577 
578             if ( cache.curveColors.contains(c) )
579             {
580                 QPen pen = c->pen();
581                 pen.setColor(cache.curveColors[c]);
582                 c->setPen(pen);
583             }
584 
585             break;
586         }
587         case QwtPlotItem::Rtti_PlotMarker:
588         {
589             QwtPlotMarker *m = (QwtPlotMarker *)item;
590 
591             if ( cache.markerFonts.contains(m) )
592             {
593                 QwtText label = m->label();
594                 label.setFont(cache.markerFonts[m]);
595                 m->setLabel(label);
596             }
597 
598             if ( cache.markerLabelColors.contains(m) )
599             {
600                 QwtText label = m->label();
601                 label.setColor(cache.markerLabelColors[m]);
602                 m->setLabel(label);
603             }
604 
605             if ( cache.markerLineColors.contains(m) )
606             {
607                 QPen pen = m->linePen();
608                 pen.setColor(cache.markerLineColors[m]);
609                 m->setLinePen(pen);
610             }
611 
612             QwtSymbol symbol = m->symbol();
613 
614             if ( cache.markerSymbolPenColors.contains(m) )
615             {
616                 QPen pen = symbol.pen();
617                 pen.setColor(cache.markerSymbolPenColors[m]);
618                 symbol.setPen(pen);
619             }
620 
621             if ( cache.markerSymbolBrushColors.contains(m) )
622             {
623                 QBrush brush = symbol.brush();
624                 brush.setColor(cache.markerSymbolBrushColors[m]);
625                 symbol.setBrush(brush);
626             }
627 
628             m->setSymbol(symbol);
629 
630             break;
631         }
632         default:
633             break;
634     }
635 }
636