예제 #1
0
    def setObjectText(self, strng):
        """
        TOWRITE

        :param `strng`: TOWRITE
        :type `strng`: QString
        """
        self.objText = strng
        textPath = QPainterPath()
        font = QFont()
        font.setFamily(self.objTextFont)
        font.setPointSizeF(self.objTextSize)
        font.setBold(self.objTextBold)
        font.setItalic(self.objTextItalic)
        font.setUnderline(self.objTextUnderline)
        font.setStrikeOut(self.objTextStrikeOut)
        font.setOverline(self.objTextOverline)
        textPath.addText(0., 0., font, strng)

        # Translate the path based on the justification.
        jRect = textPath.boundingRect()  # QRectF
        if self.objTextJustify == "Left": textPath.translate(-jRect.left(), 0)
        elif self.objTextJustify == "Center":
            textPath.translate(-jRect.center().x(), 0)
        elif self.objTextJustify == "Right":
            textPath.translate(-jRect.right(), 0)
        elif self.objTextJustify == "Aligned":
            pass  # TODO: TextSingleObject Aligned Justification
        elif self.objTextJustify == "Middle":
            textPath.translate(-jRect.center())
        elif self.objTextJustify == "Fit":
            pass  # TODO: TextSingleObject Fit Justification
        elif self.objTextJustify == "Top Left":
            textPath.translate(-jRect.topLeft())
        elif self.objTextJustify == "Top Center":
            textPath.translate(-jRect.center().x(), -jRect.top())
        elif self.objTextJustify == "Top Right":
            textPath.translate(-jRect.topRight())
        elif self.objTextJustify == "Middle Left":
            textPath.translate(-jRect.left(), -jRect.top() / 2.0)
        elif self.objTextJustify == "Middle Center":
            textPath.translate(-jRect.center().x(), -jRect.top() / 2.0)
        elif self.objTextJustify == "Middle Right":
            textPath.translate(-jRect.right(), -jRect.top() / 2.0)
        elif self.objTextJustify == "Bottom Left":
            textPath.translate(-jRect.bottomLeft())
        elif self.objTextJustify == "Bottom Center":
            textPath.translate(-jRect.center().x(), -jRect.bottom())
        elif self.objTextJustify == "Bottom Right":
            textPath.translate(-jRect.bottomRight())

        # Backward or Upside Down.
        if self.objTextBackward or self.objTextUpsideDown:

            horiz = 1.0  # qreal
            vert = 1.0  # qreal
            if self.objTextBackward:
                horiz = -1.0
            if self.objTextUpsideDown:
                vert = -1.0

            flippedPath = QPainterPath()

            element = QPainterPath.Element
            P2 = QPainterPath.Element
            P3 = QPainterPath.Element
            P4 = QPainterPath.Element
            for i in range(0, textPath.elementCount(
            )):  # for(int i = 0; i < textPath.elementCount(); ++i)

                element = textPath.elementAt(i)
                if element.isMoveTo():
                    flippedPath.moveTo(horiz * element.x, vert * element.y)

                elif element.isLineTo():
                    flippedPath.lineTo(horiz * element.x, vert * element.y)

                elif element.isCurveTo():
                    # start point P1 is not needed
                    P2 = textPath.elementAt(i)  # control point
                    P3 = textPath.elementAt(i + 1)  # control point
                    P4 = textPath.elementAt(i + 2)  # end point

                    flippedPath.cubicTo(horiz * P2.x, vert * P2.y,
                                        horiz * P3.x, vert * P3.y,
                                        horiz * P4.x, vert * P4.y)

            objTextPath = flippedPath

        else:
            objTextPath = textPath

        # Add the grip point to the shape path.
        gripPath = objTextPath  # QPainterPath
        gripPath.connectPath(objTextPath)
        gripPath.addRect(-0.00000001, -0.00000001, 0.00000002, 0.00000002)
        self.setObjectPath(gripPath)
예제 #2
0
class Bar(QToolBar):

    clicked = Signal(str)

    def __init__(self, orientation=Qt.Horizontal, parent=None):
        super().__init__(parent)
        self.setOrientation(orientation)
        policy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed,
                             QSizePolicy.ButtonBox)
        policy.setHeightForWidth(True)
        policy.setWidthForHeight(True)
        self.setSizePolicy(policy)
        self.setFloatable(False)
        self.setToolTip("""<p><b>Goto Letter</b></p>
<p>Left-click a letter to navigate to the first entry starting with that
letter.</p>
<p>Right-click a letter to navigate to the first entry starting with the
most recently left-clicked letter, plus any subsequent right-clicked
letters, and this letter.</p>
<p>(One left-click or a fifth right-click clears the previous letters.)</p>
<p>For example, left-click <i>S</i> to go to the first “s” entry. Then
right-click <i>A</i> to go to the first “sa” entry, then right-click
<i>T</i> to go to the first “sat” entry.</p>""")
        self.timer = QTimer(self)
        self.timer.setSingleShot(True)
        self.timer.timeout.connect(self.onTimeout)
        size = self.font().pointSizeF()
        strategy = QFont.StyleStrategy(QFont.PreferOutline
                                       | QFont.PreferAntialias
                                       | QFont.PreferQuality)
        self.mainFont = QFont("courier new")
        self.mainFont.setFixedPitch(True)
        self.mainFont.setStyleStrategy(strategy)
        self.mainFont.setStyleHint(QFont.Monospace)
        self.mainFont.setPointSizeF(size * 1.5)
        self.mainFont.setBold(True)
        self.mainFont.setItalic(False)
        self.setFont(self.mainFont)
        self.smallFont = QFont("helvetica")
        self.smallFont.setStyleStrategy(strategy)
        self.smallFont.setStyleHint(QFont.Times)
        self.smallFont.setPointSizeF(size * 1.25)
        self.smallFont.setBold(False)
        self.smallFont.setItalic(False)
        self.letters = string.ascii_uppercase
        self.word = None

    def sizeHint(self):
        return self.minimumSizeHint()

    def minimumSizeHint(self):
        count = len(self.letters)
        widthAll = self.fontMetrics().width(self.letters) * H_GAP_PC
        widthW = self.fontMetrics().width("WW")
        heightOne = self.fontMetrics().height()
        if self.orientation == Qt.Vertical:
            return QSize(widthW, (heightOne * count) + HANDLE_OFFSET)
        return QSize(widthAll + HANDLE_OFFSET, heightOne * V_GAP_PC)

    def paintEvent(self, event):
        super().paintEvent(event)
        letterPen = QPen(Qt.darkGreen if self.isEnabled() else Qt.lightGray)
        wordPen = QPen(Qt.darkCyan if self.isEnabled() else Qt.lightGray)
        painter = QPainter(self)
        painter.setRenderHints(QPainter.TextAntialiasing)
        painter.setPen(letterPen)
        heightOne = self.fontMetrics().height()
        widthOne = self.fontMetrics().width("W")
        if self.orientation == Qt.Vertical:
            y = HANDLE_OFFSET
            for c in self.letters:
                rect = QRectF(X_OFFSET, y, widthOne, heightOne)
                painter.drawText(rect, Qt.AlignCenter, c)
                y += heightOne
            if self.word is not None:
                painter.setFont(self.smallFont)
                painter.setPen(wordPen)
                rect = self.rect().adjusted(0, HANDLE_OFFSET, -widthOne / 3, 0)
                painter.drawText(rect,
                                 Qt.AlignTop | Qt.AlignRight | Qt.TextWordWrap,
                                 "\n".join(self.word.lower()))
                painter.setPen(letterPen)
                painter.setFont(self.mainFont)
        else:
            widthOne *= H_GAP_PC
            x = HANDLE_OFFSET
            for c in self.letters:
                rect = QRectF(x, 0, widthOne, heightOne * V_GAP_PC)
                painter.drawText(rect, Qt.AlignCenter, c)
                x += widthOne
            if self.word is not None:
                painter.setFont(self.smallFont)
                painter.setPen(wordPen)
                rect = self.rect().adjusted(HANDLE_OFFSET, 0, 0, 0)
                painter.drawText(rect, Qt.AlignBottom | Qt.AlignLeft,
                                 self.word.lower())
                painter.setPen(letterPen)
                painter.setFont(self.mainFont)

    def mousePressEvent(self, event):
        if self.orientation == Qt.Vertical:
            if event.y() < HANDLE_OFFSET:
                event.ignore()
                return
            heightOne = self.fontMetrics().height()
            i = clamp(0, int((event.y() - HANDLE_OFFSET) / heightOne),
                      len(self.letters) - 1)
        else:
            if event.x() < HANDLE_OFFSET:
                event.ignore()
                return
            widthOne = self.fontMetrics().width("W") * H_GAP_PC
            i = clamp(0, int((event.x() - HANDLE_OFFSET) / widthOne),
                      len(self.letters) - 1)
        event.accept()
        word = self.letters[i]
        if event.button() == Qt.LeftButton or self.word is None:
            self.word = word
        elif event.button() == Qt.RightButton:
            if len(self.word) >= 4:
                self.word = word
            elif self.word is not None:
                self.word += word
        if self.word is not None:
            self.clicked.emit(self.word.lower())
            self.timer.start(10000)
        self.update()

    def contextMenuEvent(self, event):
        if ((self.orientation == Qt.Vertical and event.y() < HANDLE_OFFSET) or
            (self.orientation == Qt.Horizontal and event.x() < HANDLE_OFFSET)):
            event.ignore()
        else:
            event.accept()

    def setOrientation(self, orientation):
        self.orientation = orientation
        self.update()

    def heightForWidth(self, width):
        count = len(self.letters)
        heightOne = self.fontMetrics().height()
        widthAll = self.fontMetrics().width(self.letters) * H_GAP_PC
        if widthAll > width:  # Needs to be vertical
            return heightOne * count
        return heightOne * V_GAP_PC  # Needs to be horizontal

    def onTimeout(self):
        self.timer.stop()
        if self.word is not None:
            self.word = None
            self.update()
예제 #3
0
class WidgetLcd(QWidget):
    WEIGHT_CURRENT = 1
    WEIGHT_VALUE = 4
    WEIGHT_RANGE = 1
    WEIGHT_SCALE = 0.5

    WEIGHT_BAR = 0.1
    WEIGHT_MARGIN = 0.1

    TICKS = 22

    def __init__(self, parent):
        QWidget.__init__(self, parent)
        self._fontCurrent = QFont('Monospace', self.WEIGHT_CURRENT * 10)
        self._fontValue = QFont('Monospace', self.WEIGHT_VALUE * 10)
        self._fontRange = QFont('Monospace', self.WEIGHT_RANGE * 10)
        self._fontScale = QFont('Monospace', self.WEIGHT_SCALE * 10)

        self.setFont(self._fontCurrent)
        self._sizeCurrent = self.fontMetrics().tightBoundingRect('#')

        self.setFont(self._fontValue)
        self._sizeValue = self.fontMetrics().tightBoundingRect(
            '-#########. ###')

        self.setFont(self._fontRange)
        self._sizeRange = self.fontMetrics().tightBoundingRect('#')

        self.setFont(self._fontScale)
        self._sizeScale = self.fontMetrics().tightBoundingRect('##')

        self.setMinimumWidth(self._sizeValue.width())
        self.setMinimumHeight(self._sizeValue.width() / 5)

        self._meter = None

    def paintEvent(self, event):
        width = event.rect().width() - 1
        scale = float(width) / self._sizeValue.width()

        self._fontCurrent.setPointSizeF(scale * self.WEIGHT_CURRENT * 10)
        self._fontValue.setPointSizeF(scale * self.WEIGHT_VALUE * 10)
        self._fontRange.setPointSizeF(scale * self.WEIGHT_RANGE * 10)

        painter = QPainter()
        painter.begin(self)
        painter.setPen(QPen(QColor(42, 67, 107), 4 * scale))

        pos = self.__drawText(painter, scale)
        pos = self.__drawBar(painter, scale, width, pos)

        painter.end()

        self.setMinimumHeight(pos)

    def __drawText(self, painter, scale):
        margin = self._sizeCurrent.height() * self.WEIGHT_MARGIN * 10 * scale
        top = self._sizeCurrent.height() * scale + margin
        middle = top + (self._sizeValue.height() * scale) + margin
        bottom = middle + (self._sizeRange.height() * scale) + margin

        if self._meter is not None and self._meter.display is not None:
            if self._meter.current == Meter.CURRENT_DC:
                current = 'DC'
            elif self._meter.current == Meter.CURRENT_AC:
                current = 'AC'
            else:
                current = ''
            painter.setFont(self._fontCurrent)
            painter.drawText(margin, top, current)

            painter.setFont(self._fontValue)
            painter.drawText(margin, middle, self._meter.display)

            if self._meter.auto:
                rang = 'AUTO'
            else:
                rang = 'MANUAL'
            painter.setFont(self._fontRange)
            painter.drawText(margin, bottom, rang)
        else:
            painter.setFont(self._fontValue)
            painter.drawText(margin, middle, '    ------')

        return bottom + margin

    def __drawBar(self, painter, scale, width, pos):
        margin = self._sizeCurrent.height() * self.WEIGHT_MARGIN * 10 * scale
        height = self._sizeCurrent.height() * self.WEIGHT_BAR * 10 * scale

        self._fontScale.setPointSizeF(scale * self.WEIGHT_SCALE * 10)
        painter.setFont(self._fontScale)

        for i in range(self.TICKS * 2 - 1):
            x = (i * (width - margin) / float(self.TICKS * 2)) + margin
            length = height / 2
            if i % 10 == 0:
                length = height
                centre = self.fontMetrics().width(str(i / 2)) / 2
                painter.drawText(x - centre, pos + margin * 2, str(i / 2))
            elif i % 2 == 0:
                length = height * 2 / 3
            if self._meter is not None and i <= self._meter.bar:
                painter.drawLine(x, pos + height, x, pos + height - length)

        return pos + height + margin * 2

    def set(self, meter):
        self._meter = meter
        self.repaint()

    def clear(self):
        self._meter = None
        self.repaint()
    def setObjectText(self, strng):
        """
        TOWRITE

        :param `strng`: TOWRITE
        :type `strng`: QString
        """
        self.objText = strng
        textPath = QPainterPath()
        font = QFont()
        font.setFamily(self.objTextFont)
        font.setPointSizeF(self.objTextSize)
        font.setBold(self.objTextBold)
        font.setItalic(self.objTextItalic)
        font.setUnderline(self.objTextUnderline)
        font.setStrikeOut(self.objTextStrikeOut)
        font.setOverline(self.objTextOverline)
        textPath.addText(0., 0., font, strng)

        # Translate the path based on the justification.
        jRect = textPath.boundingRect()  # QRectF
        if   self.objTextJustify == "Left":          textPath.translate(-jRect.left(), 0)
        elif self.objTextJustify == "Center":        textPath.translate(-jRect.center().x(), 0)
        elif self.objTextJustify == "Right":         textPath.translate(-jRect.right(), 0)
        elif self.objTextJustify == "Aligned":       pass # TODO: TextSingleObject Aligned Justification
        elif self.objTextJustify == "Middle":        textPath.translate(-jRect.center())
        elif self.objTextJustify == "Fit":           pass # TODO: TextSingleObject Fit Justification
        elif self.objTextJustify == "Top Left":      textPath.translate(-jRect.topLeft())
        elif self.objTextJustify == "Top Center":    textPath.translate(-jRect.center().x(), -jRect.top())
        elif self.objTextJustify == "Top Right":     textPath.translate(-jRect.topRight())
        elif self.objTextJustify == "Middle Left":   textPath.translate(-jRect.left(), -jRect.top()/2.0)
        elif self.objTextJustify == "Middle Center": textPath.translate(-jRect.center().x(), -jRect.top()/2.0)
        elif self.objTextJustify == "Middle Right":  textPath.translate(-jRect.right(), -jRect.top()/2.0)
        elif self.objTextJustify == "Bottom Left":   textPath.translate(-jRect.bottomLeft())
        elif self.objTextJustify == "Bottom Center": textPath.translate(-jRect.center().x(), -jRect.bottom())
        elif self.objTextJustify == "Bottom Right":  textPath.translate(-jRect.bottomRight())

        # Backward or Upside Down.
        if self.objTextBackward or self.objTextUpsideDown:

            horiz = 1.0  # qreal
            vert = 1.0   # qreal
            if self.objTextBackward:
                horiz = -1.0
            if self.objTextUpsideDown:
                vert = -1.0

            flippedPath = QPainterPath()

            element = QPainterPath.Element
            P2      = QPainterPath.Element
            P3      = QPainterPath.Element
            P4      = QPainterPath.Element
            for i in range(0, textPath.elementCount()):  # for(int i = 0; i < textPath.elementCount(); ++i)

                element = textPath.elementAt(i)
                if element.isMoveTo():
                    flippedPath.moveTo(horiz * element.x, vert * element.y)

                elif element.isLineTo():
                    flippedPath.lineTo(horiz * element.x, vert * element.y)

                elif element.isCurveTo():
                                                    # start point P1 is not needed
                    P2 = textPath.elementAt(i)      # control point
                    P3 = textPath.elementAt(i + 1)  # control point
                    P4 = textPath.elementAt(i + 2)  # end point

                    flippedPath.cubicTo(horiz * P2.x, vert * P2.y,
                                        horiz * P3.x, vert * P3.y,
                                        horiz * P4.x, vert * P4.y)

            objTextPath = flippedPath

        else:
            objTextPath = textPath

        # Add the grip point to the shape path.
        gripPath = objTextPath  # QPainterPath
        gripPath.connectPath(objTextPath)
        gripPath.addRect(-0.00000001, -0.00000001, 0.00000002, 0.00000002)
        self.setObjectPath(gripPath)
예제 #5
0
class DefaultCustomDelegate(QStyledItemDelegate):

    '''Delegate to do custom draw of the items'''

    memoized_size = {}

    def __init__(self, parent):
        '''Initialization'''

        QStyledItemDelegate.__init__(self, parent)

        self.bg_color = QColor('#000000')
        self.bg_alternate_color = QColor('#333333')
        self.new_bg_color = QColor('#0044dd')
        self.new_bg_alternate_color = QColor('#223399')
        self.user_color = QColor('#7AB4F5')
        self.time_color = QColor('#7AB4F5')
        self.replyto_color = QColor('#7AB4F5')

        self.text_color = QColor('#FFFFFF')
        self.separator_color = QColor('#000000')
        self.fsize = 1.0
        self.fm = None
        self.minifm = None

        self.normFont = None
        self.miniFont = None

#        print os.path.join(os.path.dirname(__file__),
#                                  'icons', 'reply.png')
        self.reply_icon = QPixmap(os.path.join(os.path.dirname(__file__),
                                  'icons', 'reply.png'))
#        print dir(self.reply_icon)
        self.retweet_icon = QPixmap(os.path.join(os.path.dirname(__file__),
                                    'icons', 'retweet.png'))
        self.geoloc_icon = QPixmap(os.path.join(os.path.dirname(__file__),
                                   'icons', 'geoloc.png'))

    def doZoomRefresh(self):
        self.memoized_size.clear()
        self.fm = None
        self.minifm = None
        self.normFont = None
        self.miniFont = None

    def sizeHint(self, option, index):
        '''Custom size calculation of our items'''

        uid = to_str(index.data(role=IDROLE)) + 'x' + str(option.rect.width()) #Fix Bug #967 (sometime uid have some strange unicode chars ... ?)
        try:
            return self.memoized_size[uid]
        except:
            tweet = to_str(index.data(Qt.DisplayRole))

            # One time is enought sizeHint need to be fast

            if not self.fm:
                self.normFont = QFont(option.font)
                self.normFont.setPointSizeF(option.font.pointSizeF()
                        * self.fsize)
                self.fm = QFontMetrics(self.normFont)

            if not self.minifm:
                self.miniFont = QFont(option.font)
                self.miniFont.setPointSizeF(option.font.pointSizeF()
                        * 0.8 * self.fsize)
                self.minifm = QFontMetrics(self.miniFont)

            height = self.fm.boundingRect(
                0,
                0,
                option.rect.width() - 75,
                800,
                int(Qt.AlignTop) | int(Qt.AlignLeft) | int(Qt.TextWordWrap),
                tweet,
                ).height()

            reply_text = to_str(index.data(role=REPLYTEXTROLE))
            if reply_text:
                height += self.minifm.boundingRect(
                    0,
                    0,
                    option.rect.width() - 75,
                    800,
                    int(Qt.AlignTop) | int(Qt.AlignLeft)
                        | int(Qt.TextWordWrap),
                    reply_text,
                    ).height() + 5

            height += self.minifm.boundingRect(
                0,
                0,
                option.rect.width() - 75,
                800,
                int(Qt.AlignTop) | int(Qt.AlignLeft) | int(Qt.TextWordWrap),
                'LpqAT',
                ).height()
            height += 10  # Spacer

            if height < 70:
                height = 70
            self.memoized_size[uid] = QSize(option.rect.width(), height)
            return self.memoized_size[uid]

    def paint(
        self,
        painter,
        option,
        index,
        ):
        '''Paint our tweet'''

        (x1, y1, x2, y2) = option.rect.getCoords()

        # Ugly hack ?
        if y1 < 0 and y2 < 0:
            return

        # Init Font : One time is enough
        if not self.fm:
            self.normFont = QFont(option.font)
            self.normFont.setPointSizeF(option.font.pointSizeF() * self.fsize)

        if not self.minifm:
            self.miniFont = QFont(option.font)
            self.miniFont.setPointSizeF(option.font.pointSizeF()
                                        * 0.8 * self.fsize)

        # Query data
        tweet = to_str(index.data(Qt.DisplayRole))
        screenname = to_str(index.data(SCREENNAMEROLE))
        retweet_of = index.data(RETWEETOFROLE)
        timestamp = to_str(index.data(role=TIMESTAMPROLE))
        reply_name = to_str(index.data(role=REPLYTOSCREENNAMEROLE))
        reply_text = to_str(index.data(role=REPLYTEXTROLE))
        is_new = index.data(role=ISNEWROLE)

        painter.save()

        # Draw alternate ?
        if index.row() % 2 == 0:
                color = self.bg_color
        else:
                color = self.bg_alternate_color

        painter.fillRect(option.rect, color)

        # highlight selected items
        if option.state & QStyle.State_Selected:
            painter.fillRect(option.rect, option.palette.highlight())

        # Draw icon
        icon = index.data(Qt.DecorationRole)
        if type(icon) == QPixmap:
            try:
                painter.drawPixmap(x1 + 10, y1 + 10, 50, 50, icon)
            except Exception:
                logging.exception("Drawing icon")

        # Draw screenname
        painter.setFont(self.miniFont)
        painter.setPen(self.user_color)
        nrect = painter.drawText(option.rect.adjusted(70, 5, -4, -9),
                                 int(Qt.AlignTop) | int(Qt.AlignLeft),
                                 screenname)

        # Reply icon
        if reply_name:
            painter.drawPixmap(x1 + 74 + nrect.width(), y1, 26, 26,
                               self.reply_icon)
            painter.setFont(self.miniFont)
            painter.setPen(self.replyto_color)
            painter.drawText(option.rect.adjusted(109 + nrect.width(), 5, -4,
                             -9), int(Qt.AlignTop) | int(Qt.AlignLeft),
                             reply_name)

        # Retweet icon
        if retweet_of:
            painter.drawPixmap(x1 + 74 + nrect.width(), y1, 32, 32,
                               self.retweet_icon)
            painter.setFont(self.miniFont)
            painter.setPen(self.replyto_color)
            painter.drawText(option.rect.adjusted(110 + nrect.width(), 5, -4,
                             -9), int(Qt.AlignTop) | int(Qt.AlignLeft),
                             retweet_of.user.screen_name)

        # Draw tweet
        painter.setFont(self.normFont)
        painter.setPen(self.text_color)
        new_rect = painter.drawText(option.rect.adjusted(70, nrect.height()
                                    + 5, -4, 0), int(Qt.AlignTop)
                                    | int(Qt.AlignLeft) | int(Qt.TextWordWrap),
                                    tweet)

        # Draw Timeline
        painter.setFont(self.miniFont)
        painter.setPen(self.time_color)
        painter.drawText(option.rect.adjusted(70, 5, -4, -9), int(Qt.AlignTop)
                         | int(Qt.AlignRight), timestamp)

        # Draw reply
        if reply_text:
            painter.setFont(self.miniFont)
            painter.setPen(self.replyto_color)
            painter.drawText(option.rect.adjusted(70, nrect.height()
                             + new_rect.height() + 5, -4, -9), int(Qt.AlignTop)
                             | int(Qt.AlignLeft) | int(Qt.TextWordWrap),
                             reply_text)

        # Draw line separator
        painter.setPen(self.separator_color)
        painter.drawLine(x1, y2, x2, y2)

        #Use a little tips to say that's a new tweet
        if is_new:
            painter.fillRect(x1,y1,8,y2, self.new_bg_alternate_color)

        # restore painter
        painter.restore()
예제 #6
0
class DefaultCustomDelegate(QStyledItemDelegate):
    '''Delegate to do custom draw of the items'''

    memoized_size = {}

    def __init__(self, parent):
        '''Initialization'''

        QStyledItemDelegate.__init__(self, parent)

        self.bg_color = QColor('#000000')
        self.bg_alternate_color = QColor('#333333')
        self.new_bg_color = QColor('#0044dd')
        self.new_bg_alternate_color = QColor('#223399')
        self.user_color = QColor('#7AB4F5')
        self.time_color = QColor('#7AB4F5')
        self.replyto_color = QColor('#7AB4F5')

        self.text_color = QColor('#FFFFFF')
        self.separator_color = QColor('#000000')
        self.fsize = 1.0
        self.fm = None
        self.minifm = None

        self.normFont = None
        self.miniFont = None

        #        print os.path.join(os.path.dirname(__file__),
        #                                  'icons', 'reply.png')
        self.reply_icon = QPixmap(
            os.path.join(os.path.dirname(__file__), 'icons', 'reply.png'))
        #        print dir(self.reply_icon)
        self.retweet_icon = QPixmap(
            os.path.join(os.path.dirname(__file__), 'icons', 'retweet.png'))
        self.geoloc_icon = QPixmap(
            os.path.join(os.path.dirname(__file__), 'icons', 'geoloc.png'))

    def doZoomRefresh(self):
        self.memoized_size.clear()
        self.fm = None
        self.minifm = None
        self.normFont = None
        self.miniFont = None

    def sizeHint(self, option, index):
        '''Custom size calculation of our items'''

        uid = to_str(index.data(role=IDROLE)) + 'x' + str(option.rect.width(
        ))  #Fix Bug #967 (sometime uid have some strange unicode chars ... ?)
        try:
            return self.memoized_size[uid]
        except:
            tweet = to_str(index.data(Qt.DisplayRole))

            # One time is enought sizeHint need to be fast

            if not self.fm:
                self.normFont = QFont(option.font)
                self.normFont.setPointSizeF(option.font.pointSizeF() *
                                            self.fsize)
                self.fm = QFontMetrics(self.normFont)

            if not self.minifm:
                self.miniFont = QFont(option.font)
                self.miniFont.setPointSizeF(option.font.pointSizeF() * 0.8 *
                                            self.fsize)
                self.minifm = QFontMetrics(self.miniFont)

            height = self.fm.boundingRect(
                0,
                0,
                option.rect.width() - 75,
                800,
                int(Qt.AlignTop) | int(Qt.AlignLeft) | int(Qt.TextWordWrap),
                tweet,
            ).height()

            reply_text = to_str(index.data(role=REPLYTEXTROLE))
            if reply_text:
                height += self.minifm.boundingRect(
                    0,
                    0,
                    option.rect.width() - 75,
                    800,
                    int(Qt.AlignTop) | int(Qt.AlignLeft)
                    | int(Qt.TextWordWrap),
                    reply_text,
                ).height() + 5

            height += self.minifm.boundingRect(
                0,
                0,
                option.rect.width() - 75,
                800,
                int(Qt.AlignTop) | int(Qt.AlignLeft) | int(Qt.TextWordWrap),
                'LpqAT',
            ).height()
            height += 10  # Spacer

            if height < 70:
                height = 70
            self.memoized_size[uid] = QSize(option.rect.width(), height)
            return self.memoized_size[uid]

    def paint(
        self,
        painter,
        option,
        index,
    ):
        '''Paint our tweet'''

        (x1, y1, x2, y2) = option.rect.getCoords()

        # Ugly hack ?
        if y1 < 0 and y2 < 0:
            return

        # Init Font : One time is enough
        if not self.fm:
            self.normFont = QFont(option.font)
            self.normFont.setPointSizeF(option.font.pointSizeF() * self.fsize)

        if not self.minifm:
            self.miniFont = QFont(option.font)
            self.miniFont.setPointSizeF(option.font.pointSizeF() * 0.8 *
                                        self.fsize)

        # Query data
        tweet = to_str(index.data(Qt.DisplayRole))
        screenname = to_str(index.data(SCREENNAMEROLE))
        retweet_of = index.data(RETWEETOFROLE)
        timestamp = to_str(index.data(role=TIMESTAMPROLE))
        reply_name = to_str(index.data(role=REPLYTOSCREENNAMEROLE))
        reply_text = to_str(index.data(role=REPLYTEXTROLE))
        is_new = index.data(role=ISNEWROLE)

        painter.save()

        # Draw alternate ?
        if index.row() % 2 == 0:
            color = self.bg_color
        else:
            color = self.bg_alternate_color

        painter.fillRect(option.rect, color)

        # highlight selected items
        if option.state & QStyle.State_Selected:
            painter.fillRect(option.rect, option.palette.highlight())

        # Draw icon
        icon = index.data(Qt.DecorationRole)
        if type(icon) == QPixmap:
            try:
                painter.drawPixmap(x1 + 10, y1 + 10, 50, 50, icon)
            except Exception:
                logging.exception("Drawing icon")

        # Draw screenname
        painter.setFont(self.miniFont)
        painter.setPen(self.user_color)
        nrect = painter.drawText(option.rect.adjusted(70, 5, -4, -9),
                                 int(Qt.AlignTop) | int(Qt.AlignLeft),
                                 screenname)

        # Reply icon
        if reply_name:
            painter.drawPixmap(x1 + 74 + nrect.width(), y1, 26, 26,
                               self.reply_icon)
            painter.setFont(self.miniFont)
            painter.setPen(self.replyto_color)
            painter.drawText(
                option.rect.adjusted(109 + nrect.width(), 5, -4, -9),
                int(Qt.AlignTop) | int(Qt.AlignLeft), reply_name)

        # Retweet icon
        if retweet_of:
            painter.drawPixmap(x1 + 74 + nrect.width(), y1, 32, 32,
                               self.retweet_icon)
            painter.setFont(self.miniFont)
            painter.setPen(self.replyto_color)
            painter.drawText(
                option.rect.adjusted(110 + nrect.width(), 5, -4, -9),
                int(Qt.AlignTop) | int(Qt.AlignLeft),
                retweet_of.user.screen_name)

        # Draw tweet
        painter.setFont(self.normFont)
        painter.setPen(self.text_color)
        new_rect = painter.drawText(
            option.rect.adjusted(70,
                                 nrect.height() + 5, -4, 0),
            int(Qt.AlignTop)
            | int(Qt.AlignLeft) | int(Qt.TextWordWrap), tweet)

        # Draw Timeline
        painter.setFont(self.miniFont)
        painter.setPen(self.time_color)
        painter.drawText(option.rect.adjusted(70, 5, -4, -9),
                         int(Qt.AlignTop)
                         | int(Qt.AlignRight), timestamp)

        # Draw reply
        if reply_text:
            painter.setFont(self.miniFont)
            painter.setPen(self.replyto_color)
            painter.drawText(
                option.rect.adjusted(70,
                                     nrect.height() + new_rect.height() + 5,
                                     -4, -9),
                int(Qt.AlignTop)
                | int(Qt.AlignLeft) | int(Qt.TextWordWrap), reply_text)

        # Draw line separator
        painter.setPen(self.separator_color)
        painter.drawLine(x1, y2, x2, y2)

        #Use a little tips to say that's a new tweet
        if is_new:
            painter.fillRect(x1, y1, 8, y2, self.new_bg_alternate_color)

        # restore painter
        painter.restore()