Qwt User's Guide  6.2.0
qwt_plot_panner.cpp
1 /******************************************************************************
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 #include "qwt_plot_panner.h"
11 #include "qwt_scale_div.h"
12 #include "qwt_plot.h"
13 #include "qwt_scale_map.h"
14 #include "qwt_painter.h"
15 
16 #include <qbitmap.h>
17 #include <qstyle.h>
18 #include <qstyleoption.h>
19 #include <qpainter.h>
20 #include <qpainterpath.h>
21 
22 static QBitmap qwtBorderMask( const QWidget* canvas, const QSize& size )
23 {
24 #if QT_VERSION >= 0x050000
25  const qreal pixelRatio = QwtPainter::devicePixelRatio( canvas );
26 #endif
27 
28  const QRect r( 0, 0, size.width(), size.height() );
29 
30  QPainterPath borderPath;
31 
32  ( void )QMetaObject::invokeMethod(
33  const_cast< QWidget* >( canvas ), "borderPath", Qt::DirectConnection,
34  Q_RETURN_ARG( QPainterPath, borderPath ), Q_ARG( QRect, r ) );
35 
36  if ( borderPath.isEmpty() )
37  {
38  if ( canvas->contentsRect() == canvas->rect() )
39  return QBitmap();
40 
41 #if QT_VERSION >= 0x050000
42  QBitmap mask( size* pixelRatio );
43  mask.setDevicePixelRatio( pixelRatio );
44 #else
45  QBitmap mask( size );
46 #endif
47  mask.fill( Qt::color0 );
48 
49  QPainter painter( &mask );
50  painter.fillRect( canvas->contentsRect(), Qt::color1 );
51 
52  return mask;
53  }
54 
55 #if QT_VERSION >= 0x050000
56  QImage image( size* pixelRatio, QImage::Format_ARGB32_Premultiplied );
57  image.setDevicePixelRatio( pixelRatio );
58 #else
59  QImage image( size, QImage::Format_ARGB32_Premultiplied );
60 #endif
61  image.fill( Qt::color0 );
62 
63  QPainter painter( &image );
64  painter.setClipPath( borderPath );
65  painter.fillRect( r, Qt::color1 );
66 
67  // now erase the frame
68 
69  painter.setCompositionMode( QPainter::CompositionMode_DestinationOut );
70 
71  if ( canvas->testAttribute(Qt::WA_StyledBackground ) )
72  {
73  QStyleOptionFrame opt;
74  opt.initFrom(canvas);
75  opt.rect = r;
76  canvas->style()->drawPrimitive( QStyle::PE_Frame, &opt, &painter, canvas );
77  }
78  else
79  {
80  const QVariant borderRadius = canvas->property( "borderRadius" );
81  const QVariant frameWidth = canvas->property( "frameWidth" );
82 
83  if ( borderRadius.canConvert< double >() && frameWidth.canConvert< int >() )
84  {
85  const double br = borderRadius.value< double >();
86  const int fw = frameWidth.value< int >();
87 
88  if ( br > 0.0 && fw > 0 )
89  {
90  painter.setPen( QPen( Qt::color1, fw ) );
91  painter.setBrush( Qt::NoBrush );
92  painter.setRenderHint( QPainter::Antialiasing, true );
93 
94  painter.drawPath( borderPath );
95  }
96  }
97  }
98 
99  painter.end();
100 
101  const QImage mask = image.createMaskFromColor(
102  QColor( Qt::color1 ).rgb(), Qt::MaskOutColor );
103 
104  return QBitmap::fromImage( mask );
105 }
106 
107 class QwtPlotPanner::PrivateData
108 {
109  public:
110  PrivateData()
111  {
112  for ( int axis = 0; axis < QwtAxis::AxisPositions; axis++ )
113  isAxisEnabled[axis] = true;
114  }
115 
116  bool isAxisEnabled[QwtAxis::AxisPositions];
117 };
118 
129  : QwtPanner( canvas )
130 {
131  m_data = new PrivateData();
132 
133  connect( this, SIGNAL(panned(int,int)),
134  SLOT(moveCanvas(int,int)) );
135 }
136 
139 {
140  delete m_data;
141 }
142 
154 void QwtPlotPanner::setAxisEnabled( QwtAxisId axisId, bool on )
155 {
156  if ( QwtAxis::isValid( axisId ) )
157  m_data->isAxisEnabled[axisId] = on;
158 }
159 
168 bool QwtPlotPanner::isAxisEnabled( QwtAxisId axisId ) const
169 {
170  if ( QwtAxis::isValid( axisId ) )
171  return m_data->isAxisEnabled[axisId];
172 
173  return true;
174 }
175 
178 {
179  return parentWidget();
180 }
181 
183 const QWidget* QwtPlotPanner::canvas() const
184 {
185  return parentWidget();
186 }
187 
190 {
191  QWidget* w = canvas();
192  if ( w )
193  w = w->parentWidget();
194 
195  return qobject_cast< QwtPlot* >( w );
196 }
197 
200 {
201  const QWidget* w = canvas();
202  if ( w )
203  w = w->parentWidget();
204 
205  return qobject_cast< const QwtPlot* >( w );
206 }
207 
216 void QwtPlotPanner::moveCanvas( int dx, int dy )
217 {
218  if ( dx == 0 && dy == 0 )
219  return;
220 
221  QwtPlot* plot = this->plot();
222  if ( plot == NULL )
223  return;
224 
225  const bool doAutoReplot = plot->autoReplot();
226  plot->setAutoReplot( false );
227 
228  for ( int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ )
229  {
230  {
231  const QwtAxisId axisId( axisPos );
232 
233  if ( !m_data->isAxisEnabled[axisId] )
234  continue;
235 
236  const QwtScaleMap map = plot->canvasMap( axisId );
237 
238  const double p1 = map.transform( plot->axisScaleDiv( axisId ).lowerBound() );
239  const double p2 = map.transform( plot->axisScaleDiv( axisId ).upperBound() );
240 
241  double d1, d2;
242  if ( QwtAxis::isXAxis( axisPos ) )
243  {
244  d1 = map.invTransform( p1 - dx );
245  d2 = map.invTransform( p2 - dx );
246  }
247  else
248  {
249  d1 = map.invTransform( p1 - dy );
250  d2 = map.invTransform( p2 - dy );
251  }
252 
253  plot->setAxisScale( axisId, d1, d2 );
254  }
255  }
256 
257  plot->setAutoReplot( doAutoReplot );
258  plot->replot();
259 }
260 
268 {
269  if ( canvas() )
270  return qwtBorderMask( canvas(), size() );
271 
272  return QwtPanner::contentsMask();
273 }
274 
278 QPixmap QwtPlotPanner::grab() const
279 {
280  const QWidget* cv = canvas();
281  if ( cv && cv->inherits( "QGLWidget" ) )
282  {
283  // we can't grab from a QGLWidget
284 
285  QPixmap pm( cv->size() );
286  QwtPainter::fillPixmap( cv, pm );
287 
288  QPainter painter( &pm );
289  const_cast< QwtPlot* >( plot() )->drawCanvas( &painter );
290 
291  return pm;
292  }
293 
294  return QwtPanner::grab();
295 }
296 
297 #if QWT_MOC_INCLUDE
298 #include "moc_qwt_plot_panner.cpp"
299 #endif
static void fillPixmap(const QWidget *, QPixmap &, const QPoint &offset=QPoint())
static qreal devicePixelRatio(const QPaintDevice *)
QwtPanner provides panning of a widget.
Definition: qwt_panner.h:36
virtual QBitmap contentsMask() const
Calculate a mask for the contents of the panned widget.
Definition: qwt_panner.cpp:297
virtual QPixmap grab() const
Definition: qwt_panner.cpp:306
void panned(int dx, int dy)
A 2-D plotting widget.
Definition: qwt_plot.h:79
void setAxisScale(QwtAxisId, double min, double max, double stepSize=0)
Disable autoscaling and specify a fixed scale for a selected axis.
bool autoReplot() const
Definition: qwt_plot.cpp:319
virtual void replot()
Redraw the plot.
Definition: qwt_plot.cpp:545
void setAutoReplot(bool=true)
Set or reset the autoReplot option.
Definition: qwt_plot.cpp:310
virtual QwtScaleMap canvasMap(QwtAxisId) const
Definition: qwt_plot.cpp:800
const QwtScaleDiv & axisScaleDiv(QwtAxisId) const
Return the scale division of a specified axis.
QWidget * canvas()
Return observed plot canvas.
virtual QBitmap contentsMask() const override
QwtPlotPanner(QWidget *)
A panner for the canvas of a QwtPlot.
void setAxisEnabled(QwtAxisId axisId, bool on)
En/Disable an axis.
virtual ~QwtPlotPanner()
Destructor.
virtual void moveCanvas(int dx, int dy)
bool isAxisEnabled(QwtAxisId) const
QwtPlot * plot()
Return plot widget, containing the observed plot canvas.
virtual QPixmap grab() const override
double lowerBound() const
double upperBound() const
A scale map.
Definition: qwt_scale_map.h:27
double transform(double s) const
double invTransform(double p) const
bool isValid(int axisPos)
Definition: qwt_axis.h:45
bool isXAxis(int axisPos)
Definition: qwt_axis.h:51