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
93class QtPLDriver;
94
95// Master Device Handler for multiple streams
96// Only handles multiple Qt devices
97class PLDLLIMPEXP_QT MasterHandler : public QObject
98{
99 Q_OBJECT
100
101public:
103
104 bool isMasterDevice( QtPLDriver* d );
105 void setMasterDevice( QtPLDriver* d );
106 void DeviceChangedPage( QtPLDriver* d );
107 void DeviceClosed( QtPLDriver* d );
108
109signals:
110 void MasterChangedPage();
111 void MasterClosed();
112
113protected:
115};
116
117// Basic class, offering the common interface to all Qt plplot devices
119{
120public:
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
147protected:
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
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
170class PLDLLIMPEXP_QT QtRasterDevice : public QtPLDriver, public QImage
171{
172public:
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
188protected:
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
197class PLDLLIMPEXP_QT QtSVGDevice : public QtPLDriver, public QSvgGenerator
198{
199public:
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
209protected:
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
216class PLDLLIMPEXP_QT QtEPSDevice : public QtPLDriver, public QPrinter
217{
218public:
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
231protected:
232};
233#endif
234
235#if defined ( PLD_qtwidget ) || defined ( PLD_extqt )
236
237typedef 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
252struct ColourStruct_
253{
254 PLINT R, G, B, A;
255};
256
257struct 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
275struct ArcStruct_
276{
277 QRectF *rect;
278 QPointF *dx;
279 int startAngle;
280 int spanAngle;
281 PLFLT rotate;
282 bool fill;
283};
284
285class BufferElement
286{
287public:
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.
312class PLDLLIMPEXP_QT QtPLWidget : public QWidget, public QtPLDriver
313{
314 Q_OBJECT
315
316public:
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
342protected:
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
393protected 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 )
405class PLDLLIMPEXP_QT QtExtWidget : public QtPLWidget
406{
407 Q_OBJECT
408
409public:
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
416public slots:
417
418 void mouseMoveEvent( QMouseEvent* event );
419 void mouseReleaseEvent( QMouseEvent* event );
420 void mousePressEvent( QMouseEvent* event );
421
422protected:
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
434PLDLLIMPEXP_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
436PLDLLIMPEXP_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
438PLDLLIMPEXP_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.
444extern PLDLLIMPEXP_QT_DATA( int ) vectorize;
445extern 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