コード例 #1
0
 def paintEvent(self, event):
     QWidget.paintEvent(self, event)
     pmap = self._pixmap
     if pmap.isNull():
         return
     w, h = pmap.width(), pmap.height()
     cw, ch = self.rect().width(), self.rect().height()
     scaled, nw, nh = fit_image(w, h, cw, ch)
     if scaled:
         pmap = pmap.scaled(nw, nh, Qt.IgnoreAspectRatio,
                            Qt.SmoothTransformation)
     w, h = pmap.width(), pmap.height()
     x = int(abs(cw - w) / 2.)
     y = int(abs(ch - h) / 2.)
     target = QRect(x, y, w, h)
     p = QPainter(self)
     p.setRenderHints(QPainter.Antialiasing
                      | QPainter.SmoothPixmapTransform)
     p.drawPixmap(target, pmap)
     pen = QPen()
     pen.setWidth(self.BORDER_WIDTH)
     p.setPen(pen)
     if self.draw_border:
         p.drawRect(target)
     #p.drawRect(self.rect())
     p.end()
コード例 #2
0
ファイル: widgets.py プロジェクト: yeyanchao/calibre
 def paintEvent(self, event):
     QWidget.paintEvent(self, event)
     pmap = self._pixmap
     if pmap.isNull():
         return
     w, h = pmap.width(), pmap.height()
     cw, ch = self.rect().width(), self.rect().height()
     scaled, nw, nh = fit_image(w, h, cw, ch)
     if scaled:
         pmap = pmap.scaled(nw, nh, Qt.IgnoreAspectRatio,
                 Qt.SmoothTransformation)
     w, h = pmap.width(), pmap.height()
     x = int(abs(cw - w)/2.)
     y = int(abs(ch - h)/2.)
     target = QRect(x, y, w, h)
     p = QPainter(self)
     p.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
     p.drawPixmap(target, pmap)
     pen = QPen()
     pen.setWidth(self.BORDER_WIDTH)
     p.setPen(pen)
     if self.draw_border:
         p.drawRect(target)
     #p.drawRect(self.rect())
     p.end()
コード例 #3
0
ファイル: PaintBoard.py プロジェクト: skianzad/MagicPen
    def penMoveEvent(self, pos, pressure, liftedDeque):
        pen_x = pos[0]
        pen_y = pos[1]
        pen_pressure = pressure

        # print(liftedDeque)
        # print(self.__lastPos)

        if self.__lastPos is None:
            self.__lastPos = QPoint(pen_x, pen_y)

        self.__currentPos = QPoint(pen_x, pen_y)
        self.__painter.begin(self.__board)

        if self.EraserMode == False:
            #Non-Eraser mode
            self.__penColor = QColor("blue")
            self.__painter.setPen(QPen(
                self.__penColor, self.__thickness))  #Set pen color, thickness
        else:
            #Eraser mode: pen color is white, thickness is 6
            self.__painter.setPen(QPen(Qt.white, 6))

        self.__painter.drawLine(self.__lastPos, self.__currentPos)
        self.__painter.end()
        self.__lastPos = self.__currentPos

        self.update()  #Show updates

        # If ever detected the pen is lifted, reset the __lastPos variable in order to reposition the pen
        if (True in liftedDeque):
            self.__lastPos = None
コード例 #4
0
ファイル: PaintBoard.py プロジェクト: skianzad/MagicPen
    def penMoveEvent(self, pos, pressure):
        pen_x = pos[0]
        pen_y = pos[1]
        pen_pressure = pressure

        if self.__lastPos is None:
            self.__lastPos = QPoint(pen_x, pen_y)
        elif (abs(pen_x - self.__lastPos.x()) > 21
              or abs(pen_y - self.__lastPos.y()) > 21):
            self.__lastPos = QPoint(pen_x, pen_y)

        self.__currentPos = QPoint(pen_x, pen_y)
        self.__painter.begin(self.__board)

        if self.EraserMode == False:
            #Non-Eraser mode
            self.__painter.setPen(QPen(
                self.__penColor, self.__thickness))  #Set pen color, thickness
        else:
            #Eraser mode: pen color is white, thickness is 6
            self.__painter.setPen(QPen(Qt.white, 6))

        self.__painter.drawLine(self.__lastPos, self.__currentPos)
        self.__painter.end()
        self.__lastPos = self.__currentPos

        self.update()  #Show updates
コード例 #5
0
ファイル: widgets.py プロジェクト: nvdnkpr/calibre
 def paintEvent(self, event):
     QWidget.paintEvent(self, event)
     pmap = self._pixmap
     if pmap.isNull():
         return
     w, h = pmap.width(), pmap.height()
     ow, oh = w, h
     cw, ch = self.rect().width(), self.rect().height()
     scaled, nw, nh = fit_image(w, h, cw, ch)
     if scaled:
         pmap = pmap.scaled(nw, nh, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
     w, h = pmap.width(), pmap.height()
     x = int(abs(cw - w) / 2.0)
     y = int(abs(ch - h) / 2.0)
     target = QRect(x, y, w, h)
     p = QPainter(self)
     p.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
     p.drawPixmap(target, pmap)
     if self.draw_border:
         pen = QPen()
         pen.setWidth(self.BORDER_WIDTH)
         p.setPen(pen)
         p.drawRect(target)
     if self.show_size:
         sztgt = target.adjusted(0, 0, 0, -4)
         f = p.font()
         f.setBold(True)
         p.setFont(f)
         sz = u"\u00a0%d x %d\u00a0" % (ow, oh)
         flags = Qt.AlignBottom | Qt.AlignRight | Qt.TextSingleLine
         szrect = p.boundingRect(sztgt, flags, sz)
         p.fillRect(szrect.adjusted(0, 0, 0, 4), QColor(0, 0, 0, 200))
         p.setPen(QPen(QColor(255, 255, 255)))
         p.drawText(sztgt, flags, sz)
     p.end()
コード例 #6
0
ファイル: PaintBoard.py プロジェクト: skianzad/MagicPen
    def paintArc(self, center_x, center_y, start_x, start_y, end_x, end_y):
        radius = math.sqrt(
            math.pow(center_x - start_x, 2) + math.pow(center_y - start_y, 2))
        rect = QRectF(center_x - radius, center_y - radius, radius * 2,
                      radius * 2)
        # start angle calculation
        startAngle = math.degrees(
            math.atan2(center_y - start_y, start_x - center_x))
        # end angle calculation
        endAngle = math.degrees(math.atan2(center_y - end_y, end_x - center_x))

        # span angle calculation
        spanAngle = endAngle - startAngle
        # assume user always wants to draw clock-wise
        if spanAngle > 0:
            spanAngle = -1 * (360 - spanAngle)
        #print("start angle is " + str(startAngle))
        #print("span angle is " + str(spanAngle))

        self.__painter.begin(self.__board)
        self.__penColor = QColor("black")
        self.__painter.setPen(QPen(self.__penColor, self.__thickness))
        self.__painter.drawArc(rect, 16 * startAngle, 16 * spanAngle)
        self.__painter.end()

        self.update()  #Show updates
コード例 #7
0
ファイル: diff.py プロジェクト: sss/calibre
    def paintEvent(self, event):
        pmap = self.blank if self.pixmap is None or self.pixmap.isNull(
        ) else self.pixmap
        target = self.rect()
        scaled, width, height = fit_image(pmap.width(), pmap.height(),
                                          target.width(), target.height())
        target.setRect(target.x(), target.y(), width, height)
        p = QPainter(self)
        p.setRenderHints(QPainter.Antialiasing
                         | QPainter.SmoothPixmapTransform)
        p.drawPixmap(target, pmap)

        if self.pixmap is not None and not self.pixmap.isNull():
            sztgt = target.adjusted(0, 0, 0, -4)
            f = p.font()
            f.setBold(True)
            p.setFont(f)
            sz = u'\u00a0%d x %d\u00a0' % (self.pixmap.width(),
                                           self.pixmap.height())
            flags = Qt.AlignBottom | Qt.AlignRight | Qt.TextSingleLine
            szrect = p.boundingRect(sztgt, flags, sz)
            p.fillRect(szrect.adjusted(0, 0, 0, 4), QColor(0, 0, 0, 200))
            p.setPen(QPen(QColor(255, 255, 255)))
            p.drawText(sztgt, flags, sz)
        p.end()
コード例 #8
0
ファイル: qwtchart.py プロジェクト: yrrapt/spurdist
    def __init__(self, spurset, fef, parent):
        chart.__init__(self, spurset, fef, parent)
        self.plot = QwtPlot(parent)

        self.plot.setAxisScale(xaxis, self.spurset.RFmin, self.spurset.RFmax)
        self.plot.setAxisScale(yaxis, -self.spurset.dspan / 2,
                               self.spurset.dspan / 2)

        self.plot.setCanvasBackground(Qt.white)
        grid = QwtPlotGrid()
        grid.setMajPen(QPen(Qt.black, 1, Qt.DotLine))
        grid.attach(self.plot)

        self.plot.insertLegend(QwtLegend(self.parent), QwtPlot.ExternalLegend)

        # a picker to be used for the front-end filter parallelogram
        self.picker = QwtPlotPicker(xaxis, yaxis, QwtPicker.PointSelection,
                                    QwtPlotPicker.NoRubberBand,
                                    QwtPicker.AlwaysOff, self.plot.canvas())
        # gonna need this to implement ondrop()
        self._mouseRelease = self.picker.widgetMouseReleaseEvent
        self._picked_obj = None

        self.picker.connect(self.picker, SIGNAL('appended(const QPoint&)'),
                            self.onpick)
        self.picker.connect(self.picker, SIGNAL('moved(const QPoint&)'),
                            self.ondrag)
        # all about the monkey-patching
        self.picker.widgetMouseReleaseEvent = self.ondrop
コード例 #9
0
    def drawScaleContents(self, painter, center, radius):
        dir = 90  #360 - int(roud(self.origin() - self.value()))
        arc = 90  #+ int(round(self.gradient * 90))
        skyColor = QColor(38, 151, 221)
        painter.save()
        painter.setBrush(skyColor)
        painter.drawChord(self.scaleContentsRect(), (dir - arc) * 16,
                          2 * arc * 16)
        direction1 = self.value() * M_PI / 180.0
        direction2 = self.value() * M_PI / 180.0 + M_PI_2

        triangleSize = qRound(radius * 0.15)
        p0 = (QPoint(center.x() + 0, center.y() + 0))
        p1 = qwtPolar2Pos(p0, 2, direction2)
        pa = QPolygon(3)
        pa.setPoint(0, qwtPolar2Pos(p1, 2 * triangleSize, direction2))
        pa.setPoint(1, qwtPolar2Pos(p1, triangleSize, direction2 + M_PI_2))
        pa.setPoint(2, qwtPolar2Pos(p1, triangleSize, direction2 - M_PI_2))
        color = self.palette().color(QPalette.Text)
        painter.setBrush(color)
        painter.drawPolygon(pa)

        p0 = (QPoint(center.x() + 0, center.y() + 0))
        color = self.palette().color(QPalette.Text)
        painter.setBrush(color)
        painter.setPen(QPen(color, 3))
        painter.drawLine(qwtPolar2Pos(p0, radius - 3, direction1),
                         qwtPolar2Pos(p0, radius - 3, direction1 - M_PI))

        painter.restore()
コード例 #10
0
 def paint_non_printing(self, painter, option, charcode):
     text = self.np_pat.sub(r'\n\1', non_printing[charcode])
     painter.drawText(
         option.rect,
         Qt.AlignCenter | Qt.TextWordWrap | Qt.TextWrapAnywhere, text)
     painter.setPen(QPen(Qt.DashLine))
     painter.drawRect(option.rect.adjusted(1, 1, -1, -1))
コード例 #11
0
ファイル: book_details.py プロジェクト: bjhemens/calibre
 def paintEvent(self, event):
     canvas_size = self.rect()
     width = self.current_pixmap_size.width()
     extrax = canvas_size.width() - width
     if extrax < 0: extrax = 0
     x = int(extrax / 2.)
     height = self.current_pixmap_size.height()
     extray = canvas_size.height() - height
     if extray < 0: extray = 0
     y = int(extray / 2.)
     target = QRect(x, y, width, height)
     p = QPainter(self)
     p.setRenderHints(QPainter.Antialiasing
                      | QPainter.SmoothPixmapTransform)
     p.drawPixmap(
         target,
         self.pixmap.scaled(target.size(), Qt.KeepAspectRatio,
                            Qt.SmoothTransformation))
     if gprefs['bd_overlay_cover_size']:
         sztgt = target.adjusted(0, 0, 0, -4)
         f = p.font()
         f.setBold(True)
         p.setFont(f)
         sz = u'\u00a0%d x %d\u00a0' % (self.pixmap.width(),
                                        self.pixmap.height())
         flags = Qt.AlignBottom | Qt.AlignRight | Qt.TextSingleLine
         szrect = p.boundingRect(sztgt, flags, sz)
         p.fillRect(szrect.adjusted(0, 0, 0, 4), QColor(0, 0, 0, 200))
         p.setPen(QPen(QColor(255, 255, 255)))
         p.drawText(sztgt, flags, sz)
     p.end()
コード例 #12
0
ファイル: PaintBoard.py プロジェクト: skianzad/MagicPen
    def paintPolyg(self, x1, y1, x2, y2, x3, y3, x4, y4):
        self.__painter.begin(self.__board)
        self.__penColor = QColor("black")
        self.__painter.setPen(QPen(self.__penColor, self.__thickness))
        self.__painter.drawPolygon(QPoint(x1, y1), QPoint(x2, y2),
                                   QPoint(x3, y3), QPoint(x4, y4))
        self.__painter.end()

        self.update()  #Show updates
コード例 #13
0
 def __init__(self, plot, label, color="green", mode=QwtPicker.PointSelection,
              rubber_band=QwtPicker.VLineRubberBand, tracker_mode=QwtPicker.ActiveOnly, track=None):
     QwtPlotPicker.__init__(self, QwtPlot.xBottom, QwtPlot.yRight, mode, rubber_band, tracker_mode,
                            plot.canvas())
     self.plot = plot
     self.label = label
     self.track = track
     self.color = QColor(color)
     self.setRubberBandPen(QPen(self.color))
コード例 #14
0
ファイル: PaintBoard.py プロジェクト: skianzad/MagicPen
    def paintTriangle(self, points):
        self.__painter.begin(self.__board)
        self.__penColor = QColor("black")
        self.__painter.setPen(QPen(self.__penColor, self.__thickness))
        self.__painter.drawPolygon(points)

        self.__painter.end()

        self.update()  #Show updates
コード例 #15
0
ファイル: view.py プロジェクト: fortyoneandahalf/calibre-1
 def failed_img(self):
     if self._failed_img is None:
         i = QImage(200, 150, QImage.Format_ARGB32)
         i.fill(Qt.white)
         p = QPainter(i)
         r = i.rect().adjusted(10, 10, -10, -10)
         n = QPen(Qt.DashLine)
         n.setColor(Qt.black)
         p.setPen(n)
         p.drawRect(r)
         p.setPen(Qt.black)
         f = self.font()
         f.setPixelSize(20)
         p.setFont(f)
         p.drawText(r.adjusted(10, 0, -10, 0), Qt.AlignCenter | Qt.TextWordWrap, _('Image could not be rendered'))
         p.end()
         self._failed_img = QPixmap.fromImage(i)
     return self._failed_img
コード例 #16
0
 def addPlotBorder(self, border_pen, label, label_color=None, bg_brush=None):
     # make plot items for image frame
     # make curve for image borders
     (l0, l1), (m0, m1) = self.image.getExtents()
     self._border_pen = QPen(border_pen)
     self._image_border.show()
     self._image_border.setData([l0, l0, l1, l1, l0], [m0, m1, m1, m0, m0])
     self._image_border.setPen(self._border_pen)
     self._image_border.setZ(self.image.z() + 1 if self._z_markers is None else self._z_markers)
     if label:
         self._image_label.show()
         self._image_label_text = text = QwtText(" %s " % label)
         text.setColor(label_color)
         text.setBackgroundBrush(bg_brush)
         self._image_label.setValue(l1, m1)
         self._image_label.setLabel(text)
         self._image_label.setLabelAlignment(Qt.AlignRight | Qt.AlignVCenter)
         self._image_label.setZ(self.image.z() + 2 if self._z_markers is None else self._z_markers)
コード例 #17
0
ファイル: PaintBoard.py プロジェクト: skianzad/MagicPen
    def paintEllipse(self, center_x, center_y, radias1, radias2):
        self.__painter.begin(self.__board)
        self.__penColor = QColor("black")
        self.__painter.setPen(QPen(self.__penColor, self.__thickness))
        self.__painter.drawEllipse(QPoint(center_x, center_y), radias1,
                                   radias2)

        self.__painter.end()

        self.update()  #Show updates
コード例 #18
0
ファイル: PaintBoard.py プロジェクト: skianzad/MagicPen
    def paintLine(self, P1_x, P1_y, P2_x, P2_y):
        P1 = QPoint(P1_x, P1_y)
        P2 = QPoint(P2_x, P2_y)

        self.__painter.begin(self.__board)
        self.__painter.setPen(QPen(self.__penColor, self.__thickness))
        self.__painter.drawLine(P1, P2)
        self.__painter.end()

        self.update()  #Show updates
コード例 #19
0
 def copy(self):
     ans = GraphicsState()
     ans.fill = QBrush(self.fill)
     ans.stroke = QPen(self.stroke)
     ans.opacity = self.opacity
     ans.transform = self.transform * QTransform()
     ans.brush_origin = QPointF(self.brush_origin)
     ans.clip_updated = self.clip_updated
     ans.do_fill, ans.do_stroke = self.do_fill, self.do_stroke
     return ans
コード例 #20
0
 def __init__(self):
     self.fill = QBrush(Qt.white)
     self.stroke = QPen()
     self.opacity = 1.0
     self.transform = QTransform()
     self.brush_origin = QPointF()
     self.clip_updated = False
     self.do_fill = False
     self.do_stroke = True
     self.qt_pattern_cache = {}
コード例 #21
0
ファイル: view.py プロジェクト: mrmac123/calibre
 def failed_img(self):
     if self._failed_img is None:
         i = QImage(200, 150, QImage.Format_ARGB32)
         i.fill(Qt.white)
         p = QPainter(i)
         r = i.rect().adjusted(10, 10, -10, -10)
         n = QPen(Qt.DashLine)
         n.setColor(Qt.black)
         p.setPen(n)
         p.drawRect(r)
         p.setPen(Qt.black)
         f = self.font()
         f.setPixelSize(20)
         p.setFont(f)
         p.drawText(r.adjusted(10, 0, -10, 0),
                    Qt.AlignCenter | Qt.TextWordWrap,
                    _('Image could not be rendered'))
         p.end()
         self._failed_img = QPixmap.fromImage(i)
     return self._failed_img
コード例 #22
0
ファイル: PaintBoard.py プロジェクト: skianzad/MagicPen
    def paintRect(self, center_x, center_y, upper_left_x, upper_left_y):
        width = abs(2 * (center_x - upper_left_x))
        height = abs(2 * (center_y - upper_left_y))

        self.__painter.begin(self.__board)
        self.__penColor = QColor("black")
        self.__painter.setPen(QPen(self.__penColor, self.__thickness))
        self.__painter.drawRect(upper_left_x, upper_left_y, width, height)

        self.__painter.end()

        self.update()  #Show updates
コード例 #23
0
 def paintEvent(self, event):
     QWidget.paintEvent(self, event)
     pmap = self._pixmap
     if pmap.isNull():
         return
     w, h = pmap.width(), pmap.height()
     ow, oh = w, h
     cw, ch = self.rect().width(), self.rect().height()
     scaled, nw, nh = fit_image(w, h, cw, ch)
     if scaled:
         pmap = pmap.scaled(nw, nh, Qt.IgnoreAspectRatio,
                            Qt.SmoothTransformation)
     w, h = pmap.width(), pmap.height()
     x = int(abs(cw - w) / 2.)
     y = int(abs(ch - h) / 2.)
     target = QRect(x, y, w, h)
     p = QPainter(self)
     p.setRenderHints(QPainter.Antialiasing
                      | QPainter.SmoothPixmapTransform)
     p.drawPixmap(target, pmap)
     if self.draw_border:
         pen = QPen()
         pen.setWidth(self.BORDER_WIDTH)
         p.setPen(pen)
         p.drawRect(target)
     if self.show_size:
         sztgt = target.adjusted(0, 0, 0, -4)
         f = p.font()
         f.setBold(True)
         p.setFont(f)
         sz = u'\u00a0%d x %d\u00a0' % (ow, oh)
         flags = Qt.AlignBottom | Qt.AlignRight | Qt.TextSingleLine
         szrect = p.boundingRect(sztgt, flags, sz)
         p.fillRect(szrect.adjusted(0, 0, 0, 4), QColor(0, 0, 0, 200))
         p.setPen(QPen(QColor(255, 255, 255)))
         p.drawText(sztgt, flags, sz)
     p.end()
コード例 #24
0
ファイル: PaintBoard.py プロジェクト: skianzad/MagicPen
    def paintArc(self, center_x, center_y, start_x, start_y, end_x, end_y):
        radius = math.sqrt(
            math.pow(center_x - start_x, 2) + math.pow(center_y - start_y, 2))
        rect = QRectF(center_x - radius, center_y - radius, radius * 2,
                      radius * 2)
        startAngle = 16 * math.atan2(start_x - center_y,
                                     start_x - center_x) * 180.0 / math.pi
        endAngle = 16 * math.atan2(end_y - center_y,
                                   end_x - center_x) * 180.0 / math.pi
        spanAngle = endAngle - startAngle

        self.__painter.begin(self.__board)
        self.__painter.setPen(QPen(self.__penColor, self.__thickness))
        self.__painter.drawArc(rect, startAngle, spanAngle)
        self.__painter.end()

        self.update()  #Show updates
コード例 #25
0
    def initBumperGraphics(self):
        
        # Pens
        self.blue_pen = QPen(QColor(0,0,255))
        self.blue_pen.setWidth(10)
        
        self.bumper_lines = []

        # Text state labels
        self.bumper_state_labels = [QGraphicsTextItem() for i in range(0,4)]
        for i in range(len(self.bumper_state_labels)):
            self.bumper_state_labels[i].setFont(QFont('Ubuntu', 14, QFont.Bold))
            self.bumper_state_labels[i].setPlainText('00')
        self.bumper_state_labels[0].setPos(self.bumper_fl_x-10, self.bumper_fl_y + 55)
        self.bumper_state_labels[1].setPos(self.bumper_fr_x-10, self.bumper_fr_y + 55)
        self.bumper_state_labels[2].setPos(self.bumper_rl_x-10, self.bumper_rl_y - 80)
        self.bumper_state_labels[3].setPos(self.bumper_rr_x-10, self.bumper_rr_y - 80)
        
        # Bumper indicator lines
        self.bumperLine(self.bumper_fl_x - 20, self.bumper_fl_y - self.bumper_dy, True)
        self.bumperLine(self.bumper_fl_x - self.bumper_dx, self.bumper_fl_y - 20, False)
        self.bumperLine(self.bumper_fl_x + self.bumper_dx, self.bumper_fl_y - 20, False)
        self.bumperLine(self.bumper_fl_x - 20, self.bumper_fl_y + self.bumper_dy, True)
        self.bumperLine(self.bumper_fr_x - 20, self.bumper_fr_y - self.bumper_dy, True)
        self.bumperLine(self.bumper_fr_x - self.bumper_dx, self.bumper_fr_y - 20, False)
        self.bumperLine(self.bumper_fr_x + self.bumper_dx, self.bumper_fr_y - 20, False)
        self.bumperLine(self.bumper_fr_x - 20, self.bumper_fr_y + self.bumper_dy, True)
        self.bumperLine(self.bumper_rl_x - 20, self.bumper_rl_y - self.bumper_dy, True)
        self.bumperLine(self.bumper_rl_x - self.bumper_dx, self.bumper_rl_y - 20, False)
        self.bumperLine(self.bumper_rl_x + self.bumper_dx, self.bumper_rl_y - 20, False)
        self.bumperLine(self.bumper_rl_x - 20, self.bumper_rl_y + self.bumper_dy, True)
        self.bumperLine(self.bumper_rr_x - 20, self.bumper_rr_y - self.bumper_dy, True)
        self.bumperLine(self.bumper_rr_x - self.bumper_dx, self.bumper_rr_y - 20, False)
        self.bumperLine(self.bumper_rr_x + self.bumper_dx, self.bumper_rr_y - 20, False)
        self.bumperLine(self.bumper_rr_x - 20, self.bumper_rr_y + self.bumper_dy, True)
        
        # Populate scene
        graphics_scene = QGraphicsScene()
        for bumper in self.bumper_lines:
            graphics_scene.addItem(bumper)
        for label in self.bumper_state_labels:
            graphics_scene.addItem(label)
        graphics_scene.setSceneRect(0, 0, self._widget.bumperGraphicsView.width() - 4, self._widget.bumperGraphicsView.height() - 4)
        self._widget.bumperGraphicsView.setScene(graphics_scene)
        self._widget.bumperGraphicsView.setBackgroundBrush(QBrush(QImage(os.path.join(rospkg.RosPack().get_path('mobility_base_tools'), 'images', 'mb_top.png'))))
        self._widget.bumperGraphicsView.show()
コード例 #26
0
 def draw(self, painter, center, length, direction, cg):
     direction1 = direction * M_PI / 180.0
     triangleSize = qRound(length * 0.1)
     painter.save()
     p0 = (QPoint(center.x() + 0, center.y() + 0))
     p1 = qwtPolar2Pos(p0, length - 2 * triangleSize - 2, direction1)
     pa = QPolygon(3)
     pa.setPoint(0, qwtPolar2Pos(p1, 2 * triangleSize, direction1))
     pa.setPoint(1, qwtPolar2Pos(p1, triangleSize, direction1 + M_PI_2))
     pa.setPoint(2, qwtPolar2Pos(p1, triangleSize, direction1 - M_PI_2))
     color = self.palette().color(cg, QPalette.Text)
     painter.setBrush(color)
     painter.drawPolygon(pa)
     painter.setPen(QPen(color, 3))
     painter.drawLine(qwtPolar2Pos(p0, length - 2, direction1 + M_PI_2),
                      qwtPolar2Pos(p0, length - 2, direction1 - M_PI_2))
     painter.restore()
コード例 #27
0
 def paintEvent(self, event):
     res = QToolButton.paintEvent(self, event)
     if _enable_hacked_QToolButton_paintEvent and self.isChecked():
         r = event.rect()
         x,y = r.left(), r.top()
         w,h = r.width(), r.height()
         # There are at least three rect sizes: 30x35, 30x36, 32x33 (see debug-print below).
         # Not sure if this sometimes includes some padding around the icon.
         ## print r.top(),r.bottom(),r.height(), r.left(),r.right(),r.width()
         ## 0 29 30 0 34 35
         ## 0 29 30 0 35 36
         ## 0 31 32 0 32 33
         p = QPainter(self, True) # True claims to mean un-clipped -- not sure if this is good.
             ## Qt4 error: TypeError: too many arguments to QPainter(), 1 at most expected
         color = toolbutton_highlight_color
         p.setPen(QPen(color, 3)) # try 3 and 2
         p.drawRect(x+2,y+2,w-4,h-4) #e could also try drawRoundRect(r, xroundedness, yroundedness)
     return res
コード例 #28
0
ファイル: PaintBoard.py プロジェクト: skianzad/MagicPen
    def paintBezierSpline(self, pointListX, pointListY):
        P1 = QPoint(int(pointListX[0]), int(pointListY[0]))
        path = QtGui.QPainterPath()
        path.moveTo(P1)

        self.__painter.begin(self.__board)
        self.__painter.setPen(QPen(self.__penColor, self.__thickness))

        i = 0
        while i < len(pointListX) - 3:
            P2 = QPoint(int(pointListX[i + 1]), int(pointListY[i + 1]))
            P3 = QPoint(int(pointListX[i + 2]), int(pointListY[i + 2]))
            P4 = QPoint(int(pointListX[i + 3]), int(pointListY[i + 3]))
            path.cubicTo(P2, P3, P4)
            self.__painter.drawPath(path)
            i += 3

        self.__painter.end()

        self.update()  #Show updates
コード例 #29
0
ファイル: PaintBoard.py プロジェクト: skianzad/MagicPen
    def paintAuxArc(self, center_x, center_y, start_x, start_y, end_x, end_y):
        radius = math.sqrt(
            math.pow(center_x - start_x, 2) + math.pow(center_y - start_y, 2))
        rect = QRectF(center_x - radius, center_y - radius, radius * 2,
                      radius * 2)
        # start angle calculation
        startAngle = math.degrees(
            math.atan2(center_y - start_y, start_x - center_x))
        # end angle calculation
        endAngle = math.degrees(math.atan2(center_y - end_y, end_x - center_x))

        # span angle calculation
        spanAngle = 0
        if (self._isAngleInThirdQuadrant(startAngle)
                and self._isAngleInSecondQuadrant(endAngle)
            ) or (self._isAngleInThirdQuadrant(endAngle)
                  and self._isAngleInSecondQuadrant(startAngle)) or (
                      startAngle == 180
                      and self._isAngleInThirdQuadrant(endAngle)
                  ) or (startAngle == -180
                        and self._isAngleInSecondQuadrant(endAngle)) or (
                            endAngle == 180
                            and self._isAngleInThirdQuadrant(startAngle)) or (
                                endAngle == -180
                                and self._isAngleInSecondQuadrant(startAngle)):
            if startAngle == 180 or self._isAngleInThirdQuadrant(startAngle):
                spanAngle = endAngle - (startAngle + 360)
            else:
                spanAngle = (endAngle + 360) - startAngle
        else:
            spanAngle = endAngle - startAngle
        #print("start angle is " + str(startAngle))
        #print("span angle is " + str(spanAngle))

        self.__painter.begin(self.__board)
        self.__penColor = QColor("red")
        self.__painter.setPen(QPen(self.__penColor, self.__thickness))
        self.__painter.drawArc(rect, 16 * startAngle, 16 * spanAngle)
        self.__painter.end()

        self.update()  #Show updates
コード例 #30
0
ファイル: fcset.py プロジェクト: gregsab/Multiflashcards
def background(painter, bkgimg):
    maxx = painter.device().width()
    maxy = painter.device().height()

    rimg = QRectF(0, 0, maxx, maxy * .9)
    #
    painter.fillRect(0, 0, maxx, maxy, QBrush(Qt.red, Qt.SolidPattern))
    painter.drawImage(rimg, bkgimg)

    wwh = QColor(255, 255, 255, 128)

    painter.fillRect(0, 2 * maxy / 10, maxx, 4 * maxy / 10,
                     QBrush(wwh, Qt.SolidPattern))

    u = QRectF(0, 9 * maxy / 10, maxx, maxy / 10)
    penHText = QPen(Qt.white)
    painter.setPen(penHText)
    painter.setFont(QFont("Arial", 16, italic=True))
    painter.drawText(
        u, Qt.AlignLeft | Qt.TextIncludeTrailingSpaces | Qt.AlignVCenter,
        " ekskursja.pl/flashcards")
コード例 #31
0
 def __init__(self, plot, color="black", linestyle=Qt.DotLine, align=Qt.AlignBottom | Qt.AlignRight, z=90,
              label="", zlabel=None, linewidth=1, spacing=2,
              yaxis=QwtPlot.yRight):
     self.line = TiggerPlotCurve()
     self.color = color = color if isinstance(color, QColor) else QColor(color)
     self.line.setPen(QPen(color, linewidth, linestyle))
     self.marker = TiggerPlotMarker()
     self.marker.setLabelAlignment(align)
     try:
         self.marker.setSpacing(spacing)
     except AttributeError:
         pass
     self.setText(label)
     self.line.setZ(z)
     self.marker.setZ(zlabel if zlabel is not None else z)
     # set axes -- using yRight, since that is the "markup" z-axis
     self.line.setAxis(QwtPlot.xBottom, yaxis)
     self.marker.setAxis(QwtPlot.xBottom, yaxis)
     # attach to plot
     self.line.attach(plot)
     self.marker.attach(plot)
コード例 #32
0
ファイル: PaintBoard.py プロジェクト: skianzad/MagicPen
    def paintPCircle(self, center_x, center_y, start_x, start_y, pers_x,
                     pers_y):
        point = [start_x, start_y]
        center = [center_x, center_y]
        distance = [(point[0] - center[0]), (point[1] - center[1])]
        phi = math.atan2(distance[1], distance[0])
        r = math.sqrt(distance[0] * distance[0] + distance[1] * distance[1])
        points = self.PointsInCircum(r, 300, phi)
        #Drawing the circle in perspective
        dist_x = center_x - pers_x
        print("dist_x", dist_x, pers_x, pers_y, center_x, center_y)
        points = [(j[0], (j[1] + center_x - pers_y) *
                   ((j[0] + center_x) / dist_x) + pers_y - center_y)
                  for j in points]

        self.__painter.begin(self.__board)
        self.__penColor = QColor("blue")
        self.__painter.setPen(QPen(self.__penColor, self.__thickness))
        for x in points:
            self.__painter.drawPoint(round(x[0] + center[0], 3),
                                     round(x[1] / 1.00 + center[1], 3))

        self.__painter.end()
コード例 #33
0
    def do_paint(self, painter, option, index):
        text = unicode(index.data(Qt.DisplayRole).toString())
        font = QFont(option.font)
        font.setPointSize(QFontInfo(font).pointSize() * 1.5)
        font2 = QFont(font)
        font2.setFamily(text)

        system, has_latin = writing_system_for_font(font2)
        if has_latin:
            font = font2

        r = option.rect

        if option.state & QStyle.State_Selected:
            painter.setPen(QPen(option.palette.highlightedText(), 0))

        if (option.direction == Qt.RightToLeft):
            r.setRight(r.right() - 4)
        else:
            r.setLeft(r.left() + 4)

        painter.setFont(font)
        painter.drawText(r,
                         Qt.AlignVCenter | Qt.AlignLeading | Qt.TextSingleLine,
                         text)

        if (system != QFontDatabase.Any):
            w = painter.fontMetrics().width(text + "  ")
            painter.setFont(font2)
            sample = QFontDatabase().writingSystemSample(system)
            if (option.direction == Qt.RightToLeft):
                r.setRight(r.right() - w)
            else:
                r.setLeft(r.left() + w)
            painter.drawText(
                r, Qt.AlignVCenter | Qt.AlignLeading | Qt.TextSingleLine,
                sample)
コード例 #34
0
ファイル: Controller.py プロジェクト: ska-sa/tigger
class ImageController(QFrame):
    """An ImageController is a widget for controlling the display of one image.
    It can emit the following signals from the image:
    raise                     raise button was clicked
    center                  center-on-image option was selected
    unload                  unload option was selected
    slice                     image slice has changed, need to redraw (emitted by SkyImage automatically)
    repaint                 image display range or colormap has changed, need to redraw (emitted by SkyImage automatically)
    """

    def __init__(self, image, parent, imgman, name=None, save=False):
        QFrame.__init__(self, parent)
        self.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
        # init state
        self.image = image
        self._imgman = imgman
        self._currier = PersistentCurrier()
        self._control_dialog = None
        # create widgets
        self._lo = lo = QHBoxLayout(self)
        lo.setContentsMargins(0, 0, 0, 0)
        lo.setSpacing(2)
        # raise button
        self._wraise = QToolButton(self)
        lo.addWidget(self._wraise)
        self._wraise.setIcon(pixmaps.raise_up.icon())
        self._wraise.setAutoRaise(True)
        self._can_raise = False
        QObject.connect(self._wraise, SIGNAL("clicked()"), self._raiseButtonPressed)
        self._wraise.setToolTip("""<P>Click here to raise this image above other images. Hold the button down briefly to
      show a menu of image operations.</P>""")
        # center label
        self._wcenter = QLabel(self)
        self._wcenter.setPixmap(pixmaps.center_image.pm())
        self._wcenter.setToolTip(
            "<P>The plot is currently centered on (the reference pixel %d,%d) of this image.</P>" % self.image.referencePixel())
        lo.addWidget(self._wcenter)
        # name/filename label
        self.name = image.name
        self._wlabel = QLabel(self.name, self)
        self._number = 0
        self.setName(self.name)
        self._wlabel.setToolTip("%s %s" % (image.filename, "\u00D7".join(map(str, image.data().shape))))
        lo.addWidget(self._wlabel, 1)
        # if 'save' is specified, create a "save" button
        if save:
            self._wsave = QToolButton(self)
            lo.addWidget(self._wsave)
            self._wsave.setText("save")
            self._wsave.setAutoRaise(True)
            self._save_dir = save if isinstance(save, str) else "."
            QObject.connect(self._wsave, SIGNAL("clicked()"), self._saveImage)
            self._wsave.setToolTip("""<P>Click here to write this image to a FITS file.</P>""")
        # render control
        dprint(2, "creating RenderControl")
        self._rc = RenderControl(image, self)
        dprint(2, "done")
        # selectors for extra axes
        self._wslicers = []
        curslice = self._rc.currentSlice();  # this may be loaded from config, so not necessarily 0
        for iextra, axisname, labels in self._rc.slicedAxes():
            if axisname.upper() not in ["STOKES", "COMPLEX"]:
                lbl = QLabel("%s:" % axisname, self)
                lo.addWidget(lbl)
            else:
                lbl = None
            slicer = QComboBox(self)
            self._wslicers.append(slicer)
            lo.addWidget(slicer)
            slicer.addItems(labels)
            slicer.setToolTip("""<P>Selects current slice along the %s axis.</P>""" % axisname)
            slicer.setCurrentIndex(curslice[iextra])
            QObject.connect(slicer, SIGNAL("activated(int)"), self._currier.curry(self._rc.changeSlice, iextra))
        # min/max display ranges
        lo.addSpacing(5)
        self._wrangelbl = QLabel(self)
        lo.addWidget(self._wrangelbl)
        self._minmaxvalidator = FloatValidator(self)
        self._wmin = QLineEdit(self)
        self._wmax = QLineEdit(self)
        width = self._wmin.fontMetrics().width("1.234567e-05")
        for w in self._wmin, self._wmax:
            lo.addWidget(w, 0)
            w.setValidator(self._minmaxvalidator)
            w.setMaximumWidth(width)
            w.setMinimumWidth(width)
            QObject.connect(w, SIGNAL("editingFinished()"), self._changeDisplayRange)
        # full-range button
        self._wfullrange = QToolButton(self)
        lo.addWidget(self._wfullrange, 0)
        self._wfullrange.setIcon(pixmaps.zoom_range.icon())
        self._wfullrange.setAutoRaise(True)
        QObject.connect(self._wfullrange, SIGNAL("clicked()"), self.renderControl().resetSubsetDisplayRange)
        rangemenu = QMenu(self)
        rangemenu.addAction(pixmaps.full_range.icon(), "Full subset", self.renderControl().resetSubsetDisplayRange)
        for percent in (99.99, 99.9, 99.5, 99, 98, 95):
            rangemenu.addAction("%g%%" % percent, self._currier.curry(self._changeDisplayRangeToPercent, percent))
        self._wfullrange.setPopupMode(QToolButton.DelayedPopup)
        self._wfullrange.setMenu(rangemenu)
        # update widgets from current display range
        self._updateDisplayRange(*self._rc.displayRange())
        # lock button
        self._wlock = QToolButton(self)
        self._wlock.setIcon(pixmaps.unlocked.icon())
        self._wlock.setAutoRaise(True)
        self._wlock.setToolTip("""<P>Click to lock or unlock the intensity range. When the intensity range is locked across multiple images, any changes in the intensity
          range of one are propagated to the others. Hold the button down briefly for additional options.</P>""")
        lo.addWidget(self._wlock)
        QObject.connect(self._wlock, SIGNAL("clicked()"), self._toggleDisplayRangeLock)
        QObject.connect(self.renderControl(), SIGNAL("displayRangeLocked"), self._setDisplayRangeLock)
        QObject.connect(self.renderControl(), SIGNAL("dataSubsetChanged"), self._dataSubsetChanged)
        lockmenu = QMenu(self)
        lockmenu.addAction(pixmaps.locked.icon(), "Lock all to this",
                           self._currier.curry(imgman.lockAllDisplayRanges, self.renderControl()))
        lockmenu.addAction(pixmaps.unlocked.icon(), "Unlock all", imgman.unlockAllDisplayRanges)
        self._wlock.setPopupMode(QToolButton.DelayedPopup)
        self._wlock.setMenu(lockmenu)
        self._setDisplayRangeLock(self.renderControl().isDisplayRangeLocked())
        # dialog button
        self._wshowdialog = QToolButton(self)
        lo.addWidget(self._wshowdialog)
        self._wshowdialog.setIcon(pixmaps.colours.icon())
        self._wshowdialog.setAutoRaise(True)
        self._wshowdialog.setToolTip("""<P>Click for colourmap and intensity policy options.</P>""")
        QObject.connect(self._wshowdialog, SIGNAL("clicked()"), self.showRenderControls)
        tooltip = """<P>You can change the currently displayed intensity range by entering low and high limits here.</P>
    <TABLE>
      <TR><TD><NOBR>Image min:</NOBR></TD><TD>%g</TD><TD>max:</TD><TD>%g</TD></TR>
      </TABLE>""" % self.image.imageMinMax()
        for w in self._wmin, self._wmax, self._wrangelbl:
            w.setToolTip(tooltip)

        # create image operations menu
        self._menu = QMenu(self.name, self)
        self._qa_raise = self._menu.addAction(pixmaps.raise_up.icon(), "Raise image",
                                              self._currier.curry(self.image.emit, SIGNAL("raise")))
        self._qa_center = self._menu.addAction(pixmaps.center_image.icon(), "Center plot on image",
                                               self._currier.curry(self.image.emit, SIGNAL("center")))
        self._qa_show_rc = self._menu.addAction(pixmaps.colours.icon(), "Colours && Intensities...",
                                                self.showRenderControls)
        if save:
            self._qa_save = self._menu.addAction("Save image...", self._saveImage)
        self._menu.addAction("Export image to PNG file...", self._exportImageToPNG)
        self._export_png_dialog = None
        self._menu.addAction("Unload image", self._currier.curry(self.image.emit, SIGNAL("unload")))
        self._wraise.setMenu(self._menu)
        self._wraise.setPopupMode(QToolButton.DelayedPopup)

        # connect updates from renderControl and image
        self.image.connect(SIGNAL("slice"), self._updateImageSlice)
        QObject.connect(self._rc, SIGNAL("displayRangeChanged"), self._updateDisplayRange)

        # default plot depth of image markers
        self._z_markers = None
        # and the markers themselves
        self._image_border = QwtPlotCurve()
        self._image_label = QwtPlotMarker()

        # subset markers
        self._subset_pen = QPen(QColor("Light Blue"))
        self._subset_border = QwtPlotCurve()
        self._subset_border.setPen(self._subset_pen)
        self._subset_border.setVisible(False)
        self._subset_label = QwtPlotMarker()
        text = QwtText("subset")
        text.setColor(self._subset_pen.color())
        self._subset_label.setLabel(text)
        self._subset_label.setLabelAlignment(Qt.AlignRight | Qt.AlignBottom)
        self._subset_label.setVisible(False)
        self._setting_lmrect = False

        self._all_markers = [self._image_border, self._image_label, self._subset_border, self._subset_label]

    def close(self):
        if self._control_dialog:
            self._control_dialog.close()
            self._control_dialog = None

    def __del__(self):
        self.close()

    def __eq__(self, other):
        return self is other

    def renderControl(self):
        return self._rc

    def getMenu(self):
        return self._menu

    def getFilename(self):
        return self.image.filename

    def setName(self, name):
        self.name = name
        self._wlabel.setText("%s: %s" % (chr(ord('a') + self._number), self.name))

    def setNumber(self, num):
        self._number = num
        self._menu.menuAction().setText("%s: %s" % (chr(ord('a') + self._number), self.name))
        self._qa_raise.setShortcut(QKeySequence("Alt+" + chr(ord('A') + num)))
        self.setName(self.name)

    def getNumber(self):
        return self._number

    def setPlotProjection(self, proj):
        self.image.setPlotProjection(proj)
        sameproj = proj == self.image.projection
        self._wcenter.setVisible(sameproj)
        self._qa_center.setVisible(not sameproj)
        if self._image_border:
            (l0, l1), (m0, m1) = self.image.getExtents()
            path = numpy.array([l0, l0, l1, l1, l0]), numpy.array([m0, m1, m1, m0, m0])
            self._image_border.setData(*path)
            if self._image_label:
                self._image_label.setValue(path[0][2], path[1][2])

    def addPlotBorder(self, border_pen, label, label_color=None, bg_brush=None):
        # make plot items for image frame
        # make curve for image borders
        (l0, l1), (m0, m1) = self.image.getExtents()
        self._border_pen = QPen(border_pen)
        self._image_border.show()
        self._image_border.setData([l0, l0, l1, l1, l0], [m0, m1, m1, m0, m0])
        self._image_border.setPen(self._border_pen)
        self._image_border.setZ(self.image.z() + 1 if self._z_markers is None else self._z_markers)
        if label:
            self._image_label.show()
            self._image_label_text = text = QwtText(" %s " % label)
            text.setColor(label_color)
            text.setBackgroundBrush(bg_brush)
            self._image_label.setValue(l1, m1)
            self._image_label.setLabel(text)
            self._image_label.setLabelAlignment(Qt.AlignRight | Qt.AlignVCenter)
            self._image_label.setZ(self.image.z() + 2 if self._z_markers is None else self._z_markers)

    def setPlotBorderStyle(self, border_color=None, label_color=None):
        if border_color:
            self._border_pen.setColor(border_color)
            self._image_border.setPen(self._border_pen)
        if label_color:
            self._image_label_text.setColor(label_color)
            self._image_label.setLabel(self._image_label_text)

    def showPlotBorder(self, show=True):
        self._image_border.setVisible(show)
        self._image_label.setVisible(show)

    def attachToPlot(self, plot, z_markers=None):
        for item in [self.image] + self._all_markers:
            if item.plot() != plot:
                item.attach(plot)

    def setImageVisible(self, visible):
        self.image.setVisible(visible)

    def showRenderControls(self):
        if not self._control_dialog:
            dprint(1, "creating control dialog")
            self._control_dialog = ImageControlDialog(self, self._rc, self._imgman)
            dprint(1, "done")
        if not self._control_dialog.isVisible():
            dprint(1, "showing control dialog")
            self._control_dialog.show()
        else:
            self._control_dialog.hide()

    def _changeDisplayRangeToPercent(self, percent):
        if not self._control_dialog:
            self._control_dialog = ImageControlDialog(self, self._rc, self._imgman)
        self._control_dialog._changeDisplayRangeToPercent(percent)

    def _updateDisplayRange(self, dmin, dmax):
        """Updates display range widgets."""
        self._wmin.setText("%.4g" % dmin)
        self._wmax.setText("%.4g" % dmax)
        self._updateFullRangeIcon()

    def _changeDisplayRange(self):
        """Gets display range from widgets and updates the image with it."""
        try:
            newrange = float(str(self._wmin.text())), float(str(self._wmax.text()))
        except ValueError:
            return
        self._rc.setDisplayRange(*newrange)

    def _dataSubsetChanged(self, subset, minmax, desc, subset_type):
        """Called when the data subset changes (or is reset)"""
        # hide the subset indicator -- unless we're invoked while we're actually setting the subset itself
        if not self._setting_lmrect:
            self._subset = None
            self._subset_border.setVisible(False)
            self._subset_label.setVisible(False)

    def setLMRectSubset(self, rect):
        self._subset = rect
        l0, m0, l1, m1 = rect.getCoords()
        self._subset_border.setData([l0, l0, l1, l1, l0], [m0, m1, m1, m0, m0])
        self._subset_border.setVisible(True)
        self._subset_label.setValue(max(l0, l1), max(m0, m1))
        self._subset_label.setVisible(True)
        self._setting_lmrect = True
        self.renderControl().setLMRectSubset(rect)
        self._setting_lmrect = False

    def currentSlice(self):
        return self._rc.currentSlice()

    def _updateImageSlice(self, slice):
        dprint(2, slice)
        for i, (iextra, name, labels) in enumerate(self._rc.slicedAxes()):
            slicer = self._wslicers[i]
            if slicer.currentIndex() != slice[iextra]:
                dprint(3, "setting widget", i, "to", slice[iextra])
                slicer.setCurrentIndex(slice[iextra])

    def setMarkersZ(self, z):
        self._z_markers = z
        for i, elem in enumerate(self._all_markers):
            elem.setZ(z + i)

    def setZ(self, z, top=False, depthlabel=None, can_raise=True):
        self.image.setZ(z)
        if self._z_markers is None:
            for i, elem in enumerate(self._all_markers):
                elem.setZ(z + i + i)
        # set the depth label, if any
        label = "%s: %s" % (chr(ord('a') + self._number), self.name)
        # label = "%s %s"%(depthlabel,self.name) if depthlabel else self.name
        if top:
            label = "%s: <B>%s</B>" % (chr(ord('a') + self._number), self.name)
        self._wlabel.setText(label)
        # set hotkey
        self._qa_show_rc.setShortcut(Qt.Key_F9 if top else QKeySequence())
        # set raise control
        self._can_raise = can_raise
        self._qa_raise.setVisible(can_raise)
        self._wlock.setVisible(can_raise)
        if can_raise:
            self._wraise.setToolTip(
                "<P>Click here to raise this image to the top. Click on the down-arrow to access the image menu.</P>")
        else:
            self._wraise.setToolTip("<P>Click to access the image menu.</P>")

    def _raiseButtonPressed(self):
        if self._can_raise:
            self.image.emit(SIGNAL("raise"))
        else:
            self._wraise.showMenu()

    def _saveImage(self):
        filename = QFileDialog.getSaveFileName(self, "Save FITS file", self._save_dir,
                                               "FITS files(*.fits *.FITS *fts *FTS)")
        filename = str(filename)
        if not filename:
            return
        busy = BusyIndicator()
        self._imgman.showMessage("""Writing FITS image %s""" % filename, 3000)
        QApplication.flush()
        try:
            self.image.save(filename)
        except Exception as exc:
            busy = None
            traceback.print_exc()
            self._imgman.showErrorMessage("""Error writing FITS image %s: %s""" % (filename, str(sys.exc_info()[1])))
            return None
        self.renderControl().startSavingConfig(filename)
        self.setName(self.image.name)
        self._qa_save.setVisible(False)
        self._wsave.hide()
        busy = None

    def _exportImageToPNG(self, filename=None):
        if not filename:
            if not self._export_png_dialog:
                dialog = self._export_png_dialog = QFileDialog(self, "Export image to PNG", ".", "*.png")
                dialog.setDefaultSuffix("png")
                dialog.setFileMode(QFileDialog.AnyFile)
                dialog.setAcceptMode(QFileDialog.AcceptSave)
                dialog.setModal(True)
                QObject.connect(dialog, SIGNAL("filesSelected(const QStringList &)"), self._exportImageToPNG)
            return self._export_png_dialog.exec_() == QDialog.Accepted
        busy = BusyIndicator()
        if isinstance(filename, QStringList):
            filename = filename[0]
        filename = str(filename)
        # make QPixmap
        nx, ny = self.image.imageDims()
        (l0, l1), (m0, m1) = self.image.getExtents()
        pixmap = QPixmap(nx, ny)
        painter = QPainter(pixmap)
        # use QwtPlot implementation of draw canvas, since we want to avoid caching
        xmap = QwtScaleMap()
        xmap.setPaintInterval(0, nx)
        xmap.setScaleInterval(l1, l0)
        ymap = QwtScaleMap()
        ymap.setPaintInterval(ny, 0)
        ymap.setScaleInterval(m0, m1)
        self.image.draw(painter, xmap, ymap, pixmap.rect())
        painter.end()
        # save to file
        try:
            pixmap.save(filename, "PNG")
        except Exception as exc:
            self.emit(SIGNAL("showErrorMessage"), "Error writing %s: %s" % (filename, str(exc)))
            return
        self.emit(SIGNAL("showMessage"), "Exported image to file %s" % filename)

    def _toggleDisplayRangeLock(self):
        self.renderControl().lockDisplayRange(not self.renderControl().isDisplayRangeLocked())

    def _setDisplayRangeLock(self, locked):
        self._wlock.setIcon(pixmaps.locked.icon() if locked else pixmaps.unlocked.icon())

    def _updateFullRangeIcon(self):
        if self._rc.isSubsetDisplayRange():
            self._wfullrange.setIcon(pixmaps.zoom_range.icon())
            self._wfullrange.setToolTip(
                """<P>The current intensity range is the full range. Hold this button down briefly for additional options.</P>""")
        else:
            self._wfullrange.setIcon(pixmaps.full_range.icon())
            self._wfullrange.setToolTip(
                """<P>Click to reset to a full intensity range. Hold the button down briefly for additional options.</P>""")
コード例 #35
0
ファイル: view.py プロジェクト: mrmac123/calibre
    def paintEvent(self, event):
        QSplitterHandle.paintEvent(self, event)
        left, right = self.parent().left, self.parent().right
        painter = QPainter(self)
        painter.setClipRect(event.rect())
        w = self.width()
        h = self.height()
        painter.setRenderHints(QPainter.Antialiasing, True)

        C = 16  # Curve factor.

        def create_line(ly, ry, right_to_left=False):
            ' Create path that represents upper or lower line of change marker '
            line = QPainterPath()
            if not right_to_left:
                line.moveTo(0, ly)
                line.cubicTo(C, ly, w - C, ry, w, ry)
            else:
                line.moveTo(w, ry)
                line.cubicTo(w - C, ry, C, ly, 0, ly)
            return line

        ldoc, rdoc = left.document(), right.document()
        lorigin, rorigin = left.contentOffset(), right.contentOffset()
        lfv, rfv = left.firstVisibleBlock().blockNumber(
        ), right.firstVisibleBlock().blockNumber()
        lines = []

        for (ltop, lbot, kind), (rtop, rbot,
                                 kind) in zip(left.changes, right.changes):
            if lbot < lfv and rbot < rfv:
                continue
            ly_top = left.blockBoundingGeometry(
                ldoc.findBlockByNumber(ltop)).translated(lorigin).y()
            ly_bot = left.blockBoundingGeometry(
                ldoc.findBlockByNumber(lbot)).translated(lorigin).y()
            ry_top = right.blockBoundingGeometry(
                rdoc.findBlockByNumber(rtop)).translated(rorigin).y()
            ry_bot = right.blockBoundingGeometry(
                rdoc.findBlockByNumber(rbot)).translated(rorigin).y()
            if max(ly_top, ly_bot, ry_top, ry_bot) < 0:
                continue
            if min(ly_top, ly_bot, ry_top, ry_bot) > h:
                break

            upper_line = create_line(ly_top, ry_top)
            lower_line = create_line(ly_bot, ry_bot, True)

            region = QPainterPath()
            region.moveTo(0, ly_top)
            region.connectPath(upper_line)
            region.lineTo(w, ry_bot)
            region.connectPath(lower_line)
            region.closeSubpath()

            painter.fillPath(region, left.diff_backgrounds[kind])
            for path, aa in zip((upper_line, lower_line),
                                (ly_top != ry_top, ly_bot != ry_bot)):
                lines.append((kind, path, aa))

        for kind, path, aa in sorted(
                lines, key=lambda x: {'replace': 0}.get(x[0], 1)):
            painter.setPen(left.diff_foregrounds[kind])
            painter.setRenderHints(QPainter.Antialiasing, aa)
            painter.drawPath(path)

        painter.setFont(left.heading_font)
        for (lnum, text), (rnum, text) in zip(left.headers, right.headers):
            ltop, lbot, rtop, rbot = lnum, lnum + 3, rnum, rnum + 3
            if lbot < lfv and rbot < rfv:
                continue
            ly_top = left.blockBoundingGeometry(
                ldoc.findBlockByNumber(ltop)).translated(lorigin).y()
            ly_bot = left.blockBoundingGeometry(
                ldoc.findBlockByNumber(lbot)).translated(lorigin).y()
            ry_top = right.blockBoundingGeometry(
                rdoc.findBlockByNumber(rtop)).translated(rorigin).y()
            ry_bot = right.blockBoundingGeometry(
                rdoc.findBlockByNumber(rbot)).translated(rorigin).y()
            if max(ly_top, ly_bot, ry_top, ry_bot) < 0:
                continue
            if min(ly_top, ly_bot, ry_top, ry_bot) > h:
                break
            ly = painter.boundingRect(3, ly_top, left.width(),
                                      ly_bot - ly_top - 5, Qt.TextSingleLine,
                                      text).bottom() + 3
            ry = painter.boundingRect(3, ry_top, right.width(),
                                      ry_bot - ry_top - 5, Qt.TextSingleLine,
                                      text).bottom() + 3
            line = create_line(ly, ry)
            painter.setPen(QPen(left.palette().text(), 2))
            painter.setRenderHints(QPainter.Antialiasing, ly != ry)
            painter.drawPath(line)

        painter.end()
        # Paint the splitter without the change lines if the mouse is over the
        # splitter
        if getattr(self, 'hover', False):
            QSplitterHandle.paintEvent(self, event)
コード例 #36
0
ファイル: Controller.py プロジェクト: ska-sa/tigger
    def __init__(self, image, parent, imgman, name=None, save=False):
        QFrame.__init__(self, parent)
        self.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
        # init state
        self.image = image
        self._imgman = imgman
        self._currier = PersistentCurrier()
        self._control_dialog = None
        # create widgets
        self._lo = lo = QHBoxLayout(self)
        lo.setContentsMargins(0, 0, 0, 0)
        lo.setSpacing(2)
        # raise button
        self._wraise = QToolButton(self)
        lo.addWidget(self._wraise)
        self._wraise.setIcon(pixmaps.raise_up.icon())
        self._wraise.setAutoRaise(True)
        self._can_raise = False
        QObject.connect(self._wraise, SIGNAL("clicked()"), self._raiseButtonPressed)
        self._wraise.setToolTip("""<P>Click here to raise this image above other images. Hold the button down briefly to
      show a menu of image operations.</P>""")
        # center label
        self._wcenter = QLabel(self)
        self._wcenter.setPixmap(pixmaps.center_image.pm())
        self._wcenter.setToolTip(
            "<P>The plot is currently centered on (the reference pixel %d,%d) of this image.</P>" % self.image.referencePixel())
        lo.addWidget(self._wcenter)
        # name/filename label
        self.name = image.name
        self._wlabel = QLabel(self.name, self)
        self._number = 0
        self.setName(self.name)
        self._wlabel.setToolTip("%s %s" % (image.filename, "\u00D7".join(map(str, image.data().shape))))
        lo.addWidget(self._wlabel, 1)
        # if 'save' is specified, create a "save" button
        if save:
            self._wsave = QToolButton(self)
            lo.addWidget(self._wsave)
            self._wsave.setText("save")
            self._wsave.setAutoRaise(True)
            self._save_dir = save if isinstance(save, str) else "."
            QObject.connect(self._wsave, SIGNAL("clicked()"), self._saveImage)
            self._wsave.setToolTip("""<P>Click here to write this image to a FITS file.</P>""")
        # render control
        dprint(2, "creating RenderControl")
        self._rc = RenderControl(image, self)
        dprint(2, "done")
        # selectors for extra axes
        self._wslicers = []
        curslice = self._rc.currentSlice();  # this may be loaded from config, so not necessarily 0
        for iextra, axisname, labels in self._rc.slicedAxes():
            if axisname.upper() not in ["STOKES", "COMPLEX"]:
                lbl = QLabel("%s:" % axisname, self)
                lo.addWidget(lbl)
            else:
                lbl = None
            slicer = QComboBox(self)
            self._wslicers.append(slicer)
            lo.addWidget(slicer)
            slicer.addItems(labels)
            slicer.setToolTip("""<P>Selects current slice along the %s axis.</P>""" % axisname)
            slicer.setCurrentIndex(curslice[iextra])
            QObject.connect(slicer, SIGNAL("activated(int)"), self._currier.curry(self._rc.changeSlice, iextra))
        # min/max display ranges
        lo.addSpacing(5)
        self._wrangelbl = QLabel(self)
        lo.addWidget(self._wrangelbl)
        self._minmaxvalidator = FloatValidator(self)
        self._wmin = QLineEdit(self)
        self._wmax = QLineEdit(self)
        width = self._wmin.fontMetrics().width("1.234567e-05")
        for w in self._wmin, self._wmax:
            lo.addWidget(w, 0)
            w.setValidator(self._minmaxvalidator)
            w.setMaximumWidth(width)
            w.setMinimumWidth(width)
            QObject.connect(w, SIGNAL("editingFinished()"), self._changeDisplayRange)
        # full-range button
        self._wfullrange = QToolButton(self)
        lo.addWidget(self._wfullrange, 0)
        self._wfullrange.setIcon(pixmaps.zoom_range.icon())
        self._wfullrange.setAutoRaise(True)
        QObject.connect(self._wfullrange, SIGNAL("clicked()"), self.renderControl().resetSubsetDisplayRange)
        rangemenu = QMenu(self)
        rangemenu.addAction(pixmaps.full_range.icon(), "Full subset", self.renderControl().resetSubsetDisplayRange)
        for percent in (99.99, 99.9, 99.5, 99, 98, 95):
            rangemenu.addAction("%g%%" % percent, self._currier.curry(self._changeDisplayRangeToPercent, percent))
        self._wfullrange.setPopupMode(QToolButton.DelayedPopup)
        self._wfullrange.setMenu(rangemenu)
        # update widgets from current display range
        self._updateDisplayRange(*self._rc.displayRange())
        # lock button
        self._wlock = QToolButton(self)
        self._wlock.setIcon(pixmaps.unlocked.icon())
        self._wlock.setAutoRaise(True)
        self._wlock.setToolTip("""<P>Click to lock or unlock the intensity range. When the intensity range is locked across multiple images, any changes in the intensity
          range of one are propagated to the others. Hold the button down briefly for additional options.</P>""")
        lo.addWidget(self._wlock)
        QObject.connect(self._wlock, SIGNAL("clicked()"), self._toggleDisplayRangeLock)
        QObject.connect(self.renderControl(), SIGNAL("displayRangeLocked"), self._setDisplayRangeLock)
        QObject.connect(self.renderControl(), SIGNAL("dataSubsetChanged"), self._dataSubsetChanged)
        lockmenu = QMenu(self)
        lockmenu.addAction(pixmaps.locked.icon(), "Lock all to this",
                           self._currier.curry(imgman.lockAllDisplayRanges, self.renderControl()))
        lockmenu.addAction(pixmaps.unlocked.icon(), "Unlock all", imgman.unlockAllDisplayRanges)
        self._wlock.setPopupMode(QToolButton.DelayedPopup)
        self._wlock.setMenu(lockmenu)
        self._setDisplayRangeLock(self.renderControl().isDisplayRangeLocked())
        # dialog button
        self._wshowdialog = QToolButton(self)
        lo.addWidget(self._wshowdialog)
        self._wshowdialog.setIcon(pixmaps.colours.icon())
        self._wshowdialog.setAutoRaise(True)
        self._wshowdialog.setToolTip("""<P>Click for colourmap and intensity policy options.</P>""")
        QObject.connect(self._wshowdialog, SIGNAL("clicked()"), self.showRenderControls)
        tooltip = """<P>You can change the currently displayed intensity range by entering low and high limits here.</P>
    <TABLE>
      <TR><TD><NOBR>Image min:</NOBR></TD><TD>%g</TD><TD>max:</TD><TD>%g</TD></TR>
      </TABLE>""" % self.image.imageMinMax()
        for w in self._wmin, self._wmax, self._wrangelbl:
            w.setToolTip(tooltip)

        # create image operations menu
        self._menu = QMenu(self.name, self)
        self._qa_raise = self._menu.addAction(pixmaps.raise_up.icon(), "Raise image",
                                              self._currier.curry(self.image.emit, SIGNAL("raise")))
        self._qa_center = self._menu.addAction(pixmaps.center_image.icon(), "Center plot on image",
                                               self._currier.curry(self.image.emit, SIGNAL("center")))
        self._qa_show_rc = self._menu.addAction(pixmaps.colours.icon(), "Colours && Intensities...",
                                                self.showRenderControls)
        if save:
            self._qa_save = self._menu.addAction("Save image...", self._saveImage)
        self._menu.addAction("Export image to PNG file...", self._exportImageToPNG)
        self._export_png_dialog = None
        self._menu.addAction("Unload image", self._currier.curry(self.image.emit, SIGNAL("unload")))
        self._wraise.setMenu(self._menu)
        self._wraise.setPopupMode(QToolButton.DelayedPopup)

        # connect updates from renderControl and image
        self.image.connect(SIGNAL("slice"), self._updateImageSlice)
        QObject.connect(self._rc, SIGNAL("displayRangeChanged"), self._updateDisplayRange)

        # default plot depth of image markers
        self._z_markers = None
        # and the markers themselves
        self._image_border = QwtPlotCurve()
        self._image_label = QwtPlotMarker()

        # subset markers
        self._subset_pen = QPen(QColor("Light Blue"))
        self._subset_border = QwtPlotCurve()
        self._subset_border.setPen(self._subset_pen)
        self._subset_border.setVisible(False)
        self._subset_label = QwtPlotMarker()
        text = QwtText("subset")
        text.setColor(self._subset_pen.color())
        self._subset_label.setLabel(text)
        self._subset_label.setLabelAlignment(Qt.AlignRight | Qt.AlignBottom)
        self._subset_label.setVisible(False)
        self._setting_lmrect = False

        self._all_markers = [self._image_border, self._image_label, self._subset_border, self._subset_label]
コード例 #37
0
ファイル: ControlDialog.py プロジェクト: ska-sa/tigger
 def _setupHistogramPlot(self):
     self._histplot.setCanvasBackground(QColor("lightgray"))
     self._histplot.setAxisFont(QwtPlot.yLeft, QApplication.font())
     self._histplot.setAxisFont(QwtPlot.xBottom, QApplication.font())
     # add histogram curves
     self._histcurve1 = TiggerPlotCurve()
     self._histcurve2 = TiggerPlotCurve()
     self._histcurve1.setStyle(QwtPlotCurve.Steps)
     self._histcurve2.setStyle(QwtPlotCurve.Steps)
     self._histcurve1.setPen(QPen(Qt.NoPen))
     self._histcurve1.setBrush(QBrush(QColor("slategrey")))
     pen = QPen(QColor("red"))
     pen.setWidth(1)
     self._histcurve2.setPen(pen)
     self._histcurve1.setZ(0)
     self._histcurve2.setZ(100)
     #    self._histcurve1.attach(self._histplot)
     self._histcurve2.attach(self._histplot)
     # add maxbin and half-max curves
     self._line_0 = self.HistogramLineMarker(self._histplot, color="grey50", linestyle=Qt.SolidLine,
                                             align=Qt.AlignTop | Qt.AlignLeft, z=90)
     self._line_mean = self.HistogramLineMarker(self._histplot, color="black", linestyle=Qt.SolidLine,
                                                align=Qt.AlignBottom | Qt.AlignRight, z=91,
                                                label="mean", zlabel=151)
     self._line_std = self.HistogramLineMarker(self._histplot, color="black", linestyle=Qt.SolidLine,
                                               align=Qt.AlignTop | Qt.AlignRight, z=91,
                                               label="std", zlabel=151)
     sym = QwtSymbol()
     sym.setStyle(QwtSymbol.VLine)
     sym.setSize(8)
     self._line_std.line.setSymbol(sym)
     self._line_maxbin = self.HistogramLineMarker(self._histplot, color="green", linestyle=Qt.DotLine,
                                                  align=Qt.AlignTop | Qt.AlignRight, z=92,
                                                  label="max bin", zlabel=150)
     self._line_halfmax = self.HistogramLineMarker(self._histplot, color="green", linestyle=Qt.DotLine,
                                                   align=Qt.AlignBottom | Qt.AlignRight, z=90,
                                                   label="half-max", yaxis=QwtPlot.yLeft)
     # add current range
     self._rangebox = TiggerPlotCurve()
     self._rangebox.setStyle(QwtPlotCurve.Steps)
     self._rangebox.setYAxis(QwtPlot.yRight)
     self._rangebox.setPen(QPen(Qt.NoPen))
     self._rangebox.setBrush(QBrush(QColor("darkgray")))
     self._rangebox.setZ(50)
     self._rangebox.attach(self._histplot)
     self._rangebox2 = TiggerPlotCurve()
     self._rangebox2.setStyle(QwtPlotCurve.Sticks)
     self._rangebox2.setYAxis(QwtPlot.yRight)
     self._rangebox2.setZ(60)
     #  self._rangebox2.attach(self._histplot)
     # add intensity transfer function
     self._itfcurve = TiggerPlotCurve()
     self._itfcurve.setStyle(QwtPlotCurve.Lines)
     self._itfcurve.setPen(QPen(QColor("blue")))
     self._itfcurve.setYAxis(QwtPlot.yRight)
     self._itfcurve.setZ(120)
     self._itfcurve.attach(self._histplot)
     self._itfmarker = TiggerPlotMarker()
     label = QwtText("ITF")
     label.setColor(QColor("blue"))
     self._itfmarker.setLabel(label)
     try:
         self._itfmarker.setSpacing(0)
     except AttributeError:
         pass
     self._itfmarker.setLabelAlignment(Qt.AlignTop | Qt.AlignRight)
     self._itfmarker.setZ(120)
     self._itfmarker.attach(self._histplot)
     # add colorbar
     self._cb_item = self.ColorBarPlotItem(1, 1 + self.ColorBarHeight)
     self._cb_item.setYAxis(QwtPlot.yRight)
     self._cb_item.attach(self._histplot)
     # add pickers
     self._hist_minpicker = self.HistLimitPicker(self._histplot, "low: %(x).4g")
     self._hist_minpicker.setMousePattern(QwtEventPattern.MouseSelect1, Qt.LeftButton)
     QObject.connect(self._hist_minpicker, SIGNAL("selected(const QwtDoublePoint &)"), self._selectLowLimit)
     self._hist_maxpicker = self.HistLimitPicker(self._histplot, "high: %(x).4g")
     self._hist_maxpicker.setMousePattern(QwtEventPattern.MouseSelect1, Qt.RightButton)
     QObject.connect(self._hist_maxpicker, SIGNAL("selected(const QwtDoublePoint &)"), self._selectHighLimit)
     self._hist_maxpicker1 = self.HistLimitPicker(self._histplot, "high: %(x).4g")
     self._hist_maxpicker1.setMousePattern(QwtEventPattern.MouseSelect1, Qt.LeftButton, Qt.CTRL)
     QObject.connect(self._hist_maxpicker1, SIGNAL("selected(const QwtDoublePoint &)"), self._selectHighLimit)
     self._hist_zoompicker = self.HistLimitPicker(self._histplot, label="zoom",
                                                  tracker_mode=QwtPicker.AlwaysOn, track=self._trackHistCoordinates,
                                                  color="black",
                                                  mode=QwtPicker.RectSelection,
                                                  rubber_band=QwtPicker.RectRubberBand)
     self._hist_zoompicker.setMousePattern(QwtEventPattern.MouseSelect1, Qt.LeftButton, Qt.SHIFT)
     QObject.connect(self._hist_zoompicker, SIGNAL("selected(const QwtDoubleRect &)"), self._zoomHistogramIntoRect)
コード例 #38
0
 def initJoystickGraphics(self):
     # Pens
     self.cyan_pen = QPen(QColor(0, 255, 255))
     self.magenta_pen = QPen(QColor(255, 0, 255))
     self.red_pen = QPen(QColor(255, 0, 0))
     self.cyan_pen.setWidth(3)
     self.magenta_pen.setWidth(3)
     self.red_pen.setWidth(3)
     self.stick_ind_l = QGraphicsEllipseItem()
     self.stick_ind_r = QGraphicsEllipseItem()
     self.stick_line_l = QGraphicsLineItem()
     self.stick_line_r = QGraphicsLineItem()
     self.mode_ind = QGraphicsLineItem()
     
     # Left joystick indicator circle
     px_l = self.stick_ind_lox - self.stick_ind_radius
     py_l = self.stick_ind_loy - self.stick_ind_radius
     self.stick_ind_l.setRect(px_l, py_l, 2 * self.stick_ind_radius, 2 * self.stick_ind_radius)
     self.stick_ind_l.setBrush(QBrush(QColor(255, 0, 0)))
     self.stick_ind_l.setPen(QPen(QColor(0, 0, 0)))  
     
     # Right joystick indicator circle
     px_r = self.stick_ind_rox - self.stick_ind_radius
     py_r = self.stick_ind_roy - self.stick_ind_radius
     self.stick_ind_r.setRect(px_r, py_r, 2 * self.stick_ind_radius, 2 * self.stick_ind_radius)
     self.stick_ind_r.setBrush(QBrush(QColor(255, 0, 0)))
     self.stick_ind_r.setPen(QPen(QColor(0, 0, 0)))
     
     # Left joystick indicator line
     line_pen = QPen(QColor(255,0,0))
     line_pen.setWidth(4)
     self.stick_line_l.setLine(self.stick_ind_lox, self.stick_ind_loy, self.stick_ind_lox, self.stick_ind_loy)
     self.stick_line_l.setPen(line_pen)
     
     # Right joystick indicator line
     self.stick_line_r.setLine(self.stick_ind_rox, self.stick_ind_roy, self.stick_ind_rox, self.stick_ind_roy)
     self.stick_line_r.setPen(line_pen) 
     
     # Mode indicator line
     self.mode_ind.setLine(self.mode_ind_x1, self.mode_ind_y1, self.mode_ind_x2, self.mode_ind_y2)
     self.mode_ind.setPen(self.cyan_pen)
     
     # Joystick power indicator
     self.joystick_power_ind = []
     self.joystick_power_ind.append(QGraphicsLineItem(self.power_ind_x1, self.power_ind_y + 20, self.power_ind_x1, self.power_ind_y - 20))
     self.joystick_power_ind.append(QGraphicsLineItem(self.power_ind_x1, self.power_ind_y - 20, self.power_ind_x1 + 50, self.power_ind_y - 20))
     self.joystick_power_ind.append(QGraphicsLineItem(self.power_ind_x1+50, self.power_ind_y - 20, self.power_ind_x1+50, self.power_ind_y + 20))
     self.joystick_power_ind.append(QGraphicsLineItem(self.power_ind_x1+50, self.power_ind_y + 20, self.power_ind_x1, self.power_ind_y + 20))
     
     # Populate scene
     graphics_scene = QGraphicsScene()
     graphics_scene.addItem(self.stick_ind_l)
     graphics_scene.addItem(self.stick_ind_r)
     graphics_scene.addItem(self.stick_line_l)
     graphics_scene.addItem(self.stick_line_r)
     graphics_scene.addItem(self.mode_ind)
     for l in self.joystick_power_ind:
         l.setPen(self.red_pen)
         graphics_scene.addItem(l)
     graphics_scene.setSceneRect(0, 0, self._widget.joystickGraphicsView.width() - 4, self._widget.joystickGraphicsView.height() - 4)
     self._widget.joystickGraphicsView.setScene(graphics_scene)
     self._widget.joystickGraphicsView.setBackgroundBrush(QBrush(QImage(os.path.join(rospkg.RosPack().get_path('mobility_base_tools'), 'images', 'dx6ilabels.jpg'))))
     self._widget.joystickGraphicsView.show()
コード例 #39
0
class DiagnosticGui(Plugin):
    
    last_suppress_time = Time()
    last_twist_time = Time()
    gui_update_timer = QTimer()
    
    # Raw joystick data    
    joystick_data = []
    joystick_table_vals = []
    joystick_channel_text = ['CHAN_ENABLE: ', 'CHAN_ROTATE: ', 'CHAN_FORWARD: ', 'CHAN_LATERAL: ', 'CHAN_MODE: ', 'CHAN_EXTRA: ']
    joystick_bind_status = False
    joystick_bind_dot_counter = 0
    
    # Mode
    current_mode = -1
    
    # Topic pub timeouts    
    JOYSTICK_SUPPRESS_PERIOD = 0.2 # 5 Hz
    CMD_VEL_TIMEOUT_PERIOD = 0.2 # 5 Hz    
    joystick_suppressed = False
    command_received = False
    current_cmd = Twist()
    battery_percent = 0
    battery_voltage = 0
    
    # Checklist icons
    bad_icon = QPixmap()
    good_icon = QPixmap()
    none_icon = QPixmap()
    
    # Checklist status
    GOOD = 0
    BAD = 1
    NONE = 2
    
    # Checklist variables
    checklist_status = []
    
    BATT_MAN = 0
    ESTOP_MAN = 1
    DISABLE_MAN = 2
    JOYSTICK_MAN = 3
    SUPPRESS_MAN = 4    
    BATT_COMP = 5
    ESTOP_COMP = 6
    DISABLE_COMP = 7
    JOYSTICK_COMP = 8
    SUPPRESS_COMP = 9
    CMD_COMP = 10
    
    # Bumpers
    bumper_front_left = 0
    bumper_front_right = 0
    bumper_rear_left = 0
    bumper_rear_right = 0
    
    # Gyro cal
    gyro_cal_status = False
    gyro_x = 0.0
    gyro_y = 0.0
    gyro_z = 0.0
    cal_enabled = True
    cal_time = rospy.Time(0)
    
    # Max speed config
    max_speed_known = False
    max_speed_dirty = True
    max_linear_actual = 0.0
    max_angular_actual = 0.0
    max_linear_setting = 0.0
    max_angular_setting = 0.0
    
    # Wake time
    current_wake_time = rospy.Time(0)
    rel_wake_days = 0
    rel_wake_hours = 0
    rel_wake_minutes = 0
    rel_wake_secs = 0
    
    # Switching between tabs and full GUI
    is_currently_tab = False
    widget_count = 0
    current_tab_idx = -1
    raw_data_tab_idx = 5
    
    # Check connection to base
    base_connected = False
    last_joystick_time = rospy.Time(0)
    
    # Constants    
    stick_ind_lox = 80
    stick_ind_loy = 136
    stick_ind_rox = 286
    stick_ind_roy = 135
    stick_ind_range_pix = 88.0
    stick_ind_range_max = JoystickRaw.MAX
    stick_ind_range_min = JoystickRaw.MIN
    stick_ind_range_mid = JoystickRaw.CENTER
    stick_ind_range_factor = stick_ind_range_pix / (stick_ind_range_max - stick_ind_range_min)
    stick_ind_radius = 7    
    mode_ind_x1 = 52
    mode_ind_y1 = 37
    mode_ind_x2 = 44
    mode_ind_y2 = 13
    power_ind_x1 = 160
    power_ind_x2 = 206
    power_ind_y = 213    
    bumper_fl_x = 70
    bumper_fl_y = 60
    bumper_fr_x = 293
    bumper_fr_y = 60
    bumper_rl_x = 70
    bumper_rl_y = 282
    bumper_rr_x = 293
    bumper_rr_y = 282
    bumper_dx = 62
    bumper_dy = 54    
    joystick_table_left_edge = 440
    joystick_table_top_edge = 525    
    twist_table_left_edge = 700
    twist_table_top_edge = 580    
    battery_table_left_edge = 700
    battery_table_top_edge = 730
    
    def __init__(self, context):
        # Qt setup
        self.context_ = context
        self.initGui('full')      
        
        # ROS setup
        topic_timeout_timer = rospy.Timer(rospy.Duration(0.02), self.topicTimeoutCallback)
        self.subscribeTopics()
        self.advertiseTopics()
        
    def initGui(self, gui_type):
        if gui_type == 'full':
            self.spawnFullGui()
            self.initTables(self._widget, self.joystick_table_left_edge, self.joystick_table_top_edge) 
        else:
            self.spawnTabGui()
            self.initTables(self._widget.gui_tabs.widget(self.raw_data_tab_idx), 20, 20) 
            self._widget.gui_tabs.setCurrentIndex(self.current_tab_idx)
            
        self.resetGuiTimer()            
        self.initJoystickGraphics()
        self.initBumperGraphics()
        self.initChecklists()
        self.bindCallbacks()
        self.refreshMaxSpeed()
        
        # Initialize absolute wake time setter to current time
        datetime_now = QDateTime(QDate.currentDate(), QTime.currentTime())
        self._widget.absolute_wake_time_obj.setDateTime(datetime_now)
        temp_time = self._widget.absolute_wake_time_obj.time()
        temp_time = QTime(temp_time.hour(), temp_time.minute())
        self._widget.absolute_wake_time_obj.setTime(temp_time)
        
        # Set connection label text
        if self.base_connected:
            self._widget.disconnected_lbl.setVisible(False)
        else:
            self._widget.disconnected_lbl.setVisible(True)
            self._widget.disconnected_lbl.setText('<font color=#FF0000>NOT CONNECTED</font>')

    def topicTimeoutCallback(self, event):
        # Joystick suppression
        if (event.current_real - self.last_suppress_time).to_sec() < self.JOYSTICK_SUPPRESS_PERIOD and self.suppress_dt.to_sec() <= 1.0/9.0:
            self.joystick_suppressed = True
        else:
            self.joystick_suppressed = False
            
        # Command message
        if (event.current_real - self.last_twist_time).to_sec() < self.CMD_VEL_TIMEOUT_PERIOD and self.twist_dt.to_sec() <= 1.0/6.0:
            self.command_received = True
        else:
            self.command_received = False

    def initChecklists(self):
        self.bad_icon.load(os.path.join(rospkg.RosPack().get_path('mobility_base_tools'), 'images', 'bad.png'))
        self.good_icon.load(os.path.join(rospkg.RosPack().get_path('mobility_base_tools'), 'images', 'good.png'))
        self.none_icon.load(os.path.join(rospkg.RosPack().get_path('mobility_base_tools'), 'images', 'none.png'))        
        self.checklist_status=[0 for i in range(self.CMD_COMP + 1)]
        self.checklist_status[self.BATT_MAN] = self.NONE
        self.checklist_status[self.ESTOP_MAN] = self.NONE
        self.checklist_status[self.DISABLE_MAN] = self.NONE
        self.checklist_status[self.JOYSTICK_MAN] = self.NONE
        self.checklist_status[self.SUPPRESS_MAN] = self.NONE        
        self.checklist_status[self.BATT_COMP] = self.NONE
        self.checklist_status[self.ESTOP_COMP] = self.NONE
        self.checklist_status[self.DISABLE_COMP] = self.NONE
        self.checklist_status[self.JOYSTICK_COMP] = self.NONE
        self.checklist_status[self.SUPPRESS_COMP] = self.NONE
        self.checklist_status[self.CMD_COMP] = self.NONE

    def initTabTables(self):
        self.joystick_table_vals = [QLabel(self._widget.gui_tabs.widget(self.raw_data_tab_idx)) for i in range(ChannelIndex.CHAN_EXTRA+1)]
        self.joystick_table_labels = [QLabel(self._widget.gui_tabs.widget(self.raw_data_tab_idx)) for i in range(ChannelIndex.CHAN_EXTRA+1)]
        self.joystick_table_heading = QLabel(self._widget.gui_tabs.widget(self.raw_data_tab_idx))
        

    def initTables(self, widget, left, top):
        # Joystick data table
        self.joystick_data = [0 for i in range(ChannelIndex.CHAN_EXTRA+1)]
        self.joystick_table_vals = [QLabel(widget) for i in range(ChannelIndex.CHAN_EXTRA+1)]
        self.joystick_table_labels = [QLabel(widget) for i in range(ChannelIndex.CHAN_EXTRA+1)]
        self.joystick_table_heading = QLabel(widget)
        
        self.joystick_table_heading.setText('Raw Joystick Data')
        self.joystick_table_heading.setFont(QFont('Ubuntu', 11, QFont.Bold))
        self.joystick_table_heading.move(left, top)
        for i in range(len(self.joystick_table_vals)):
            self.joystick_table_vals[i].move(left + 150, top + 30 * (i+1))
            self.joystick_table_vals[i].setText('0000')
            self.joystick_table_vals[i].setFixedWidth(200)
            
            self.joystick_table_labels[i].move(left, top + 30 * (i+1))
            self.joystick_table_labels[i].setText(self.joystick_channel_text[i])
            
        # Twist data table
        self.twist_table_heading = QLabel(widget)
        self.twist_table_heading.setText('Current Twist Command')
        self.twist_table_heading.setFont(QFont('Ubuntu', 11, QFont.Bold))
        self.twist_table_heading.move(left + 260, top)
        self.twist_table_labels = [QLabel(widget) for i in range(0, 3)]
        self.twist_table_vals = [QLabel(widget) for i in range(0, 3)]
        for i in range(len(self.twist_table_vals)):
            self.twist_table_vals[i].move(left + 260 + 150, top + 30 * (i+1))
            self.twist_table_vals[i].setText('Not Published')
            self.twist_table_vals[i].setFixedWidth(200)
            self.twist_table_labels[i].move(left + 260, top + 30 * (i+1))
            
        self.twist_table_labels[0].setText('Forward (m/s):')
        self.twist_table_labels[1].setText('Lateral (m/s):')
        self.twist_table_labels[2].setText('Rotation (rad/s):')
        
        # Battery percentage
        self.battery_heading = QLabel(widget)
        self.battery_heading.setText('Current Battery State')
        self.battery_heading.setFont(QFont('Ubuntu', 11, QFont.Bold))
        self.battery_heading.move(left + 260, top + 150)
        self.battery_label = QLabel(widget)
        self.battery_label.move(left + 260, top + 150 +30)
        self.battery_label.setText('000 %')
        self.battery_voltage_label = QLabel(widget)
        self.battery_voltage_label.move(left + 260, top + 150 +60)
        self.battery_voltage_label.setText('00.00 V')
        self.battery_voltage_label.setFixedWidth(200)
        
        # Mode
        self.mode_heading = QLabel(widget)
        self.mode_heading.setFont(QFont('Ubuntu', 11, QFont.Bold))
        self.mode_heading.move(left, top + 225)
        self.mode_heading.setText('Current Mode')
        self.mode_label = QLabel(widget)
        self.mode_label.move(left + 120, top + 225)        
        self.mode_label.setText('XXXXXXXXXXXXXXXXXXXXXX')

    def bindCallbacks(self):
        self._widget.start_bind_btn.clicked.connect(self.startBind)
        self._widget.stop_bind_btn.clicked.connect(self.stopBind)
        
        self._widget.gyro_cal_btn.clicked.connect(self.calGyro)
        self._widget.clear_cal_btn.clicked.connect(self.clearCal)
        
        self._widget.max_linear_txt.editingFinished.connect(self.maxLinearChanged)
        self._widget.max_angular_txt.editingFinished.connect(self.maxAngularChanged)
        self._widget.set_speed_btn.clicked.connect(self.setMaxSpeed)
        self._widget.clear_speed_btn.clicked.connect(self.clearMaxSpeed)
        
        self._widget.wake_time_days_txt.editingFinished.connect(self.wakeDaysChanged)
        self._widget.wake_time_hours_txt.editingFinished.connect(self.wakeHoursChanged)
        self._widget.wake_time_minutes_txt.editingFinished.connect(self.wakeMinutesChanged)
        self._widget.wake_time_secs_txt.editingFinished.connect(self.wakeSecsChanged)
        self._widget.set_relative_wake_time_btn.clicked.connect(self.setRelativeWakeTime)        
        self._widget.set_absolute_wake_time_btn.clicked.connect(self.setAbsoluteWakeTime)
        self._widget.clear_wake_time_btn.clicked.connect(self.clearWakeTime)
        
        if self.is_currently_tab:
            self._widget.gui_tabs.currentChanged.connect(self.setCurrentTab)
        
    def setCurrentTab(self, idx):
        self.current_tab_idx = self._widget.gui_tabs.currentIndex()
        
    def startBind(self):
        self.pub_start_bind.publish(std_msgs.msg.Empty())
        
    def stopBind(self):
        self.pub_stop_bind.publish(std_msgs.msg.Empty())
        
    def calGyro(self):
        gyro_cal_srv = rospy.ServiceProxy('/mobility_base/imu/calibrate', std_srvs.srv.Empty)
        try:
            gyro_cal_srv()
            self.cal_enabled = False
            self.cal_time = rospy.Time.now()
        except:
            pass
 
    def clearCal(self):
        clear_cal_srv = rospy.ServiceProxy('/mobility_base/imu/clear_cal', std_srvs.srv.Empty)
        try:
            clear_cal_srv()
        except:
            pass
        
    def maxLinearChanged(self):
        try:
            float_val = float(self._widget.max_linear_txt.text())
            self.max_linear_setting = float_val;
        except ValueError:
            if self.max_linear_actual <= 0 or not isfinite(self.max_linear_actual):
                self.max_linear_setting = 0.0
            else:
                self.max_linear_setting = self.max_linear_actual
        self.max_speed_dirty = True
        
    def maxAngularChanged(self):
        try:
            float_val = float(self._widget.max_angular_txt.text())
            self.max_angular_setting = float_val;
        except ValueError:
            if self.max_angular_actual <= 0 or not isfinite(self.max_angular_actual):
                self.max_angular_setting = 0.0
            else:
                self.max_angular_setting = self.max_angular_actual
        self.max_speed_dirty = True
        
    def setMaxSpeed(self):
        set_max_speed_srv = rospy.ServiceProxy('/mobility_base/set_max_speed', SetMaxSpeed)
        req = SetMaxSpeedRequest()
        req.linear = self.max_linear_setting
        req.angular = self.max_angular_setting
        try:
            set_max_speed_srv(req)
            self.max_speed_known = False
        except:
            pass
        
    def clearMaxSpeed(self):
        set_max_speed_srv = rospy.ServiceProxy('/mobility_base/set_max_speed', SetMaxSpeed)
        req = SetMaxSpeedRequest()
        req.linear = float('nan')
        req.angular = float('nan')
        try:
            set_max_speed_srv(req)
            self.max_speed_known = False
        except:
            pass

    def wakeDaysChanged(self):
        try:
            self.rel_wake_days = float(self._widget.wake_time_days_txt.text())
        except:
            self._widget.wake_time_days_txt.setText(str(self.rel_wake_days))
                        
    def wakeHoursChanged(self):
        try:
            self.rel_wake_hours = float(self._widget.wake_time_hours_txt.text())
        except:
            self._widget.wake_time_hours_txt.setText(str(self.rel_wake_hours))
            
    def wakeMinutesChanged(self):
        try:
            self.rel_wake_minutes = float(self._widget.wake_time_minutes_txt.text())
        except:
            self._widget.wake_time_minutes_txt.setText(str(self.rel_wake_minutes)) 

    def wakeSecsChanged(self):
        try:
            self.rel_wake_secs = float(self._widget.wake_time_secs_txt.text())
        except:
            self._widget.wake_time_secs_txt.setText(str(self.rel_wake_secs)) 

    def setRelativeWakeTime(self):
        new_wake_time = std_msgs.msg.Time()
        rel_wake_time = 86400 * self.rel_wake_days + 3600 * self.rel_wake_hours + 60 * self.rel_wake_minutes + self.rel_wake_secs
        new_wake_time.data = rospy.Time.now() + rospy.Duration(rel_wake_time)
        self.pub_set_wake_time.publish(new_wake_time)
        
    def setAbsoluteWakeTime(self):
        self.pub_set_wake_time.publish(rospy.Time(self._widget.absolute_wake_time_obj.dateTime().toTime_t()))
        
    def clearWakeTime(self):
        self.pub_set_wake_time.publish(rospy.Time(0))
    
    def refreshMaxSpeed(self):
        self.max_speed_dirty = True
        self.max_speed_known = False
    
    def updateGuiCallback(self):
        
        # Switch between tabs and full GUI
        if self.is_currently_tab:
            if self._widget.height() > 830 and self._widget.width() > 1205:
                self.is_currently_tab = False
                self.context_.remove_widget(self._widget)
                self.initGui('full')
        else:
            if self._widget.height() < 810 or self._widget.width() < 1185:
                self.is_currently_tab = True
                self.context_.remove_widget(self._widget)
                self.initGui('tab')
        
        # Check connection to base
        if self.base_connected and (rospy.Time.now() - self.last_joystick_time).to_sec() > 1.0:
            self.base_connected = False
            self._widget.disconnected_lbl.setText('<font color=#FF0000>NOT CONNECTED</font>')
            self._widget.disconnected_lbl.setVisible(True)
        
        if not self.base_connected and (rospy.Time.now() - self.last_joystick_time).to_sec() < 1.0:
            self.base_connected = True
#             self._widget.disconnected_lbl.setText('')
            self._widget.disconnected_lbl.setVisible(False)
        
        # Update checklists
        self.updateChecklist();

        # Manage 5 second disable of gyro calibration button
        if not self.cal_enabled:
            if (rospy.Time.now() - self.cal_time).to_sec() > 5.0:
                self._widget.gyro_cal_btn.setEnabled(True)
                self._widget.gyro_cal_btn.setText('Calibrate')
                self.cal_enabled = True
            else:
                self._widget.gyro_cal_btn.setEnabled(False)
                self._widget.gyro_cal_btn.setText(str(5 - 0.1*floor(10*(rospy.Time.now() - self.cal_time).to_sec()))) 
                
        # Update joystick graphics
        if not self.checkJoystickValid():
            self.updateCheckStatus(self._widget.joystick_bind_chk, self.NONE)
            
            if not self.joystick_bind_status:
                self._widget.joystick_bind_lbl.setText('')

            
            for l in self.joystick_power_ind:
                l.setVisible(True)
            self.updateRightStickIndicator(self.stick_ind_range_mid, self.stick_ind_range_mid)
            self.updateLeftStickIndicator(self.stick_ind_range_mid, self.stick_ind_range_mid)
        else:
            self.updateCheckStatus(self._widget.joystick_bind_chk, self.GOOD)
            self._widget.joystick_bind_lbl.setText('Joystick bound')

            for l in self.joystick_power_ind:
                l.setVisible(False)
            self.updateRightStickIndicator(self.joystick_data[ChannelIndex.CHAN_LATERAL], self.joystick_data[ChannelIndex.CHAN_FORWARD])
            self.updateLeftStickIndicator(self.joystick_data[ChannelIndex.CHAN_ROTATE], self.joystick_data[ChannelIndex.CHAN_ENABLE])
        if self.joystick_data[ChannelIndex.CHAN_MODE] < self.stick_ind_range_mid:
            self.mode_ind.setPen(self.cyan_pen)
            self._widget.modeLabel.setText("0 (Computer)")
        else:
            self.mode_ind.setPen(self.magenta_pen)
            self._widget.modeLabel.setText("1 (Manual)")
        
        # Update joystick data table
        for i in range(len(self.joystick_table_vals)):
            self.joystick_table_vals[i].setText(str(self.joystick_data[i]))
            
        # Update twist data table
        if self.command_received:
            self.twist_table_vals[0].setText(str(0.01 * floor(100 * self.current_cmd.linear.x)))
            self.twist_table_vals[1].setText(str(0.01 * floor(100 * self.current_cmd.linear.y)))
            self.twist_table_vals[2].setText(str(0.01 * floor(100 * self.current_cmd.angular.z)))
        else:
            self.twist_table_vals[0].setText('Not Published')
            self.twist_table_vals[1].setText('Not Published')
            self.twist_table_vals[2].setText('Not Published')
            
        # Update battery percentage
        self.battery_label.setText(str(self.battery_percent) + ' %')
        self.battery_voltage_label.setText(str(0.01 * floor(100 * self.battery_voltage)) + ' V')
        
        # Update mode
        self.mode_label.setText(self.getModeString(self.current_mode))
        
        # Update bumper graphics
        self.bumperVisibleSwitch(BumperIndex.BUMPER_1F, self.bumper_front_left)
        self.bumperVisibleSwitch(BumperIndex.BUMPER_2F, self.bumper_front_right)
        self.bumperVisibleSwitch(BumperIndex.BUMPER_3F, self.bumper_rear_left)
        self.bumperVisibleSwitch(BumperIndex.BUMPER_4F, self.bumper_rear_right)
        self.bumper_state_labels[0].setPlainText(str(self.bumper_front_left))
        self.bumper_state_labels[1].setPlainText(str(self.bumper_front_right))
        self.bumper_state_labels[2].setPlainText(str(self.bumper_rear_left))
        self.bumper_state_labels[3].setPlainText(str(self.bumper_rear_right))
        
        # Update gyro cal graphics
        if self.gyro_cal_status:            
            self.updateCheckStatus(self._widget.gyro_cal_chk, self.GOOD)
            self._widget.gyro_cal_lbl.setText('Gyro calibrated')
        else:
            self.updateCheckStatus(self._widget.gyro_cal_chk, self.BAD)
            self._widget.gyro_cal_lbl.setText('Gyro NOT calibrated')
    
        self._widget.gyro_x_lbl.setText('x: ' + str(1e-5*floor(1e5*self.gyro_x)))
        self._widget.gyro_y_lbl.setText('y: ' + str(1e-5*floor(1e5*self.gyro_y)))
        self._widget.gyro_z_lbl.setText('z: ' + str(1e-5*floor(1e5*self.gyro_z)))
    
        # Update max speed configuration
        if not self.max_speed_known:
            service_name = '/mobility_base/get_max_speed'
            get_max_speed_srv = rospy.ServiceProxy(service_name, GetMaxSpeed)
            
            try:
                resp = get_max_speed_srv()
                self.max_speed_known = True
                self.max_linear_actual = resp.linear
                self.max_angular_actual = resp.angular
                
                if self.max_linear_actual <= 0 or not isfinite(self.max_linear_actual):
                    self._widget.max_linear_lbl.setText('Unlimited')
                else:
                    self._widget.max_linear_lbl.setText(str(1e-2*round(1e2*self.max_linear_actual)))
                
                if self.max_angular_actual <= 0 or not isfinite(self.max_angular_actual):
                    self._widget.max_angular_lbl.setText('Unlimited')
                else:
                    self._widget.max_angular_lbl.setText(str(1e-2*round(1e2*self.max_angular_actual)))

            except:
                pass
#                 print service_name + " doesn't exist"
                
        if self.max_speed_dirty:        
            self._widget.max_linear_txt.setText(str(self.max_linear_setting))
            self._widget.max_angular_txt.setText(str(self.max_angular_setting))
            self.max_speed_dirty = False
       
        # Wake time
        if self.current_wake_time == rospy.Time(0):
            self._widget.wake_time_lbl.setText('Not Set')
        else:
            self._widget.wake_time_lbl.setText(time.strftime('%m/%d/%Y,  %H:%M:%S', time.localtime(self.current_wake_time.to_sec())))
            
    def checkJoystickValid(self):
        return self.joystick_data[ChannelIndex.CHAN_FORWARD] > 0 or self.joystick_data[ChannelIndex.CHAN_LATERAL] > 0 or self.joystick_data[ChannelIndex.CHAN_ROTATE] > 0 or self.joystick_data[ChannelIndex.CHAN_MODE] > 0
            
    def getModeString(self, mode_num):
        if mode_num == Mode.MODE_ESTOP:
            return 'MODE_ESTOP'
        elif mode_num == Mode.MODE_DISABLED:
            return 'MODE_DISABLED'
        elif mode_num == Mode.MODE_BATTERY_LIMP_HOME:
            return 'MODE_BATTERY_LIMP_HOME'
        elif mode_num == Mode.MODE_BATTERY_CRITICAL:
            return 'MODE_BATTERY_CRITICAL'
        elif mode_num == Mode.MODE_WIRELESS:
            return 'MODE_WIRELESS'
        elif mode_num == Mode.MODE_TIMEOUT:
            return 'MODE_TIMEOUT'
        elif mode_num == Mode.MODE_VELOCITY:
            return 'MODE_VELOCITY'
        elif mode_num == Mode.MODE_VELOCITY_RAW:
            return 'MODE_VELOCITY_RAW'
        else:
            return ''
        
    def updateChecklist(self):
        if self.current_mode >= Mode.MODE_TIMEOUT:
            self.checklist_status[self.BATT_MAN] = self.GOOD
            self.checklist_status[self.ESTOP_MAN] = self.GOOD
            self.checklist_status[self.DISABLE_MAN] = self.GOOD
            self.checklist_status[self.JOYSTICK_MAN] = self.BAD
            self.checklist_status[self.BATT_COMP] = self.GOOD
            self.checklist_status[self.ESTOP_COMP] = self.GOOD
            self.checklist_status[self.DISABLE_COMP] = self.GOOD
            self.checklist_status[self.JOYSTICK_COMP] = self.GOOD
        elif self.current_mode == Mode.MODE_WIRELESS:
            self.checklist_status[self.BATT_MAN] = self.GOOD
            self.checklist_status[self.ESTOP_MAN] = self.GOOD
            self.checklist_status[self.DISABLE_MAN] = self.GOOD
            self.checklist_status[self.JOYSTICK_MAN] = self.GOOD
            self.checklist_status[self.BATT_COMP] = self.GOOD
            self.checklist_status[self.ESTOP_COMP] = self.GOOD
            self.checklist_status[self.DISABLE_COMP] = self.GOOD
            self.checklist_status[self.JOYSTICK_COMP] = self.BAD
        elif self.current_mode == Mode.MODE_DISABLED:
            self.checklist_status[self.BATT_MAN] = self.NONE
            self.checklist_status[self.ESTOP_MAN] = self.GOOD
            self.checklist_status[self.DISABLE_MAN] = self.BAD
            self.checklist_status[self.JOYSTICK_MAN] = self.NONE
            self.checklist_status[self.BATT_COMP] = self.NONE
            self.checklist_status[self.ESTOP_COMP] = self.GOOD
            self.checklist_status[self.DISABLE_COMP] = self.BAD
            self.checklist_status[self.JOYSTICK_COMP] = self.NONE
        elif self.current_mode == Mode.MODE_ESTOP:
            self.checklist_status[self.BATT_MAN] = self.NONE
            self.checklist_status[self.ESTOP_MAN] = self.BAD
            self.checklist_status[self.DISABLE_MAN] = self.NONE
            self.checklist_status[self.JOYSTICK_MAN] = self.NONE
            self.checklist_status[self.BATT_COMP] = self.NONE
            self.checklist_status[self.ESTOP_COMP] = self.BAD
            self.checklist_status[self.DISABLE_COMP] = self.NONE
            self.checklist_status[self.JOYSTICK_COMP] = self.NONE
        elif self.current_mode == Mode.MODE_BATTERY_CRITICAL:
            self.checklist_status[self.BATT_MAN] = self.BAD
            self.checklist_status[self.ESTOP_MAN] = self.GOOD
            self.checklist_status[self.DISABLE_MAN] = self.GOOD
            self.checklist_status[self.JOYSTICK_MAN] = self.NONE
            self.checklist_status[self.BATT_COMP] = self.BAD
            self.checklist_status[self.ESTOP_COMP] = self.GOOD
            self.checklist_status[self.DISABLE_COMP] = self.GOOD
            self.checklist_status[self.JOYSTICK_COMP] = self.NONE
        elif self.current_mode == Mode.MODE_BATTERY_LIMP_HOME:
            self.checklist_status[self.BATT_MAN] = self.GOOD
            self.checklist_status[self.ESTOP_MAN] = self.GOOD
            self.checklist_status[self.DISABLE_MAN] = self.GOOD
            self.checklist_status[self.JOYSTICK_MAN] = self.NONE
            self.checklist_status[self.BATT_COMP] = self.BAD
            self.checklist_status[self.ESTOP_COMP] = self.GOOD
            self.checklist_status[self.DISABLE_COMP] = self.GOOD
            self.checklist_status[self.JOYSTICK_COMP] = self.NONE
        
        # Check if joystick is suppressed by topic
        if self.joystick_suppressed:
            self.checklist_status[self.SUPPRESS_COMP] = self.GOOD
            self.checklist_status[self.DISABLE_COMP] = self.NONE
            self.checklist_status[self.JOYSTICK_COMP] = self.NONE
        else:
            self.checklist_status[self.SUPPRESS_COMP] = self.NONE
        if (rospy.Time.now() - self.last_suppress_time).to_sec() > self.JOYSTICK_SUPPRESS_PERIOD:
            self.checklist_status[self.SUPPRESS_MAN] = self.GOOD
        else:
            self.checklist_status[self.SUPPRESS_MAN] = self.BAD
        
        # Command message received
        if self.command_received:
            self.checklist_status[self.CMD_COMP] = self.GOOD
        else:
            self.checklist_status[self.CMD_COMP] = self.BAD
            
        # Override twist checkbox if mode is in TIMEOUT
        if self.current_mode == Mode.MODE_TIMEOUT:
            self.checklist_status[self.CMD_COMP] = self.BAD
        
        # Update checklist graphics    
        self.updateCheckStatus(self._widget.batt_man_chk, self.checklist_status[self.BATT_MAN])
        self.updateCheckStatus(self._widget.estop_man_chk, self.checklist_status[self.ESTOP_MAN])
        self.updateCheckStatus(self._widget.disable_man_chk, self.checklist_status[self.DISABLE_MAN])
        self.updateCheckStatus(self._widget.joystick_man_chk, self.checklist_status[self.JOYSTICK_MAN])
        self.updateCheckStatus(self._widget.suppress_man_chk, self.checklist_status[self.SUPPRESS_MAN])
        self.updateCheckStatus(self._widget.batt_comp_chk, self.checklist_status[self.BATT_COMP])
        self.updateCheckStatus(self._widget.estop_comp_chk, self.checklist_status[self.ESTOP_COMP])
        self.updateCheckStatus(self._widget.disable_comp_chk, self.checklist_status[self.DISABLE_COMP])
        self.updateCheckStatus(self._widget.joystick_comp_chk, self.checklist_status[self.JOYSTICK_COMP])
        self.updateCheckStatus(self._widget.suppress_comp_chk, self.checklist_status[self.SUPPRESS_COMP])
        self.updateCheckStatus(self._widget.cmd_comp_chk, self.checklist_status[self.CMD_COMP])
        self.updateCheckStatus(self._widget.joystick_bind_chk, self.NONE)        

        
    def updateCheckStatus(self, obj, icon_type):
        if icon_type == self.GOOD:
            obj.setPixmap(self.good_icon)
        elif icon_type == self.BAD:
            obj.setPixmap(self.bad_icon)
        else:
            obj.setPixmap(self.none_icon)
        
    def updateTable(self):
        for i in range(0, len(self.joystick_table_vals)):
            self.joystick_table_vals[i].setText(55)
    
    def recvMode(self, mode_msg):
        self.current_mode = mode_msg.mode
    
    def recvSuppress(self, suppress_msg):
        self.suppress_dt = rospy.Time.now() - self.last_suppress_time
        self.last_suppress_time = rospy.Time.now()
    
    def recvTwist(self, twist_msg):
        self.twist_dt = rospy.Time.now() - self.last_twist_time
        self.last_twist_time = rospy.Time.now()
        self.current_cmd = twist_msg
    
    def recvJoystick(self, joystick_msg):
        self.joystick_data = joystick_msg.channels;
        self.last_joystick_time = rospy.Time.now()
    
    def recvBumpers(self, bumper_msg):
        self.bumper_front_left = bumper_msg.front_left
        self.bumper_front_right = bumper_msg.front_right
        self.bumper_rear_left = bumper_msg.rear_left
        self.bumper_rear_right = bumper_msg.rear_right
    
    def recvBattery(self, battery_msg):
        self.battery_percent = battery_msg.percent
        self.battery_voltage = battery_msg.voltage
    
    def recvBindStatus(self, bind_msg):
        self.joystick_bind_status = bind_msg.data
        
        if bind_msg.data:
            if self.joystick_bind_dot_counter == 0:
                self._widget.joystick_bind_lbl.setText('Binding.')
            elif self.joystick_bind_dot_counter == 1:
                self._widget.joystick_bind_lbl.setText('Binding..')
            elif self.joystick_bind_dot_counter == 2:
                self._widget.joystick_bind_lbl.setText('Binding...')
                
            self.joystick_bind_dot_counter = (self.joystick_bind_dot_counter + 1) % 3

    def recvGyroCalibrated(self, cal_msg):
        self.gyro_cal_status = cal_msg.data
            
    def recvImu(self, imu_msg):
        self.gyro_x = imu_msg.angular_velocity.x
        self.gyro_y = imu_msg.angular_velocity.y
        self.gyro_z = imu_msg.angular_velocity.z
    
    def recvWakeTime(self, time_msg):
        self.current_wake_time = time_msg.data
            
    def subscribeTopics(self):    
        sub_joystick = rospy.Subscriber('/mobility_base/joystick_raw', JoystickRaw, self.recvJoystick)
        sub_suppress = rospy.Subscriber('/mobility_base/suppress_wireless', std_msgs.msg.Empty, self.recvSuppress)
        sub_twist = rospy.Subscriber('/mobility_base/cmd_vel', Twist, self.recvTwist)
        sub_mode = rospy.Subscriber('/mobility_base/mode', Mode, self.recvMode)
        sub_bumpers = rospy.Subscriber('/mobility_base/bumper_states', BumperState, self.recvBumpers)
        sub_battery = rospy.Subscriber('/mobility_base/battery', BatteryState, self.recvBattery)
        sub_bind = rospy.Subscriber('/mobility_base/bind_status', std_msgs.msg.Bool, self.recvBindStatus)
        sub_gyro_calibrated = rospy.Subscriber('/mobility_base/imu/is_calibrated', std_msgs.msg.Bool, self.recvGyroCalibrated)
        sub_imu = rospy.Subscriber('/mobility_base/imu/data_raw', Imu, self.recvImu)
        sub_wake_time = rospy.Subscriber('/mobility_base/wake_time', std_msgs.msg.Time, self.recvWakeTime)
    
    def advertiseTopics(self):
        self.pub_start_bind = rospy.Publisher('/mobility_base/bind_start', std_msgs.msg.Empty, queue_size=1)
        self.pub_stop_bind = rospy.Publisher('/mobility_base/bind_stop', std_msgs.msg.Empty, queue_size=1)
        self.pub_set_wake_time = rospy.Publisher('/mobility_base/set_wake_time', std_msgs.msg.Time, queue_size=1)
    
    def initJoystickGraphics(self):
        # Pens
        self.cyan_pen = QPen(QColor(0, 255, 255))
        self.magenta_pen = QPen(QColor(255, 0, 255))
        self.red_pen = QPen(QColor(255, 0, 0))
        self.cyan_pen.setWidth(3)
        self.magenta_pen.setWidth(3)
        self.red_pen.setWidth(3)
        self.stick_ind_l = QGraphicsEllipseItem()
        self.stick_ind_r = QGraphicsEllipseItem()
        self.stick_line_l = QGraphicsLineItem()
        self.stick_line_r = QGraphicsLineItem()
        self.mode_ind = QGraphicsLineItem()
        
        # Left joystick indicator circle
        px_l = self.stick_ind_lox - self.stick_ind_radius
        py_l = self.stick_ind_loy - self.stick_ind_radius
        self.stick_ind_l.setRect(px_l, py_l, 2 * self.stick_ind_radius, 2 * self.stick_ind_radius)
        self.stick_ind_l.setBrush(QBrush(QColor(255, 0, 0)))
        self.stick_ind_l.setPen(QPen(QColor(0, 0, 0)))  
        
        # Right joystick indicator circle
        px_r = self.stick_ind_rox - self.stick_ind_radius
        py_r = self.stick_ind_roy - self.stick_ind_radius
        self.stick_ind_r.setRect(px_r, py_r, 2 * self.stick_ind_radius, 2 * self.stick_ind_radius)
        self.stick_ind_r.setBrush(QBrush(QColor(255, 0, 0)))
        self.stick_ind_r.setPen(QPen(QColor(0, 0, 0)))
        
        # Left joystick indicator line
        line_pen = QPen(QColor(255,0,0))
        line_pen.setWidth(4)
        self.stick_line_l.setLine(self.stick_ind_lox, self.stick_ind_loy, self.stick_ind_lox, self.stick_ind_loy)
        self.stick_line_l.setPen(line_pen)
        
        # Right joystick indicator line
        self.stick_line_r.setLine(self.stick_ind_rox, self.stick_ind_roy, self.stick_ind_rox, self.stick_ind_roy)
        self.stick_line_r.setPen(line_pen) 
        
        # Mode indicator line
        self.mode_ind.setLine(self.mode_ind_x1, self.mode_ind_y1, self.mode_ind_x2, self.mode_ind_y2)
        self.mode_ind.setPen(self.cyan_pen)
        
        # Joystick power indicator
        self.joystick_power_ind = []
        self.joystick_power_ind.append(QGraphicsLineItem(self.power_ind_x1, self.power_ind_y + 20, self.power_ind_x1, self.power_ind_y - 20))
        self.joystick_power_ind.append(QGraphicsLineItem(self.power_ind_x1, self.power_ind_y - 20, self.power_ind_x1 + 50, self.power_ind_y - 20))
        self.joystick_power_ind.append(QGraphicsLineItem(self.power_ind_x1+50, self.power_ind_y - 20, self.power_ind_x1+50, self.power_ind_y + 20))
        self.joystick_power_ind.append(QGraphicsLineItem(self.power_ind_x1+50, self.power_ind_y + 20, self.power_ind_x1, self.power_ind_y + 20))
        
        # Populate scene
        graphics_scene = QGraphicsScene()
        graphics_scene.addItem(self.stick_ind_l)
        graphics_scene.addItem(self.stick_ind_r)
        graphics_scene.addItem(self.stick_line_l)
        graphics_scene.addItem(self.stick_line_r)
        graphics_scene.addItem(self.mode_ind)
        for l in self.joystick_power_ind:
            l.setPen(self.red_pen)
            graphics_scene.addItem(l)
        graphics_scene.setSceneRect(0, 0, self._widget.joystickGraphicsView.width() - 4, self._widget.joystickGraphicsView.height() - 4)
        self._widget.joystickGraphicsView.setScene(graphics_scene)
        self._widget.joystickGraphicsView.setBackgroundBrush(QBrush(QImage(os.path.join(rospkg.RosPack().get_path('mobility_base_tools'), 'images', 'dx6ilabels.jpg'))))
        self._widget.joystickGraphicsView.show()
        
    def initBumperGraphics(self):
        
        # Pens
        self.blue_pen = QPen(QColor(0,0,255))
        self.blue_pen.setWidth(10)
        
        self.bumper_lines = []

        # Text state labels
        self.bumper_state_labels = [QGraphicsTextItem() for i in range(0,4)]
        for i in range(len(self.bumper_state_labels)):
            self.bumper_state_labels[i].setFont(QFont('Ubuntu', 14, QFont.Bold))
            self.bumper_state_labels[i].setPlainText('00')
        self.bumper_state_labels[0].setPos(self.bumper_fl_x-10, self.bumper_fl_y + 55)
        self.bumper_state_labels[1].setPos(self.bumper_fr_x-10, self.bumper_fr_y + 55)
        self.bumper_state_labels[2].setPos(self.bumper_rl_x-10, self.bumper_rl_y - 80)
        self.bumper_state_labels[3].setPos(self.bumper_rr_x-10, self.bumper_rr_y - 80)
        
        # Bumper indicator lines
        self.bumperLine(self.bumper_fl_x - 20, self.bumper_fl_y - self.bumper_dy, True)
        self.bumperLine(self.bumper_fl_x - self.bumper_dx, self.bumper_fl_y - 20, False)
        self.bumperLine(self.bumper_fl_x + self.bumper_dx, self.bumper_fl_y - 20, False)
        self.bumperLine(self.bumper_fl_x - 20, self.bumper_fl_y + self.bumper_dy, True)
        self.bumperLine(self.bumper_fr_x - 20, self.bumper_fr_y - self.bumper_dy, True)
        self.bumperLine(self.bumper_fr_x - self.bumper_dx, self.bumper_fr_y - 20, False)
        self.bumperLine(self.bumper_fr_x + self.bumper_dx, self.bumper_fr_y - 20, False)
        self.bumperLine(self.bumper_fr_x - 20, self.bumper_fr_y + self.bumper_dy, True)
        self.bumperLine(self.bumper_rl_x - 20, self.bumper_rl_y - self.bumper_dy, True)
        self.bumperLine(self.bumper_rl_x - self.bumper_dx, self.bumper_rl_y - 20, False)
        self.bumperLine(self.bumper_rl_x + self.bumper_dx, self.bumper_rl_y - 20, False)
        self.bumperLine(self.bumper_rl_x - 20, self.bumper_rl_y + self.bumper_dy, True)
        self.bumperLine(self.bumper_rr_x - 20, self.bumper_rr_y - self.bumper_dy, True)
        self.bumperLine(self.bumper_rr_x - self.bumper_dx, self.bumper_rr_y - 20, False)
        self.bumperLine(self.bumper_rr_x + self.bumper_dx, self.bumper_rr_y - 20, False)
        self.bumperLine(self.bumper_rr_x - 20, self.bumper_rr_y + self.bumper_dy, True)
        
        # Populate scene
        graphics_scene = QGraphicsScene()
        for bumper in self.bumper_lines:
            graphics_scene.addItem(bumper)
        for label in self.bumper_state_labels:
            graphics_scene.addItem(label)
        graphics_scene.setSceneRect(0, 0, self._widget.bumperGraphicsView.width() - 4, self._widget.bumperGraphicsView.height() - 4)
        self._widget.bumperGraphicsView.setScene(graphics_scene)
        self._widget.bumperGraphicsView.setBackgroundBrush(QBrush(QImage(os.path.join(rospkg.RosPack().get_path('mobility_base_tools'), 'images', 'mb_top.png'))))
        self._widget.bumperGraphicsView.show()
    
    def bumperLine(self, x, y, front):
        new_line = QGraphicsLineItem()
        if front:
            new_line.setLine(x, y, x+40, y)
        else:
            new_line.setLine(x, y, x, y+40)
        new_line.setPen(self.blue_pen)
        new_line.setVisible(False)
        self.bumper_lines.append(new_line)
        
    def bumperVisibleSwitch(self, idx, bumper_state):
        if (bumper_state & BumperState.BUMPER_FRONT):
            self.bumper_lines[idx].setVisible(True)
        else:
            self.bumper_lines[idx].setVisible(False)
        if (bumper_state & BumperState.BUMPER_LEFT):
            self.bumper_lines[idx+1].setVisible(True)
        else:
            self.bumper_lines[idx+1].setVisible(False)
        if (bumper_state & BumperState.BUMPER_RIGHT):
            self.bumper_lines[idx+2].setVisible(True)
        else:
            self.bumper_lines[idx+2].setVisible(False)  
        if (bumper_state & BumperState.BUMPER_REAR):
            self.bumper_lines[idx+3].setVisible(True)
        else:
            self.bumper_lines[idx+3].setVisible(False)
            

    def resetGuiTimer(self):
#         del self.gui_update_timer
        self.gui_update_timer = QTimer(self._widget)
        self.gui_update_timer.setInterval(100)
        self.gui_update_timer.setSingleShot(False)
        self.gui_update_timer.timeout.connect(lambda:self.updateGuiCallback())
        self.gui_update_timer.start()
        
    def spawnFullGui(self):
        super(DiagnosticGui, self).__init__(self.context_)
        # Give QObjects reasonable names
        self.setObjectName('DiagnosticGui')

        # Create QWidget
        self._widget = QWidget()

        # Get path to UI file which should be in the "resource" folder of this package
        ui_file = os.path.join(rospkg.RosPack().get_path('mobility_base_tools'), 'resource', 'DiagnosticGui.ui')
        # Extend the widget with all attributes and children from UI file
        loadUi(ui_file, self._widget)
        # Give QObjects reasonable names
        self._widget.setObjectName('DiagnosticGui' + str(self.widget_count))
        self.widget_count += 1
        # Add widget to the user interface
        self.context_.add_widget(self._widget)
        
    def spawnTabGui(self):
        super(DiagnosticGui, self).__init__(self.context_)
        # Give QObjects reasonable names
        self.setObjectName('DiagnosticGui')

        # Create QWidget
        self._widget = QWidget()
        
        # Get path to UI file which should be in the "resource" folder of this package
        ui_file = os.path.join(rospkg.RosPack().get_path('mobility_base_tools'), 'resource', 'DiagnosticGuiTabs.ui')
        # Extend the widget with all attributes and children from UI file
        loadUi(ui_file, self._widget)
        # Give QObjects reasonable names
        self._widget.setObjectName('DiagnosticGui' + str(self.widget_count))
        self.widget_count += 1
        # Add widget to the user interface
        self.context_.add_widget(self._widget)
        
    def updateRightStickIndicator(self, lat_val, forward_val):
        horiz_val = -self.stick_ind_range_factor * (lat_val - self.stick_ind_range_mid)
        vert_val = -self.stick_ind_range_factor * (forward_val - self.stick_ind_range_mid)
        r = sqrt(horiz_val * horiz_val + vert_val * vert_val)
        if r > self.stick_ind_range_pix / 2:
            r = self.stick_ind_range_pix / 2
        ang = atan2(vert_val, horiz_val)    
        px = r * cos(ang)
        py = r * sin(ang)
        self.stick_ind_r.setPos(QPoint(px, py))
        self.stick_line_r.setLine(self.stick_ind_rox, self.stick_ind_roy, self.stick_ind_rox + px, self.stick_ind_roy + py)
    
    def updateLeftStickIndicator(self, yaw_val, enable_val):
        horiz_val = -self.stick_ind_range_factor * (yaw_val - self.stick_ind_range_mid)
        vert_val = -self.stick_ind_range_factor * (enable_val - self.stick_ind_range_mid)
        r = sqrt(horiz_val * horiz_val + vert_val * vert_val)
        if r > self.stick_ind_range_pix / 2:
            r = self.stick_ind_range_pix / 2
        ang = atan2(vert_val, horiz_val)    
        px = r * cos(ang)
        py = r * sin(ang)
        self.stick_ind_l.setPos(QPoint(px, py))
        self.stick_line_l.setLine(self.stick_ind_lox, self.stick_ind_loy, self.stick_ind_lox + px, self.stick_ind_loy + py)        
    
    def shutdown_plugin(self):
        pass