1 # -*- coding: utf-8 -*- |
|
2 import numpy |
|
3 import pylab |
|
4 import math |
|
5 import new # monkey patching... |
|
6 |
|
7 from PyQt4 import QtGui, QtCore |
|
8 from PyQt4.QtCore import Qt, SIGNAL |
|
9 |
|
10 from hpgl_parser import HPGLParser |
|
11 |
|
12 class QHPGLPlotterWidget(HPGLParser, QtGui.QWidget): |
|
13 pen_styles = {2: [0.4, 0.6], |
|
14 3: [0.6, 0.4], |
|
15 4: [0.7, 0.1, 0.1, 0.1], |
|
16 5: [0.6, 0.1, 0.2, 0.1], |
|
17 6: [0.45, 0.1, 0.1, 0.2, 0.1, 0.05], |
|
18 } |
|
19 pen_colors = ["black", "green", "red", "blue", "yellow", "cyan", "magenta", |
|
20 "darkred", "darkblue"] |
|
21 |
|
22 def __init__(self, parent=None): |
|
23 QtGui.QWidget.__init__(self, parent) |
|
24 l = QtGui.QVBoxLayout(self) |
|
25 l.setMargin(1) |
|
26 self.qview = QtGui.QGraphicsView(self) |
|
27 self.qview.setRenderHints(QtGui.QPainter.Antialiasing) |
|
28 self.qview.scale(0.5,-0.5) |
|
29 l = self.layout() |
|
30 l.addWidget(self.qview) |
|
31 self.setBackgroundRole(QtGui.QPalette.Base) |
|
32 self.setSizePolicy(QtGui.QSizePolicy.Expanding, |
|
33 QtGui.QSizePolicy.Expanding) |
|
34 self.clear() |
|
35 HPGLParser.__init__(self) |
|
36 |
|
37 def parse(self, data): |
|
38 HPGLParser.parse(self, data) |
|
39 self.resize(self.size()) |
|
40 |
|
41 def clear(self): |
|
42 self.qpen = QtGui.QPen(QtCore.Qt.blue) |
|
43 self.qbrush = QtGui.QBrush(QtCore.Qt.blue) |
|
44 self.qfont = QtGui.QFont('Courier') |
|
45 self.qantialiased = False |
|
46 self.qtransformed = False |
|
47 self.qscene = QtGui.QGraphicsScene() |
|
48 self.qview.setScene(self.qscene) |
|
49 |
|
50 def _get_PW(self): |
|
51 return self._pen_width |
|
52 def _set_PW(self, value): |
|
53 value = float(value) |
|
54 #print "set pen width", value, value*300.0/75.0 |
|
55 #self.qpen.setWidthF(value*300.0/75.0) |
|
56 self._pen_width = value |
|
57 pen_width = property(_get_PW, _set_PW) |
|
58 |
|
59 def LT(self): |
|
60 HPGLParser.LT(self) |
|
61 if self.line_type == 0: |
|
62 self.qpen.setStyle(Qt.SolidLine) |
|
63 elif self.line_type == 1: |
|
64 self.qpen.setStyle(Qt.DotLine) |
|
65 else: |
|
66 pattern = numpy.array(self.pen_styles[self.line_type]) |
|
67 x0, x1, y0, y1 = self.scale |
|
68 dist = math.sqrt((x1-x0)**2 + (y1-y0)**2) |
|
69 pattern = self.pattern_len*dist/100.0 * pattern |
|
70 if self.qpen.widthF()>0: |
|
71 pattern = pattern/self.qpen.widthF() |
|
72 self.qpen.setDashPattern(pattern.tolist()) |
|
73 |
|
74 def SP(self): |
|
75 HPGLParser.SP(self) |
|
76 color = self.pen_colors[self.pen] |
|
77 if isinstance(color, tuple): |
|
78 color = QtGui.QColor(*color) |
|
79 else: |
|
80 color = QtGui.QColor(color) |
|
81 self.qpen.setColor(color) |
|
82 |
|
83 def parse(self, data): |
|
84 HPGLParser.parse(self, data) |
|
85 self.update() |
|
86 self.qview.fitInView(self.qscene.sceneRect(), Qt.KeepAspectRatio) |
|
87 |
|
88 def minimumSizeHint(self): |
|
89 return QtCore.QSize(100, 100) |
|
90 |
|
91 def sizeHint(self): |
|
92 return QtCore.QSize(400, 400) |
|
93 |
|
94 def resizeEvent(self, event): |
|
95 self.qview.fitInView(self.qscene.sceneRect(), Qt.KeepAspectRatio) |
|
96 QtGui.QWidget.resizeEvent(self, event) |
|
97 |
|
98 def plot_lines(self, points): |
|
99 if len(points) == 1: |
|
100 return |
|
101 pa = QtGui.QPainterPath() |
|
102 pa.addPolygon(QtGui.QPolygonF([QtCore.QPointF(*p) for p in points])) |
|
103 self.qscene.addPath(pa, self.qpen) |
|
104 |
|
105 def plot_symbols(self, points): |
|
106 pass |
|
107 |
|
108 def plot_string(self, s): |
|
109 cw, ch = self.get_char_size() |
|
110 # this is very ugly and so, but I don't understand haw is |
|
111 # computed string positionning in HPGL... |
|
112 t0 = self.qscene.addSimpleText(" ", self.qfont) |
|
113 br = t0.boundingRect() |
|
114 mw = br.width() |
|
115 mh = br.height() |
|
116 self.qscene.removeItem(t0) |
|
117 # don't ask me why theses constants are here, they seem OK, that's all |
|
118 t = self.qscene.addSimpleText(s, self.qfont) |
|
119 t.scale(1.0 * cw/mw, -1.6 * ch/mh) |
|
120 x, y = self.pos |
|
121 t.moveBy(x,y) |
|
122 br = t.boundingRect() |
|
123 t.moveBy(-0.5*cw+8, math.sqrt(2)*ch - 13) |
|
124 |
|
125 |
|
126 if __name__=='__main__': |
|
127 import sys |
|
128 a = QtGui.QApplication(sys.argv) |
|
129 mw = QtGui.QMainWindow() |
|
130 w = QtGui.QWidget(mw) |
|
131 mw.setCentralWidget(w) |
|
132 |
|
133 l = QtGui.QVBoxLayout(w) |
|
134 p = QHPGLPlotterWidget(w) |
|
135 l.addWidget(p, 1) |
|
136 b = QtGui.QPushButton("Replot", w) |
|
137 l.addWidget(b) |
|
138 def plot(): |
|
139 p.parse(open(sys.argv[1]).read()) |
|
140 b.connect(b, SIGNAL('pressed()'), plot) |
|
141 mw.show() |
|
142 plot() |
|
143 a.exec_() |
|
144 |
|