pygpibtoolkit/plotter/hpgl_qt.py

Thu, 24 May 2018 23:22:37 +0200

author
David Douard <david.douard@logilab.fr>
date
Thu, 24 May 2018 23:22:37 +0200
changeset 104
916c255b3079
parent 91
f2a8f688dbc0
permissions
-rw-r--r--

[plotter] flake8

# -*- coding: utf-8 -*-
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
""" Copyright (c) 2007-2018 David Douard (Paris, FRANCE).
https://bitbucket.org/dddouard/pygpibtoolkit -- mailto:david.douard@sdfa3.org
"""

import numpy
import math
# import new # monkey patching...

from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtCore import Qt

from pygpibtoolkit.plotter.hpgl_parser import HPGLParser


class QHPGLPlotterWidget(QtWidgets.QWidget, HPGLParser):
    pen_styles = {2: [0.4, 0.6],
                  3: [0.6, 0.4],
                  4: [0.7, 0.1, 0.1, 0.1],
                  5: [0.6, 0.1, 0.2, 0.1],
                  6: [0.45, 0.1, 0.1, 0.2, 0.1, 0.05],
                  }
    pen_colors = ["black", "green", "red", "blue", "yellow", "cyan", "magenta",
                  "darkred", "darkblue"]

    def __init__(self, parent=None):
        super().__init__(parent)
        l = QtWidgets.QVBoxLayout(self)
        l.setContentsMargins(1, 1, 1, 1)
        self.qview = QtWidgets.QGraphicsView(self)
        self.qview.setRenderHints(QtGui.QPainter.Antialiasing)
        self.qview.scale(0.5, -0.5)
        l = self.layout()
        l.addWidget(self.qview)
        self.setBackgroundRole(QtGui.QPalette.Base)
        self.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                           QtWidgets.QSizePolicy.Expanding)
        self.clear()
        HPGLParser.__init__(self)

    def clear(self):
        self.qpen = QtGui.QPen(QtCore.Qt.blue)
        self.qbrush = QtGui.QBrush(QtCore.Qt.blue)
        self.qfont = QtGui.QFont('Courier')
        self.qantialiased = False
        self.qtransformed = False
        self.qscene = QtWidgets.QGraphicsScene()
        self.qview.setScene(self.qscene)

    @property
    def pen_width(self):
        return self._pen_width

    @pen_width.setter
    def pen_width(self, value):
        value = float(value)
        # print "set pen width", value, value*300.0/75.0
        # self.qpen.setWidthF(value*300.0/75.0)
        self._pen_width = value

    def LT(self):
        super().LT()
        if self.line_type == 0:
            self.qpen.setStyle(Qt.SolidLine)
        elif self.line_type == 1:
            self.qpen.setStyle(Qt.DotLine)
        else:
            pattern = numpy.array(self.pen_styles[self.line_type])
            x0, x1, y0, y1 = self.scale
            dist = math.sqrt((x1-x0)**2 + (y1-y0)**2)
            pattern = self.pattern_len*dist/100.0 * pattern
            if self.qpen.widthF() > 0:
                pattern = pattern/self.qpen.widthF()
            self.qpen.setDashPattern(pattern.tolist())

    def SP(self):
        super().SP()
        color = self.pen_colors[self.pen % len(self.pen_colors)]
        if isinstance(color, tuple):
            color = QtGui.QColor(*color)
        else:
            color = QtGui.QColor(color)
        self.qpen.setColor(color)

    def parse(self, data):
        super().parse(data)
        self.update()
        self.qview.fitInView(self.qscene.sceneRect(), Qt.KeepAspectRatio)

    def minimumSizeHint(self):
        return QtCore.QSize(100, 100)

    def sizeHint(self):
        return QtCore.QSize(400, 400)

    def resizeEvent(self, event):
        self.qview.fitInView(self.qscene.sceneRect(), Qt.KeepAspectRatio)
        QtWidgets.QWidget.resizeEvent(self, event)

    def plot_lines(self, points):
        if len(points) == 1:
            return
        pa = QtGui.QPainterPath()
        pa.addPolygon(QtGui.QPolygonF([QtCore.QPointF(*p) for p in points]))
        self.qscene.addPath(pa, self.qpen)

    def plot_symbols(self, points):
        pass

    def plot_string(self, s):
        cw, ch = self.get_char_size()
        # this is very ugly and so, but I don't understand haw is
        # computed string positionning in HPGL...
        t0 = self.qscene.addSimpleText(" ", self.qfont)
        br = t0.boundingRect()
        mw = br.width()
        mh = br.height()
        self.qscene.removeItem(t0)
        # don't ask me why theses constants are here, they seem OK, that's all
        t = self.qscene.addSimpleText(s, self.qfont)
        t.setTransform(QtGui.QTransform(1.0 * cw/mw, 0, 0, -1.6 * ch/mh, 0, 0))
        x, y = self.pos
        t.moveBy(x, y)
        br = t.boundingRect()
        t.moveBy(-0.5*cw+8, math.sqrt(2)*ch - 13)


if __name__ == '__main__':
    import sys
    a = QtWidgets.QApplication(sys.argv)
    mw = QtWidgets.QMainWindow()
    w = QtWidgets.QWidget(mw)
    mw.setCentralWidget(w)

    l = QtWidgets.QVBoxLayout(w)
    p = QHPGLPlotterWidget(w)
    l.addWidget(p, 1)
    b = QtWidgets.QPushButton("Replot", w)
    l.addWidget(b)

    def plot():
        p.parse(open(sys.argv[1]).read())

    b.pressed.connect(plot)
    mw.show()
    plot()
    a.exec_()

mercurial