PLplot  5.15.0
qt.h
Go to the documentation of this file.
1 //
2 //
3 // This software is provided under the LGPL in March 2009 by the
4 // Cluster Science Centre
5 // QSAS team,
6 // Imperial College, London
7 //
8 // Copyright (C) 2009 Imperial College, London
9 // Copyright (C) 2009-2016 Alan W. Irwin
10 //
11 // This is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Lesser Public License as published
13 // by the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
15 //
16 // This software is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU Lesser General Public License for more details.
20 //
21 // To received a copy of the GNU Library General Public License
22 // write to the Free Software Foundation, Inc.,
23 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 //
25 // History:
26 //
27 //
28 // March 2009: v1.00
29 // Initial release.
30 //
31 //
32 
33 //
34 // Interpretation of the -geometry XSIZExYSIZE option (or the third and fourth
35 // parameters of plspage if those are specified by the user instead) for
36 // the various devices:
37 // - the raster devices (bmpqt, jpgqt, pngqt, ppmqt, tiffqt):
38 // XSIZE and YSIZE define the x and y size in pixels
39 // - qtwidget:
40 // XSIZE and YSIZE define the default x and y size of the widget in
41 // pixels, as well as its aspect ratio, which is kept when the widget is
42 // resized.
43 // - svgqt, epsqt, pdfqt:
44 // XSIZE and YSIZE define the x and y size in points (1/72 of inches).
45 // EPS and PDF files will be drawn in A4 pages for Qt versions before 4.4
46 //
47 // Interpretation of the -dpi DPI option (or the first parameter of
48 // plspage if that is specified by the user instead).
49 // DPI is ignored for all but the raster devices. For those devices
50 // DPI should be set to the DPI value of the monitor being used to view
51 // the results if exact character sizes are desired. Otherwise, DEFAULT_DPI
52 // (set to an average value for modern monitors) is used instead.
53 //
54 
55 #ifndef QT_H
56 #define QT_H
57 
58 #include <iostream>
59 #include <QImage>
60 #include <QPainter>
61 #include <QLinkedList>
62 #include <QPrinter>
63 #include <QApplication>
64 #include <QWidget>
65 #include <QMouseEvent>
66 #include <QTabWidget>
67 #include <QMainWindow>
68 #include <QPicture>
69 #include <QMutex>
70 #include <QPainterPath>
71 
72 #include "plDevs.h"
73 #include "plplotP.h"
74 #include "drivers.h"
75 
76 // Used for devices (epsqt, pdfqt, svgqt) with known physical size in points.
77 #define POINTS_PER_INCH 72
78 
79 // Average value of dots per inch assumed for modern monitors if the user
80 // does not specify a value appropriate to their monitor with plspage or
81 // the -dpi option. Used only for devices with size specified in pixels
82 // but not qtwidget since it has independent access to information (e.g.,
83 // delivered by X) about the DPI of the monitor. So this value is only
84 // used for the raster devices (bmpqt, jpgqt, pngqt, ppmqt, tiffqt).
85 #define DEFAULT_DPI 72
86 
87 // These values are in units of pixels (the raster devices and qtwidget)
88 // or points (epsqt, pdfqt, svgqt). In the points case, this corresponds
89 // to the A4 paper size.
90 #define QT_DEFAULT_X 842
91 #define QT_DEFAULT_Y 595
92 
93 class QtPLDriver;
94 
95 // Master Device Handler for multiple streams
96 // Only handles multiple Qt devices
97 class PLDLLIMPEXP_QT MasterHandler : public QObject
98 {
99  Q_OBJECT
100 
101 public:
102  MasterHandler();
103 
104  bool isMasterDevice( QtPLDriver* d );
105  void setMasterDevice( QtPLDriver* d );
106  void DeviceChangedPage( QtPLDriver* d );
107  void DeviceClosed( QtPLDriver* d );
108 
109 signals:
110  void MasterChangedPage();
111  void MasterClosed();
112 
113 protected:
115 };
116 
117 // Basic class, offering the common interface to all Qt plplot devices
119 {
120 public:
121  // Constructor, taking the device size as arguments
122  QtPLDriver( PLINT i_iWidth = QT_DEFAULT_X, PLINT i_iHeight = QT_DEFAULT_Y );
123 
124  virtual ~QtPLDriver(); // does not delete emitter!
125 
126  void setPLStream( PLStream *pls ); // store the related stream
127 
128  virtual void drawArc( short x, short y, short width, short height, PLFLT angle1, PLFLT angle2, PLFLT rotate, bool fill );
129  // Draws a line from (x1, y1) to (x2, y2) in internal plplot coordinates
130  virtual void drawLine( short x1, short y1, short x2, short y2 );
131  virtual void drawPolyline( short * x, short * y, PLINT npts );
132  virtual void drawPolygon( short * x, short * y, PLINT npts );
133  virtual void drawText( EscText* txt );
134  virtual void setColor( int r, int g, int b, double alpha );
135  virtual void setBackgroundColor( int /* r */, int /* g */, int /* b */, double /* alpha */ ){}
136  virtual void setGradient( int x1, int x2, int y1, int y2,
137  unsigned char *r, unsigned char *g,
138  unsigned char *b, PLFLT *alpha, PLINT ncol1 );
139  virtual void setWidthF( PLFLT w );
140  // Set pen to draw solid strokes (called after drawing dashed strokes)
141  virtual void setSolid();
142  // Conversion factor from internal plplot coordinates to device coordinates
143  double downscale;
144  double m_dWidth, m_dHeight;
145  static QMutex mutex; // All-purpose mutex
146 
147 protected:
148  // Returns font with the good size for a QPicture's resolution
149  QFont getFont( PLUNICODE code );
150  // Draws text in a QPicture using a sub-QPicture (!), updates the current xOffset
151  void drawTextInPicture( QPainter*, const QString& );
152  // Gets the QPicture displaying text, with the base chrht char height
153  QPicture getTextPicture( PLUNICODE fci, PLUNICODE* text, int len, PLFLT chrht );
154 
155  // Text-related variables
157  bool overlined;
160  double yOffset;
161  double xOffset;
162 
164 
165  QPainter * m_painterP;
166 };
167 
168 #if defined ( PLD_bmpqt ) || defined ( PLD_jpgqt ) || defined ( PLD_pngqt ) || defined ( PLD_ppmqt ) || defined ( PLD_tiffqt ) || defined ( PLD_memqt )
169 // Driver painting whatever raster format Qt can save
170 class PLDLLIMPEXP_QT QtRasterDevice : public QtPLDriver, public QImage
171 {
172 public:
173  QtRasterDevice( int i_iWidth = QT_DEFAULT_X,
174  int i_iHeight = QT_DEFAULT_Y );
175  virtual ~QtRasterDevice();
176 
177  virtual void setBackgroundColor( int r, int g, int b, double alpha );
178  void definePlotName( const char* fileName, const char* format );
179  void savePlot();
180  virtual void setResolution( double dotsPerInch )
181  {
182  setDotsPerMeterX( (int) ( ( dotsPerInch / 25.4 ) * 1000. ) );
183  setDotsPerMeterY( (int) ( ( dotsPerInch / 25.4 ) * 1000. ) );
184  }
185  // used by the memqt driver
186  unsigned char *memory;
187 
188 protected:
189  char format[5];
190  QString fileName;
191 };
192 #endif
193 
194 #if defined ( PLD_svgqt ) && QT_VERSION >= 0x040300
195 #include <QSvgGenerator>
196 // Driver painting on an SVG device
197 class PLDLLIMPEXP_QT QtSVGDevice : public QtPLDriver, public QSvgGenerator
198 {
199 public:
200  QtSVGDevice( int i_iWidth = QT_DEFAULT_X,
201  int i_iHeight = QT_DEFAULT_Y );
202 
203  virtual ~QtSVGDevice();
204 
205  virtual void setBackgroundColor( int r, int g, int b, double alpha );
206  void definePlotName( const char* fileName );
207  void savePlot();
208 
209 protected:
210 };
211 #endif
212 
213 #if defined ( PLD_epsqt ) || defined ( PLD_pdfqt )
214 // Driver painting on an EPS or PDF device, uses QPrinter
215 // A (possibly dummy) QApplication must be declared before use
216 class PLDLLIMPEXP_QT QtEPSDevice : public QtPLDriver, public QPrinter
217 {
218 public:
219 #if QT_VERSION < 0x040400
220  QtEPSDevice( int i_iWidth = -1, int i_iHeight = -1 );
221 #else
222  QtEPSDevice( int i_iWidth = QT_DEFAULT_X, int i_iHeight = QT_DEFAULT_Y );
223 #endif
224 
225  virtual ~QtEPSDevice();
226 
227  virtual void setBackgroundColor( int r, int g, int b, double alpha );
228  void definePlotName( const char* fileName, int ifeps );
229  void savePlot();
230 
231 protected:
232 };
233 #endif
234 
235 #if defined ( PLD_qtwidget ) || defined ( PLD_extqt )
236 
237 typedef enum ElementType_
238 {
239  LINE,
240  POLYLINE,
241  POLYGON,
242  RECTANGLE,
243  SET_WIDTH,
244  SET_COLOUR,
245  SET_GRADIENT,
246  SET_SMOOTH,
247  TEXT,
248  SET_BG_COLOUR,
249  ARC
250 } ElementType; // Identifiers for elements of the buffer
251 
252 struct ColourStruct_
253 {
254  PLINT R, G, B, A;
255 };
256 
257 struct TextStruct_
258 {
259  PLFLT x;
260  PLFLT y;
261  PLFLT clipxmin;
262  PLFLT clipymin;
263  PLFLT clipxmax;
264  PLFLT clipymax;
265  PLFLT rotation;
266  PLFLT shear;
267  PLFLT stride;
268  PLFLT just;
269  PLUNICODE * text;
270  PLUNICODE fci;
271  PLINT len;
272  PLFLT chrht;
273 };
274 
275 struct ArcStruct_
276 {
277  QRectF *rect;
278  QPointF *dx;
279  int startAngle;
280  int spanAngle;
281  PLFLT rotate;
282  bool fill;
283 };
284 
285 class BufferElement
286 {
287 public:
288  ElementType Element;
289 
290  union DataType
291  {
292  QLineF * Line;
293  QPolygonF * Polyline;
294  QRectF * Rect;
295  QLinearGradient * LinearGradient;
296  struct ColourStruct_* ColourStruct;
297  struct TextStruct_ * TextStruct;
298  struct ArcStruct_ * ArcStruct;
299  PLINT intParam;
300  PLFLT fltParam;
301  } Data;
302 };
303 
304 // This widget allows to use plplot as a plotting engine in a Qt
305 // Application. The aspect ratio of the plotted data is constant, so
306 // gray strips are used to delimit the page when the widget aspect
307 // ratio is not the one of the plotted page.
308 
309 // N.B. The moc application assumes that the first inherited class and
310 // only that inherited class is a subclass of QObject. Therefore,
311 // Qwidget (a subclass of QObject) must be first.
312 class PLDLLIMPEXP_QT QtPLWidget : public QWidget, public QtPLDriver
313 {
314  Q_OBJECT
315 
316 public:
317  // Parameters are the actual size of the page, NOT the size of the widget
318  // Call QWidget::resize for that
319  QtPLWidget( int i_iWidth = QT_DEFAULT_X, int i_iHeight = QT_DEFAULT_Y, QWidget * parent = 0 );
320 
321  virtual ~QtPLWidget();
322 
323  void clearWidget();
324  void clearBuffer();
325 
326  int pageNumber;
327 
328  void drawArc( short x, short y, short width, short height, PLFLT angle1, PLFLT angle2, PLFLT rotate, bool fill );
329  void drawLine( short x1, short y1, short x2, short y2 );
330  void drawPolyline( short * x, short * y, PLINT npts );
331  void drawPolygon( short * x, short * y, PLINT npts );
332  void setColor( int r, int g, int b, double alpha );
333  void setBackgroundColor( int r, int g, int b, double alpha );
334  void setGradient( int x1, int x2, int y1, int y2,
335  unsigned char *r, unsigned char *g,
336  unsigned char *b, PLFLT *alpha, PLINT ncol1 );
337  void setWidthF( PLFLT r );
338  void drawText( EscText* txt );
339  void flush();
340  void getCursorCmd( PLGraphicsIn *ptr );
341 
342 protected:
343 
344  void resizeEvent( QResizeEvent* );
345  void paintEvent( QPaintEvent* );
346  void mouseEvent( QMouseEvent * event );
347 
348  void getPlotParameters( double & io_dXFact, double & io_dYFact, double & io_dXOffset, double & io_dYOffset ); // gives the parameters to scale and center the plot on the page
349  void doPlot( QPainter* p, double x_fact, double y_fact, double x_offset, double y_offset ); // Actually draws the plot. Deported in a function for readability
350  void renderText( QPainter* p, struct TextStruct_* s, double x_fact, double x_offset, double y_fact, double y_offset );
351  void lookupButtonEvent( QMouseEvent * event );
352  void locate();
353 
354  void resetPensAndBrushes( QPainter* );
355 
356  double m_dAspectRatio; // Is kept constant during resizes
357  QPixmap * m_pixPixmap; // stores the drawn image as long as it does not have to be regenerated
358 
359  QLinkedList<BufferElement> m_listBuffer; // Buffer holding the draw instructions
360 // bool m_bAwaitingRedraw;
361 // int m_iOldSize; // Holds the size of the buffer. Modified => image has to be redrawn
362  bool redrawFromLastFlush;
363  bool redrawAll;
364 
365  // Pens and brushes required to maintain the status between 2 flushes
366  QPen SolidPen;
367  QPen NoPen;
368  bool hasPen;
369  QBrush SolidBrush;
370  // end parameters
371 
372  QLinkedList<BufferElement>::const_iterator start_iterator;
373 
374  struct
375  {
376  int r;
377  int g;
378  int b;
379  double alpha;
380  } lastColour;
381 
382  struct
383  {
384  int r;
385  int g;
386  int b;
387  double alpha;
388  } bgColour;
389 
390  PLGraphicsIn gin; // Graphics Input Structure
391  int locate_mode; // Set while in locate mode
392 
393 protected slots:
394  void mousePressEvent( QMouseEvent * event );
395  void mouseReleaseEvent( QMouseEvent * event );
396  void mouseMoveEvent( QMouseEvent * event );
397  void keyPressEvent( QKeyEvent* event );
398  void closeEvent( QCloseEvent* event );
399  void nextPage();
400 };
401 
402 #endif
403 
404 #if defined ( PLD_extqt )
405 class PLDLLIMPEXP_QT QtExtWidget : public QtPLWidget
406 {
407  Q_OBJECT
408 
409 public:
410  QtExtWidget( int i_iWidth = QT_DEFAULT_X, int i_iHeight = QT_DEFAULT_Y, QWidget * parent = 0 );
411 
412  virtual ~QtExtWidget();
413 
414  void captureMousePlotCoords( PLFLT* x, PLFLT* y );
415 
416 public slots:
417 
418  void mouseMoveEvent( QMouseEvent* event );
419  void mouseReleaseEvent( QMouseEvent* event );
420  void mousePressEvent( QMouseEvent* event );
421 
422 protected:
423  void paintEvent( QPaintEvent* );
424 
425  struct
426  {
427  bool isTracking;
428  double cursor_x, cursor_y;
429  } cursorParameters;
430 
431  bool killed;
432 };
433 
434 PLDLLIMPEXP_QT void plsetqtdev( QtExtWidget* widget ); // Registers the widget as plot device, as the widget has to be created in the Qt application GUI, prior to any plplot call. Must be called before plinit().
435 
436 PLDLLIMPEXP_QT void plsetqtdev( QtExtWidget* widget, int argc, char** argv ); // Registers the widget as plot device, as the widget has to be created in the Qt application GUI, prior to any plplot call. Must be called before plinit().
437 
438 PLDLLIMPEXP_QT void plfreeqtdev(); // Deletes and unregisters the device.
439 
440 #endif
441 
442 // These variables are declared in plqt.cpp but also needed
443 // by the qt driver.
444 extern PLDLLIMPEXP_QT_DATA( int ) vectorize;
445 extern PLDLLIMPEXP_QT_DATA( int ) lines_aa;
447 
448 #if defined ( plplot_pyqt4_EXPORTS )
449 #define initplplot_pyqt4 PLDLLIMPEXP_PYQT4 initplplot_pyqt4
450 #endif
451 
452 #if defined ( plplot_pyqt5_EXPORTS )
453 #define initplplot_pyqt5 PLDLLIMPEXP_PYQT5 initplplot_pyqt5
454 #endif
455 
456 #endif
QtPLDriver * masterDevice
Definition: qt.h:114
Definition: qt.h:119
PLStream * pls
Definition: qt.h:163
QPainter * m_painterP
Definition: qt.h:165
double downscale
Definition: qt.h:143
virtual void setBackgroundColor(int, int, int, double)
Definition: qt.h:135
double m_dHeight
Definition: qt.h:144
double yOffset
Definition: qt.h:160
static QMutex mutex
Definition: qt.h:145
double xOffset
Definition: qt.h:161
double currentFontScale
Definition: qt.h:158
double currentFontSize
Definition: qt.h:159
bool underlined
Definition: qt.h:156
bool overlined
Definition: qt.h:157
#define POLYLINE
Definition: metadefs.h:65
#define LINE
Definition: metadefs.h:61
PLDLLIMPEXP_CXX void fill(PLINT n, const PLFLT *x, const PLFLT *y)
Definition: plstream.cc:246
static PLStream * pls[PL_NSTREAMS]
Definition: plcore.h:88
#define PLDLLIMPEXP_QT
Definition: pldll.h:146
PLUINT PLUNICODE
Definition: plplot.h:201
float PLFLT
Definition: plplot.h:163
int PLINT
Definition: plplot.h:181
static int text
Definition: ps.c:77
static int argc
Definition: qt.cpp:48
static char ** argv
Definition: qt.cpp:49
#define QT_DEFAULT_Y
Definition: qt.h:91
PLDLLIMPEXP_QT_DATA(int) vectorize
#define QT_DEFAULT_X
Definition: qt.h:90
static const char * fileName
Definition: tkMain.c:134