示例#1
0
class NDocumentLabel(QFrame):
    """Simple widget to draw QTextDocument. sizeHint will always related
    to fixed number of lines set. If font fallback happen, it may look bad."""

    def __init__(self, parent=None, lines=None, **kwargs):
        super().__init__(parent, **kwargs)
        self._lines = self._heightHint = None
        self.doc = NTextDocument(self)
        self.doc.setDocumentMargin(0)
        self.doc.setUndoRedoEnabled(False)
        self.setLines(lines if lines else 4)
        self.doc.documentLayout().setPaintDevice(self)  # make difference on high DPI

    def setFont(self, f):
        self.doc.setDefaultFont(f)
        super().setFont(f)
        self.setLines(self._lines)  # refresh size hint

    def setText(self, text, formats):
        self.doc.setText(text, formats)
        # delete exceed lines here using QTextCursor will slow down

    def setLines(self, lines):
        self._lines = lines
        self.doc.setText('\n' * (lines - 1), None)
        self._heightHint = int(self.doc.size().height())
        self.updateGeometry()

    def paintEvent(self, event):
        painter = QPainter(self)
        rect = self.contentsRect()
        painter.translate(rect.topLeft())
        rect.moveTo(0, 0)  # become clip rect
        self.doc.drawContentsPalette(painter, rect, self.palette())

    def resizeEvent(self, event):
        self.doc.setTextWidth(self.contentsRect().width())
        super().resizeEvent(event)

    def sizeHint(self):
        __, top, __, bottom = self.getContentsMargins()
        return QSize(-1, self._heightHint + top + bottom)
示例#2
0
class DiaryListDelegate(QStyledItemDelegate):
    """ItemDelegate of old theme 'one-pixel-rect' for DiaryList, Using 'traditional'
    painting method compared to colorful theme."""
    def __init__(self):
        super().__init__()  # don't pass parent because of mem problem
        # Because some fonts have much more space at top and bottom, we use ascent instead
        # of height, and add it with a small number.
        magic = int(4 * scaleRatio)
        self.title_h = max(font.title_m.ascent(), font.datetime_m.ascent()) + magic
        self.titleArea_h = self.title_h + 4
        self.text_h = font.text_m.lineSpacing() * settings['Main'].getint('previewLines')
        self.tagPath_h = font.default_m.ascent() + magic
        self.tag_h = self.tagPath_h + 4
        self.dt_w = font.datetime_m.width(datetimeTrans('2000-01-01 00:00')) + 40
        self.all_h = None  # updated in sizeHint before each item being painting
        # doc is used to draw text(diary's body)
        self.doc = NTextDocument()
        self.doc.setDefaultFont(font.text)
        self.doc.setUndoRedoEnabled(False)
        self.doc.setDocumentMargin(0)
        self.doc.documentLayout().setPaintDevice(qApp.desktop())  # refer actual list will cause segfault
        # setup colors
        self.c_text = Qt.black
        self.c_bg = QColor(255, 236, 176)
        self.c_border = QColor(214, 172, 41)
        self.c_inActBg = QColor(255, 236, 176, 40)
        self.c_gray = QColor(93, 73, 57)

    def paint(self, painter, option, index):
        x, y, w = option.rect.x(), option.rect.y(), option.rect.width()-1
        row = index.row()
        dt, text, title, tags, formats = (index.sibling(row, i).data()
                                          for i in range(1, 6))
        selected = bool(option.state & QStyle.State_Selected)
        active = bool(option.state & QStyle.State_Active)
        # draw border and background
        painter.setPen(self.c_border)
        painter.setBrush(self.c_bg if selected and active else
                         self.c_inActBg)
        painter.drawRect(x+1, y, w-2, self.all_h)  # outer border
        if selected:  # draw inner border
            pen = QPen()
            pen.setStyle(Qt.DashLine)
            pen.setColor(self.c_gray)
            painter.setPen(pen)
            painter.drawRect(x+2, y+1, w-4, self.all_h-2)
        # draw datetime and title
        painter.setPen(self.c_gray)
        painter.drawLine(x+10, y+self.titleArea_h, x+w-10, y+self.titleArea_h)
        painter.setPen(self.c_text)
        painter.setFont(font.datetime)
        painter.drawText(x+14, y+self.titleArea_h-self.title_h, self.dt_w, self.title_h,
                         Qt.AlignVCenter, datetimeTrans(dt))
        if title:
            painter.setFont(font.title)
            title_w = w - self.dt_w - 13
            title = font.title_m.elidedText(title, Qt.ElideRight, title_w)
            painter.drawText(x+self.dt_w, y+self.titleArea_h-self.title_h, title_w, self.title_h,
                             Qt.AlignVCenter | Qt.AlignRight, title)
        # draw text
        self.doc.setText(text, formats)
        self.doc.setTextWidth(w-26)
        painter.translate(x+14, y+self.titleArea_h+2)
        self.doc.drawContentsColor(painter, QRect(0, 0, w-26, self.text_h), self.c_text)
        painter.resetTransform()
        # draw tags
        if tags:
            painter.setPen(self.c_gray)
            painter.setFont(font.default)
            painter.translate(x + 15, y+self.titleArea_h+6+self.text_h)
            real_x, max_x = x+15, w-10
            for t in tags.split():
                oneTag_w = font.default_m.width(t) + 4
                real_x += oneTag_w + 15
                if real_x > max_x: break
                tagPath = QPainterPath()
                tagPath.moveTo(8, 0)
                tagPath.lineTo(8+oneTag_w, 0)
                tagPath.lineTo(8+oneTag_w, self.tagPath_h)
                tagPath.lineTo(8, self.tagPath_h)
                tagPath.lineTo(0, self.tagPath_h/2)
                tagPath.closeSubpath()
                painter.drawPath(tagPath)
                painter.drawText(8, 0, oneTag_w, self.tagPath_h, Qt.AlignCenter, t)
                painter.translate(oneTag_w+15, 0)  # translate by offset
            else:
                painter.resetTransform()
                return
            # draw ellipsis if too many tags
            painter.setPen(Qt.DotLine)
            painter.drawLine(-4, self.tagPath_h/2, 2, self.tagPath_h/2)
            painter.resetTransform()

    def sizeHint(self, option, index):
        tag_h = self.tag_h if index.sibling(index.row(), 4).data() else 0
        self.all_h = self.titleArea_h + 2 + self.text_h + tag_h + 6
        return QSize(-1, self.all_h+3)  # 3 is spacing between entries
示例#3
0
class DiaryListDelegate(QStyledItemDelegate):
    """ItemDelegate of old theme 'one-pixel-rect' for DiaryList, Using 'traditional'
    painting method compared to colorful theme."""
    def __init__(self):
        super().__init__()  # don't pass parent because of mem problem
        # Because some fonts have much more space at top and bottom, we use ascent instead
        # of height, and add it with a small number.
        magic = int(4 * scaleRatio)
        self.title_h = max(font.title_m.ascent(),
                           font.datetime_m.ascent()) + magic
        self.titleArea_h = self.title_h + 4
        self.text_h = font.text_m.lineSpacing() * settings['Main'].getint(
            'previewLines')
        self.tagPath_h = font.default_m.ascent() + magic
        self.tag_h = self.tagPath_h + 4
        self.dt_w = font.datetime_m.width(
            datetimeTrans('2000-01-01 00:00')) + 40
        self.all_h = None  # updated in sizeHint before each item being painting
        # doc is used to draw text(diary's body)
        self.doc = NTextDocument()
        self.doc.setDefaultFont(font.text)
        self.doc.setUndoRedoEnabled(False)
        self.doc.setDocumentMargin(0)
        self.doc.documentLayout().setPaintDevice(
            qApp.desktop())  # refer actual list will cause segfault
        # setup colors
        self.c_text = Qt.black
        self.c_bg = QColor(255, 236, 176)
        self.c_border = QColor(214, 172, 41)
        self.c_inActBg = QColor(255, 236, 176, 40)
        self.c_gray = QColor(93, 73, 57)

    def paint(self, painter, option, index):
        x, y, w = option.rect.x(), option.rect.y(), option.rect.width() - 1
        row = index.row()
        dt, text, title, tags, formats = (index.sibling(row, i).data()
                                          for i in range(1, 6))
        selected = bool(option.state & QStyle.State_Selected)
        active = bool(option.state & QStyle.State_Active)
        # draw border and background
        painter.setPen(self.c_border)
        painter.setBrush(self.c_bg if selected and active else self.c_inActBg)
        painter.drawRect(x + 1, y, w - 2, self.all_h)  # outer border
        if selected:  # draw inner border
            pen = QPen()
            pen.setStyle(Qt.DashLine)
            pen.setColor(self.c_gray)
            painter.setPen(pen)
            painter.drawRect(x + 2, y + 1, w - 4, self.all_h - 2)
        # draw datetime and title
        painter.setPen(self.c_gray)
        painter.drawLine(x + 10, y + self.titleArea_h, x + w - 10,
                         y + self.titleArea_h)
        painter.setPen(self.c_text)
        painter.setFont(font.datetime)
        painter.drawText(x + 14, y + self.titleArea_h - self.title_h,
                         self.dt_w, self.title_h, Qt.AlignVCenter,
                         datetimeTrans(dt))
        if title:
            painter.setFont(font.title)
            title_w = w - self.dt_w - 13
            title = font.title_m.elidedText(title, Qt.ElideRight, title_w)
            painter.drawText(x + self.dt_w,
                             y + self.titleArea_h - self.title_h, title_w,
                             self.title_h, Qt.AlignVCenter | Qt.AlignRight,
                             title)
        # draw text
        self.doc.setText(text, formats)
        self.doc.setTextWidth(w - 26)
        painter.translate(x + 14, y + self.titleArea_h + 2)
        self.doc.drawContentsColor(painter, QRect(0, 0, w - 26, self.text_h),
                                   self.c_text)
        painter.resetTransform()
        # draw tags
        if tags:
            painter.setPen(self.c_gray)
            painter.setFont(font.default)
            painter.translate(x + 15, y + self.titleArea_h + 6 + self.text_h)
            real_x, max_x = x + 15, w - 10
            for t in tags.split():
                oneTag_w = font.default_m.width(t) + 4
                real_x += oneTag_w + 15
                if real_x > max_x: break
                tagPath = QPainterPath()
                tagPath.moveTo(8, 0)
                tagPath.lineTo(8 + oneTag_w, 0)
                tagPath.lineTo(8 + oneTag_w, self.tagPath_h)
                tagPath.lineTo(8, self.tagPath_h)
                tagPath.lineTo(0, self.tagPath_h / 2)
                tagPath.closeSubpath()
                painter.drawPath(tagPath)
                painter.drawText(8, 0, oneTag_w, self.tagPath_h,
                                 Qt.AlignCenter, t)
                painter.translate(oneTag_w + 15, 0)  # translate by offset
            else:
                painter.resetTransform()
                return
            # draw ellipsis if too many tags
            painter.setPen(Qt.DotLine)
            painter.drawLine(-4, self.tagPath_h / 2, 2, self.tagPath_h / 2)
            painter.resetTransform()

    def sizeHint(self, option, index):
        tag_h = self.tag_h if index.sibling(index.row(), 4).data() else 0
        self.all_h = self.titleArea_h + 2 + self.text_h + tag_h + 6
        return QSize(-1, self.all_h + 3)  # 3 is spacing between entries