Exemplo n.º 1
0
 def paintEvent(self, event):
     if self.pixmap.isNull():
         return
     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, min(canvas_size.width(), width),
                    min(canvas_size.height(), height))
     p = QPainter(self)
     p.setRenderHints(QPainter.RenderHint.Antialiasing
                      | QPainter.RenderHint.SmoothPixmapTransform)
     p.drawPixmap(
         target,
         self.pixmap.scaled(target.size(),
                            Qt.AspectRatioMode.KeepAspectRatio,
                            Qt.TransformationMode.SmoothTransformation))
     p.end()
Exemplo n.º 2
0
 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.RenderHint.Antialiasing | QPainter.RenderHint.SmoothPixmapTransform)
     try:
         dpr = self.devicePixelRatioF()
     except AttributeError:
         dpr = self.devicePixelRatio()
     spmap = self.pixmap.scaled(target.size() * dpr, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation)
     spmap.setDevicePixelRatio(dpr)
     p.drawPixmap(target, spmap)
     if gprefs['bd_overlay_cover_size']:
         sztgt = target.adjusted(0, 0, 0, -4)
         f = p.font()
         f.setBold(True)
         p.setFont(f)
         sz = '\u00a0%d x %d\u00a0'%(self.pixmap.width(), self.pixmap.height())
         flags = Qt.AlignmentFlag.AlignBottom|Qt.AlignmentFlag.AlignRight|Qt.TextFlag.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()
Exemplo n.º 3
0
 def resizeEvent(self, ev):
     PlainTextEdit.resizeEvent(self, ev)
     cr = self.contentsRect()
     if self.right:
         self.line_number_area.setGeometry(QRect(cr.right() - self.line_number_area_width(), cr.top(), cr.right(), cr.height()))
     else:
         self.line_number_area.setGeometry(QRect(cr.left(), cr.top(), self.line_number_area_width(), cr.height()))
     self.resized.emit()
Exemplo n.º 4
0
    def do_layout(self):
        fm = self.fontMetrics()
        bounding_rect = lambda text: fm.boundingRect(0, 0, 10000, 10000, Cell.
                                                     FLAGS, text)
        line_spacing = 2
        side_margin = Cell.SIDE_MARGIN
        self.rows = []
        ypos = line_spacing + (1 if self.is_first else 0)
        if 'href' in self.data:
            name = self.data['href']
            if isinstance(name, list):
                name = self.html_name
            br1 = bounding_rect(name)
            sel = self.data['selector'] or ''
            if self.data['type'] == 'inline':
                sel = 'style=""'
            br2 = bounding_rect(sel)
            self.hyperlink_rect = QRect(side_margin, ypos, br1.width(),
                                        br1.height())
            self.rows.append([
                Cell(name,
                     self.hyperlink_rect,
                     color_role=QPalette.ColorRole.Link),
                Cell(sel,
                     QRect(br1.right() + side_margin, ypos, br2.width(),
                           br2.height()),
                     right_align=True)
            ])
            ypos += max(br1.height(), br2.height()) + 2 * line_spacing
            self.lines_for_copy.append(name + ' ' + sel)

        for prop in self.data['properties']:
            text = prop.name + ':\xa0'
            br1 = bounding_rect(text)
            vtext = prop.value + '\xa0' + ('!' if prop.important else
                                           '') + prop.important
            br2 = bounding_rect(vtext)
            self.rows.append([
                Cell(text,
                     QRect(side_margin, ypos, br1.width(), br1.height()),
                     color_role=QPalette.ColorRole.LinkVisited,
                     is_overriden=prop.is_overriden),
                Cell(vtext,
                     QRect(br1.right() + side_margin, ypos, br2.width(),
                           br2.height()),
                     swatch=prop.color,
                     is_overriden=prop.is_overriden)
            ])
            self.lines_for_copy.append(text + vtext)
            if prop.is_overriden:
                self.lines_for_copy[-1] += ' [overridden]'
            ypos += max(br1.height(), br2.height()) + line_spacing
        self.lines_for_copy.append('--------------------------\n')

        self.height_hint = ypos + line_spacing
        self.width_hint = max(row[-1].rect.right() + side_margin
                              for row in self.rows) if self.rows else 0
Exemplo n.º 5
0
 def paint(self, painter, option, index):
     QStyledItemDelegate.paint(self, painter, option, index)
     style = QApplication.style()
     waiting = self.animator.is_running() and bool(index.data(Qt.ItemDataRole.UserRole))
     if waiting:
         rect = QRect(0, 0, self.spinner_width, self.spinner_width)
         rect.moveCenter(option.rect.center())
         self.animator.draw(painter, rect, self.color)
     else:
         # Ensure the cover is rendered over any selection rect
         style.drawItemPixmap(painter, option.rect, Qt.AlignmentFlag.AlignTop|Qt.AlignmentFlag.AlignHCenter,
             QPixmap(index.data(Qt.ItemDataRole.DecorationRole)))
Exemplo n.º 6
0
 def grid_bounds(self):
     #return QRect(-100, -100, 200, 200)
     it = iter(self.grid)
     try:
         minx, miny = next(it)
         maxx = minx
         maxy = miny
     except StopIteration:
         return QRect()
     for x, y in it:
         if   x < minx: minx = x
         elif x > maxx: maxx = x
         if   y < miny: miny = y
         elif y > maxy: maxy = y
     return QRect(minx, miny, maxx-minx+1, maxy-miny+1)
Exemplo n.º 7
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(int(nw * pmap.devicePixelRatio()),
                            int(nh * pmap.devicePixelRatio()),
                            Qt.AspectRatioMode.IgnoreAspectRatio,
                            Qt.TransformationMode.SmoothTransformation)
     w, h = int(pmap.width() / pmap.devicePixelRatio()), int(
         pmap.height() / pmap.devicePixelRatio())
     x = int(abs(cw - w) / 2)
     y = int(abs(ch - h) / 2)
     target = QRect(x, y, w, h)
     p = QPainter(self)
     p.setRenderHints(QPainter.RenderHint.Antialiasing
                      | QPainter.RenderHint.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:
         draw_size(p, target, ow, oh)
     p.end()
Exemplo n.º 8
0
def generate_cover(mi, prefs=None, as_qimage=False):
    init_environment()
    prefs = prefs or cprefs
    prefs = {k: prefs.get(k) for k in cprefs.defaults}
    prefs = Prefs(**prefs)
    color_theme = random.choice(load_color_themes(prefs))
    style = random.choice(load_styles(prefs))(color_theme, prefs)
    title, subtitle, footer = format_text(mi, prefs)
    img = QImage(prefs.cover_width, prefs.cover_height,
                 QImage.Format.Format_ARGB32)
    title_block, subtitle_block, footer_block = layout_text(
        prefs, img, title, subtitle, footer,
        img.height() // 3, style)
    p = QPainter(img)
    rect = QRect(0, 0, img.width(), img.height())
    colors = style(p, rect, color_theme, title_block, subtitle_block,
                   footer_block)
    for block, color in zip((title_block, subtitle_block, footer_block),
                            colors):
        p.setPen(color)
        block.draw(p)
    p.end()
    img.setText('Generated cover', '{} {}'.format(__appname__, __version__))
    if as_qimage:
        return img
    return pixmap_to_data(img)
Exemplo n.º 9
0
    def paint(self, painter, option, index):
        QStyledItemDelegate.paint(
            self, painter, option,
            empty_index)  # draw the hover and selection highlights
        name = str(index.data(Qt.ItemDataRole.DisplayRole) or '')
        cover = self.cover_cache.get(name, None)
        if cover is None:
            cover = self.cover_cache[name] = QPixmap()
            try:
                raw = current_container().raw_data(name, decode=False)
            except:
                pass
            else:
                try:
                    dpr = painter.device().devicePixelRatioF()
                except AttributeError:
                    dpr = painter.device().devicePixelRatio()
                cover.loadFromData(raw)
                cover.setDevicePixelRatio(dpr)
                if not cover.isNull():
                    scaled, width, height = fit_image(cover.width(),
                                                      cover.height(),
                                                      self.cover_size.width(),
                                                      self.cover_size.height())
                    if scaled:
                        cover = self.cover_cache[name] = cover.scaled(
                            int(dpr * width),
                            int(dpr * height),
                            transformMode=Qt.TransformationMode.
                            SmoothTransformation)

        painter.save()
        try:
            rect = option.rect
            rect.adjust(self.MARGIN, self.MARGIN, -self.MARGIN, -self.MARGIN)
            trect = QRect(rect)
            rect.setBottom(rect.bottom() - self.title_height)
            if not cover.isNull():
                dx = max(
                    0,
                    int((rect.width() -
                         int(cover.width() / cover.devicePixelRatio())) / 2.0))
                dy = max(
                    0,
                    rect.height() -
                    int(cover.height() / cover.devicePixelRatio()))
                rect.adjust(dx, dy, -dx, 0)
                painter.drawPixmap(rect, cover)
            rect = trect
            rect.setTop(rect.bottom() - self.title_height + 5)
            painter.setRenderHint(QPainter.RenderHint.TextAntialiasing, True)
            metrics = painter.fontMetrics()
            painter.drawText(
                rect,
                Qt.AlignmentFlag.AlignCenter | Qt.TextFlag.TextSingleLine,
                metrics.elidedText(name, Qt.TextElideMode.ElideLeft,
                                   rect.width()))
        finally:
            painter.restore()
Exemplo n.º 10
0
 def __init__(self, parent=None, icon_size=18):
     super().__init__(parent)
     self.icon_size = QSize(icon_size, icon_size)
     self.setSizePolicy(QSizePolicy.Policy.Preferred,
                        QSizePolicy.Policy.Preferred)
     self.items = []
     self.button_map = {}
     self.applied_geometry = QRect(0, 0, 0, 0)
Exemplo n.º 11
0
 def __call__(self, painter, rect, color_theme, title_block, subtitle_block, footer_block):
     painter.fillRect(rect, self.color1)
     y = rect.height() - rect.height() // 3
     r = QRect(rect)
     r.setBottom(y)
     painter.fillRect(rect, self.color1)
     r = QRect(rect)
     r.setTop(y)
     painter.fillRect(r, self.color2)
     return self.ccolor1, self.ccolor1, self.ccolor2
Exemplo n.º 12
0
def calibre_cover2(title,
                   author_string='',
                   series_string='',
                   prefs=None,
                   as_qimage=False,
                   logo_path=None):
    init_environment()
    title, subtitle, footer = '<b>' + escape_formatting(
        title), '<i>' + escape_formatting(
            series_string), '<b>' + escape_formatting(author_string)
    prefs = prefs or cprefs
    prefs = {k: prefs.get(k) for k in cprefs.defaults}
    scale = 800. / prefs['cover_height']
    scale_cover(prefs, scale)
    prefs = Prefs(**prefs)
    img = QImage(prefs.cover_width, prefs.cover_height,
                 QImage.Format.Format_ARGB32)
    img.fill(Qt.GlobalColor.white)
    # colors = to_theme('ffffff ffffff 000000 000000')
    color_theme = theme_to_colors(fallback_colors)

    class CalibeLogoStyle(Style):
        NAME = GUI_NAME = 'calibre'

        def __call__(self, painter, rect, color_theme, title_block,
                     subtitle_block, footer_block):
            top = title_block.position.y + 10
            extra_spacing = subtitle_block.line_spacing // 2 if subtitle_block.line_spacing else title_block.line_spacing // 3
            height = title_block.height + subtitle_block.height + extra_spacing + title_block.leading
            top += height + 25
            bottom = footer_block.position.y - 50
            logo = QImage(logo_path or I('library.png'))
            pwidth, pheight = rect.width(), bottom - top
            scaled, width, height = fit_image(logo.width(), logo.height(),
                                              pwidth, pheight)
            x, y = (pwidth - width) // 2, (pheight - height) // 2
            rect = QRect(x, top + y, width, height)
            painter.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform)
            painter.drawImage(rect, logo)
            return self.ccolor1, self.ccolor1, self.ccolor1

    style = CalibeLogoStyle(color_theme, prefs)
    title_block, subtitle_block, footer_block = layout_text(
        prefs, img, title, subtitle, footer,
        img.height() // 3, style)
    p = QPainter(img)
    rect = QRect(0, 0, img.width(), img.height())
    colors = style(p, rect, color_theme, title_block, subtitle_block,
                   footer_block)
    for block, color in zip((title_block, subtitle_block, footer_block),
                            colors):
        p.setPen(color)
        block.draw(p)
    p.end()
    img.setText('Generated cover', '{} {}'.format(__appname__, __version__))
    if as_qimage:
        return img
    return pixmap_to_data(img)
Exemplo n.º 13
0
    def paintEvent(self, event):
        w = self.viewport().rect().width()
        painter = QPainter(self.viewport())
        painter.setClipRect(event.rect())
        painter.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform, True)
        floor = event.rect().bottom()
        ceiling = event.rect().top()
        fv = self.firstVisibleBlock().blockNumber()
        origin = self.contentOffset()
        doc = self.document()
        lines = []

        for num, text in self.headers:
            top, bot = num, num + 3
            if bot < fv:
                continue
            y_top = self.blockBoundingGeometry(doc.findBlockByNumber(top)).translated(origin).y()
            y_bot = self.blockBoundingGeometry(doc.findBlockByNumber(bot)).translated(origin).y()
            if max(y_top, y_bot) < ceiling:
                continue
            if min(y_top, y_bot) > floor:
                break
            painter.setFont(self.heading_font)
            br = painter.drawText(3, y_top, w, y_bot - y_top - 5, Qt.TextFlag.TextSingleLine, text)
            painter.setPen(QPen(self.palette().text(), 2))
            painter.drawLine(0, br.bottom()+3, w, br.bottom()+3)

        for top, bot, kind in self.changes:
            if bot < fv:
                continue
            y_top = self.blockBoundingGeometry(doc.findBlockByNumber(top)).translated(origin).y()
            y_bot = self.blockBoundingGeometry(doc.findBlockByNumber(bot)).translated(origin).y()
            if max(y_top, y_bot) < ceiling:
                continue
            if min(y_top, y_bot) > floor:
                break
            if y_top != y_bot:
                painter.fillRect(0,  y_top, w, y_bot - y_top, self.diff_backgrounds[kind])
            lines.append((y_top, y_bot, kind))
            if top in self.images:
                img, maxw = self.images[top][:2]
                if bot > top + 1 and not img.isNull():
                    y_top = self.blockBoundingGeometry(doc.findBlockByNumber(top+1)).translated(origin).y() + 3
                    y_bot -= 3
                    scaled, imgw, imgh = fit_image(int(img.width()/img.devicePixelRatio()), int(img.height()/img.devicePixelRatio()), w - 3, y_bot - y_top)
                    painter.drawPixmap(QRect(3, y_top, imgw, imgh), img)

        painter.end()
        PlainTextEdit.paintEvent(self, event)
        painter = QPainter(self.viewport())
        painter.setClipRect(event.rect())
        for top, bottom, kind in sorted(lines, key=lambda t_b_k:{'replace':0}.get(t_b_k[2], 1)):
            painter.setPen(QPen(self.diff_foregrounds[kind], 1))
            painter.drawLine(0, top, w, top)
            painter.drawLine(0, bottom - 1, w, bottom - 1)
Exemplo n.º 14
0
 def do_layout(self, rect):
     if len(self._children) != 2:
         return
     left, top, right, bottom = self.getContentsMargins()
     r = rect.adjusted(+left, +top, -right, -bottom)
     x = r.x()
     y = r.y()
     cover, details = self._children
     if self.vertical:
         ch = self.cover_height(r)
         cover.setGeometry(QRect(x, y, r.width(), ch))
         cover.widget().do_layout()
         y += ch + 5
         details.setGeometry(QRect(x, y, r.width(), r.height()-ch-5))
     else:
         cw = self.cover_width(r)
         cover.setGeometry(QRect(x, y, cw, r.height()))
         cover.widget().do_layout()
         x += cw + 5
         details.setGeometry(QRect(x, y, r.width() - cw - 5, r.height()))
Exemplo n.º 15
0
 def paintEvent(self, ev):
     br = ev.region().boundingRect()
     QWidget.paintEvent(self, ev)
     p = QPainter(self)
     p.setClipRect(br)
     f = p.font()
     f.setBold(True)
     f.setPointSize(20)
     p.setFont(f)
     p.setPen(Qt.PenStyle.SolidLine)
     r = QRect(0, self.dummy.geometry().top() + 10, self.geometry().width(), 150)
     p.drawText(r, Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignTop | Qt.TextFlag.TextSingleLine, self.text)
     p.end()
Exemplo n.º 16
0
 def __call__(self, painter, rect, color_theme, title_block, subtitle_block, footer_block):
     top = title_block.position.y + 10
     extra_spacing = subtitle_block.line_spacing // 2 if subtitle_block.line_spacing else title_block.line_spacing // 3
     height = title_block.height + subtitle_block.height + extra_spacing + title_block.leading
     top += height + 25
     bottom = footer_block.position.y - 50
     logo = QImage(logo_path or I('library.png'))
     pwidth, pheight = rect.width(), bottom - top
     scaled, width, height = fit_image(logo.width(), logo.height(), pwidth, pheight)
     x, y = (pwidth - width) // 2, (pheight - height) // 2
     rect = QRect(x, top + y, width, height)
     painter.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform)
     painter.drawImage(rect, logo)
     return self.ccolor1, self.ccolor1, self.ccolor1
Exemplo n.º 17
0
    def do_layout(self, rect, apply_geometry=False):
        left, top, right, bottom = self.getContentsMargins()
        erect = rect.adjusted(left, top, -right, -bottom)
        x, y = erect.x(), erect.y()

        line_height = 0

        def layout_spacing(wid, horizontal=True):
            ans = self.smart_spacing(horizontal)
            if ans != -1:
                return ans
            if wid is None:
                return 0
            return wid.style().layoutSpacing(
                QSizePolicy.ControlType.PushButton,
                QSizePolicy.ControlType.PushButton, Qt.Orientation.Horizontal
                if horizontal else Qt.Orientation.Vertical)

        lines, current_line = [], []
        gmap = {}
        for item in self.items:
            isz, wid = item.sizeHint(), item.widget()
            hs, vs = layout_spacing(wid), layout_spacing(wid, False)

            next_x = x + isz.width() + hs
            if next_x - hs > erect.right() and line_height > 0:
                x = erect.x()
                y = y + line_height + vs
                next_x = x + isz.width() + hs
                lines.append((line_height, current_line))
                current_line = []
                line_height = 0
            if apply_geometry:
                gmap[item] = x, y, isz
            x = next_x
            line_height = max(line_height, isz.height())
            current_line.append((item, isz.height()))

        lines.append((line_height, current_line))

        if apply_geometry:
            for line_height, items in lines:
                for item, item_height in items:
                    x, wy, isz = gmap[item]
                    if item_height < line_height:
                        wy += (line_height - item_height) // 2
                    item.setGeometry(QRect(QPoint(x, wy), isz))

        return y + line_height - rect.y() + bottom
Exemplo n.º 18
0
 def draw(self, painter, width, palette):
     flags = self.FLAGS | (Qt.AlignmentFlag.AlignRight if self.right_align else Qt.AlignmentFlag.AlignLeft)
     rect = QRect(self.rect)
     if self.right_align:
         rect.setRight(width - self.SIDE_MARGIN)
     painter.setPen(palette.color(self.color_role) if self.override_color is None else self.override_color)
     br = painter.drawText(rect, flags, self.text)
     if self.swatch is not None:
         r = QRect(br.right() + self.SIDE_MARGIN // 2, br.top() + 2, br.height() - 4, br.height() - 4)
         painter.fillRect(r, self.swatch)
         br.setRight(r.right())
     if self.is_overriden:
         painter.setPen(palette.color(QPalette.ColorRole.WindowText))
         painter.drawLine(br.left(), br.top() + br.height() // 2, br.right(), br.top() + br.height() // 2)
Exemplo n.º 19
0
 def __call__(self, painter, rect, color_theme, title_block, subtitle_block, footer_block):
     painter.fillRect(rect, self.color1)
     r = QRect(0, int(title_block.position.y), rect.width(),
               title_block.height + subtitle_block.height + subtitle_block.line_spacing // 2 + title_block.leading)
     painter.save()
     p = QPainterPath()
     p.addRoundedRect(QRectF(r), 10, 10 * r.width()/r.height(), Qt.SizeMode.RelativeSize)
     painter.setClipPath(p)
     painter.setRenderHint(QPainter.RenderHint.Antialiasing)
     painter.fillRect(r, self.color2)
     painter.restore()
     r = QRect(0, 0, int(title_block.position.x), rect.height())
     painter.fillRect(r, self.color2)
     return self.ccolor2, self.ccolor2, self.ccolor1
Exemplo n.º 20
0
 def paintEvent(self, ev):
     painter = QStylePainter(self)
     opt = QStyleOptionToolButton()
     self.initStyleOption(opt)
     text = opt.text
     opt.text = ''
     opt.icon = QIcon()
     s = painter.style()
     painter.drawComplexControl(QStyle.ComplexControl.CC_ToolButton, opt)
     if s.styleHint(QStyle.StyleHint.SH_UnderlineShortcut, opt, self):
         flags = self.text_flags | Qt.TextFlag.TextShowMnemonic
     else:
         flags = self.text_flags | Qt.TextFlag.TextHideMnemonic
     fw = s.pixelMetric(QStyle.PixelMetric.PM_DefaultFrameWidth, opt, self)
     opt.rect.adjust(fw, fw, -fw, -fw)
     w = opt.iconSize.width()
     text_rect = opt.rect.adjusted(w, 0, 0, 0)
     painter.drawItemText(text_rect, flags, opt.palette, self.isEnabled(), text)
     fm = QFontMetrics(opt.font)
     text_rect = s.itemTextRect(fm, text_rect, flags, self.isEnabled(), text)
     left = text_rect.left() - w - 4
     pixmap_rect = QRect(left, opt.rect.top(), opt.iconSize.width(), opt.rect.height())
     painter.drawItemPixmap(pixmap_rect, Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter, self.icon().pixmap(opt.iconSize))
Exemplo n.º 21
0
    def do_layout(self, rect, apply_geometry=False):
        x, y = rect.x(), rect.y()

        line_height = 0

        def layout_spacing(wid, horizontal=True):
            ans = self.smart_spacing(horizontal)
            if ans != -1:
                return ans
            return wid.style().layoutSpacing(
                QSizePolicy.ControlType.ToolButton,
                QSizePolicy.ControlType.ToolButton, Qt.Orientation.Horizontal
                if horizontal else Qt.Orientation.Vertical)

        lines, current_line = [], []
        gmap = {}
        if apply_geometry:
            for item in self.items:
                if isinstance(item, Separator):
                    item.setGeometry(0, 0, 0, 0)

        def commit_line():
            while current_line and isinstance(current_line[-1], Separator):
                current_line.pop()
            if current_line:
                lines.append((line_height, current_line))

        for wid in self.items:
            if not wid.isVisible() or (not current_line
                                       and isinstance(wid, Separator)):
                continue
            isz = wid.sizeHint()
            hs, vs = layout_spacing(wid), layout_spacing(wid, False)

            next_x = x + isz.width() + hs
            if next_x - hs > rect.right() and line_height > 0:
                if isinstance(wid, Separator):
                    continue
                x = rect.x()
                y = y + line_height + vs
                next_x = x + isz.width() + hs
                commit_line()
                current_line = []
                line_height = 0
            if apply_geometry:
                gmap[wid] = x, y, isz
            x = next_x
            line_height = max(line_height, isz.height())
            current_line.append(wid)

        commit_line()

        if apply_geometry:
            self.applied_geometry = rect
            for line_height, items in lines:
                for wid in items:
                    x, wy, isz = gmap[wid]
                    if isz.height() < line_height:
                        wy += (line_height - isz.height()) // 2
                    if wid.isVisible():
                        wid.setGeometry(QRect(QPoint(x, wy), isz))

        return y + line_height - rect.y()
Exemplo n.º 22
0
 def heightForWidth(self, width):
     return self.do_layout(QRect(0, 0, width, 0), apply_geometry=False)
Exemplo n.º 23
0
 def rect_at(self, frac):
     return QRect(self.point_at(frac), self.size())
Exemplo n.º 24
0
 def resizeEvent(self, ev):
     QPlainTextEdit.resizeEvent(self, ev)
     cr = self.contentsRect()
     self.line_number_area.setGeometry(QRect(cr.left(), cr.top(), self.line_number_area_width(), cr.height()))
Exemplo n.º 25
0
 def paint_embossed_emblem(self,
                           pixmap,
                           painter,
                           orect,
                           right_adjust,
                           left=True):
     drect = QRect(orect)
     pw = int(pixmap.width() / pixmap.devicePixelRatio())
     ph = int(pixmap.height() / pixmap.devicePixelRatio())
     if left:
         drect.setLeft(drect.left() + right_adjust)
         drect.setRight(drect.left() + pw)
     else:
         drect.setRight(drect.right() - right_adjust)
         drect.setLeft(drect.right() - pw + 1)
     drect.setBottom(drect.bottom() - self.title_height)
     drect.setTop(drect.bottom() - ph)
     painter.drawPixmap(drect, pixmap)
Exemplo n.º 26
0
 def paint_emblems(self, painter, rect, emblems):
     gutter = self.emblem_size + self.MARGIN
     grect = QRect(rect)
     gpos = self.gutter_position
     if gpos is self.TOP:
         grect.setBottom(grect.top() + gutter)
         rect.setTop(rect.top() + gutter)
     elif gpos is self.BOTTOM:
         grect.setTop(grect.bottom() - gutter + self.MARGIN)
         rect.setBottom(rect.bottom() - gutter)
     elif gpos is self.LEFT:
         grect.setRight(grect.left() + gutter)
         rect.setLeft(rect.left() + gutter)
     else:
         grect.setLeft(grect.right() - gutter + self.MARGIN)
         rect.setRight(rect.right() - gutter)
     horizontal = gpos in (self.TOP, self.BOTTOM)
     painter.save()
     painter.setClipRect(grect)
     try:
         for i, emblem in enumerate(emblems):
             delta = 0 if i == 0 else self.emblem_size + self.MARGIN
             grect.moveLeft(grect.left() +
                            delta) if horizontal else grect.moveTop(
                                grect.top() + delta)
             rect = QRect(grect)
             rect.setWidth(int(emblem.width() /
                               emblem.devicePixelRatio())), rect.setHeight(
                                   int(emblem.height() /
                                       emblem.devicePixelRatio()))
             painter.drawPixmap(rect, emblem)
     finally:
         painter.restore()
Exemplo n.º 27
0
    def paint(self, painter, option, index):
        QStyledItemDelegate.paint(
            self, painter, option,
            empty_index)  # draw the hover and selection highlights
        m = index.model()
        db = m.db
        try:
            book_id = db.id(index.row())
        except (ValueError, IndexError, KeyError):
            return
        if book_id in m.ids_to_highlight_set:
            painter.save()
            try:
                painter.setPen(self.highlight_color)
                painter.setRenderHint(QPainter.RenderHint.Antialiasing, True)
                painter.drawRoundedRect(option.rect, 10, 10,
                                        Qt.SizeMode.RelativeSize)
            finally:
                painter.restore()
        marked = db.data.get_marked(book_id)
        db = db.new_api
        cdata = self.cover_cache[book_id]
        device_connected = self.parent().gui.device_connected is not None
        on_device = device_connected and db.field_for('ondevice', book_id)

        emblem_rules = db.pref('cover_grid_icon_rules', default=())
        emblems = []
        if self.emblem_size > 0:
            mi = None
            for i, (kind, column, rule) in enumerate(emblem_rules):
                icon_name, mi = self.render_emblem(book_id, rule, i,
                                                   m.cover_grid_emblem_cache,
                                                   mi, db, m.formatter,
                                                   m.cover_grid_template_cache)
                if icon_name is not None:
                    for one_icon in filter(None,
                                           (i.strip()
                                            for i in icon_name.split(':'))):
                        pixmap = self.cached_emblem(m.cover_grid_bitmap_cache,
                                                    one_icon)
                        if pixmap is not None:
                            emblems.append(pixmap)
            if marked:
                emblems.insert(
                    0,
                    self.cached_emblem(m.cover_grid_bitmap_cache, ':marked',
                                       m.marked_icon))
            if on_device:
                emblems.insert(
                    0,
                    self.cached_emblem(m.cover_grid_bitmap_cache, ':ondevice'))

        painter.save()
        right_adjust = 0
        try:
            rect = option.rect
            rect.adjust(self.MARGIN, self.MARGIN, -self.MARGIN, -self.MARGIN)
            if self.emblem_size > 0:
                self.paint_emblems(painter, rect, emblems)
            orect = QRect(rect)
            trect = QRect(rect)
            if self.title_height != 0:
                rect.setBottom(rect.bottom() - self.title_height)
                trect.setTop(trect.bottom() - self.title_height + 5)
            if cdata is None or cdata is False:
                title = db.field_for('title', book_id, default_value='')
                authors = ' & '.join(
                    db.field_for('authors', book_id, default_value=()))
                painter.setRenderHint(QPainter.RenderHint.TextAntialiasing,
                                      True)
                painter.drawText(
                    rect,
                    Qt.AlignmentFlag.AlignCenter | Qt.TextFlag.TextWordWrap,
                    '%s\n\n%s' % (title, authors))
                if cdata is False:
                    self.render_queue.put(book_id)
                if self.title_height != 0:
                    self.paint_title(painter, trect, db, book_id)
            else:
                if self.animating is not None and self.animating.row(
                ) == index.row():
                    cdata = cdata.scaled(cdata.size() * self._animated_size)
                dpr = cdata.devicePixelRatio()
                cw, ch = int(cdata.width() / dpr), int(cdata.height() / dpr)
                dx = max(0, int((rect.width() - cw) / 2.0))
                dy = max(0, int((rect.height() - ch) / 2.0))
                right_adjust = dx
                rect.adjust(dx, dy, -dx, -dy)
                painter.drawPixmap(rect, cdata)
                if self.title_height != 0:
                    self.paint_title(painter, trect, db, book_id)
            if self.emblem_size > 0:
                return  # We dont draw embossed emblems as the ondevice/marked emblems are drawn in the gutter
            if marked:
                try:
                    p = self.marked_emblem
                except AttributeError:
                    p = self.marked_emblem = m.marked_icon.pixmap(48, 48)
                self.paint_embossed_emblem(p, painter, orect, right_adjust)

            if on_device:
                try:
                    p = self.on_device_emblem
                except AttributeError:
                    p = self.on_device_emblem = QIcon(I('ok.png')).pixmap(
                        48, 48)
                self.paint_embossed_emblem(p,
                                           painter,
                                           orect,
                                           right_adjust,
                                           left=False)
        finally:
            painter.restore()
Exemplo n.º 28
0
def drag_icon(self, cover, multiple):
    cover = cover.scaledToHeight(120,
                                 Qt.TransformationMode.SmoothTransformation)
    if multiple:
        base_width = cover.width()
        base_height = cover.height()
        base = QImage(base_width + 21, base_height + 21,
                      QImage.Format.Format_ARGB32_Premultiplied)
        base.fill(QColor(255, 255, 255, 0).rgba())
        p = QPainter(base)
        rect = QRect(20, 0, base_width, base_height)
        p.fillRect(rect, QColor('white'))
        p.drawRect(rect)
        rect.moveLeft(10)
        rect.moveTop(10)
        p.fillRect(rect, QColor('white'))
        p.drawRect(rect)
        rect.moveLeft(0)
        rect.moveTop(20)
        p.fillRect(rect, QColor('white'))
        p.save()
        p.setCompositionMode(
            QPainter.CompositionMode.CompositionMode_SourceAtop)
        p.drawImage(rect.topLeft(), cover)
        p.restore()
        p.drawRect(rect)
        p.end()
        cover = base
    return QPixmap.fromImage(cover)
Exemplo n.º 29
0
def decoration_for_style(palette, style, icon_size, device_pixel_ratio, is_dark):
    style_key = (is_dark, icon_size, device_pixel_ratio, tuple((k, style[k]) for k in sorted(style)))
    sentinel = object()
    ans = decoration_cache.get(style_key, sentinel)
    if ans is not sentinel:
        return ans
    ans = None
    kind = style.get('kind')
    if kind == 'color':
        key = 'dark' if is_dark else 'light'
        val = style.get(key)
        if val is None:
            which = style.get('which')
            val = (builtin_colors_dark if is_dark else builtin_colors_light).get(which)
        if val is None:
            val = style.get('background-color')
        if val is not None:
            ans = QColor(val)
    elif kind == 'decoration':
        which = style.get('which')
        if which is not None:
            q = builtin_decorations.get(which)
            if q is not None:
                style = q
        sz = int(math.ceil(icon_size * device_pixel_ratio))
        canvas = QImage(sz, sz, QImage.Format.Format_ARGB32)
        canvas.fill(Qt.GlobalColor.transparent)
        canvas.setDevicePixelRatio(device_pixel_ratio)
        p = QPainter(canvas)
        p.setRenderHint(QPainter.RenderHint.Antialiasing, True)
        p.setPen(palette.color(QPalette.ColorRole.WindowText))
        irect = QRect(0, 0, icon_size, icon_size)
        adjust = -2
        text_rect = p.drawText(irect.adjusted(0, adjust, 0, adjust), Qt.AlignmentFlag.AlignHCenter| Qt.AlignmentFlag.AlignTop, 'a')
        p.drawRect(irect)
        fm = p.fontMetrics()
        pen = p.pen()
        if 'text-decoration-color' in style:
            pen.setColor(QColor(style['text-decoration-color']))
        lstyle = style.get('text-decoration-style') or 'solid'
        q = {'dotted': Qt.PenStyle.DotLine, 'dashed': Qt.PenStyle.DashLine, }.get(lstyle)
        if q is not None:
            pen.setStyle(q)
        lw = fm.lineWidth()
        if lstyle == 'double':
            lw * 2
        pen.setWidth(fm.lineWidth())
        q = style.get('text-decoration-line') or 'underline'
        pos = text_rect.bottom()
        height = irect.bottom() - pos
        if q == 'overline':
            pos = height
        elif q == 'line-through':
            pos = text_rect.center().y() - adjust - lw // 2
        p.setPen(pen)
        if lstyle == 'wavy':
            p.drawPath(wavy_path(icon_size, height, pos))
        else:
            p.drawLine(0, pos, irect.right(), pos)
        p.end()
        ans = QPixmap.fromImage(canvas)
    elif 'background-color' in style:
        ans = QColor(style['background-color'])
    decoration_cache[style_key] = ans
    return ans
Exemplo n.º 30
0
class Declaration(QWidget):

    hyperlink_activated = pyqtSignal(object)
    context_menu_requested = pyqtSignal(object, object)

    def __init__(self, html_name, data, is_first=False, parent=None):
        QWidget.__init__(self, parent)
        self.setSizePolicy(QSizePolicy.Policy.Preferred,
                           QSizePolicy.Policy.Minimum)
        self.data = data
        self.is_first = is_first
        self.html_name = html_name
        self.lines_for_copy = []
        self.do_layout()
        self.setMouseTracking(True)

    def do_layout(self):
        fm = self.fontMetrics()
        bounding_rect = lambda text: fm.boundingRect(0, 0, 10000, 10000, Cell.
                                                     FLAGS, text)
        line_spacing = 2
        side_margin = Cell.SIDE_MARGIN
        self.rows = []
        ypos = line_spacing + (1 if self.is_first else 0)
        if 'href' in self.data:
            name = self.data['href']
            if isinstance(name, list):
                name = self.html_name
            br1 = bounding_rect(name)
            sel = self.data['selector'] or ''
            if self.data['type'] == 'inline':
                sel = 'style=""'
            br2 = bounding_rect(sel)
            self.hyperlink_rect = QRect(side_margin, ypos, br1.width(),
                                        br1.height())
            self.rows.append([
                Cell(name,
                     self.hyperlink_rect,
                     color_role=QPalette.ColorRole.Link),
                Cell(sel,
                     QRect(br1.right() + side_margin, ypos, br2.width(),
                           br2.height()),
                     right_align=True)
            ])
            ypos += max(br1.height(), br2.height()) + 2 * line_spacing
            self.lines_for_copy.append(name + ' ' + sel)

        for prop in self.data['properties']:
            text = prop.name + ':\xa0'
            br1 = bounding_rect(text)
            vtext = prop.value + '\xa0' + ('!' if prop.important else
                                           '') + prop.important
            br2 = bounding_rect(vtext)
            self.rows.append([
                Cell(text,
                     QRect(side_margin, ypos, br1.width(), br1.height()),
                     color_role=QPalette.ColorRole.LinkVisited,
                     is_overriden=prop.is_overriden),
                Cell(vtext,
                     QRect(br1.right() + side_margin, ypos, br2.width(),
                           br2.height()),
                     swatch=prop.color,
                     is_overriden=prop.is_overriden)
            ])
            self.lines_for_copy.append(text + vtext)
            if prop.is_overriden:
                self.lines_for_copy[-1] += ' [overridden]'
            ypos += max(br1.height(), br2.height()) + line_spacing
        self.lines_for_copy.append('--------------------------\n')

        self.height_hint = ypos + line_spacing
        self.width_hint = max(row[-1].rect.right() + side_margin
                              for row in self.rows) if self.rows else 0

    def sizeHint(self):
        return QSize(self.width_hint, self.height_hint)

    def paintEvent(self, ev):
        p = QPainter(self)
        p.setClipRect(ev.rect())
        palette = self.palette()
        p.setPen(palette.color(QPalette.ColorRole.WindowText))
        if not self.is_first:
            p.drawLine(0, 0, self.width(), 0)
        try:
            for row in self.rows:
                for cell in row:
                    p.save()
                    try:
                        cell.draw(p, self.width(), palette)
                    finally:
                        p.restore()

        finally:
            p.end()

    def mouseMoveEvent(self, ev):
        if hasattr(self, 'hyperlink_rect'):
            pos = ev.pos()
            hovering = self.hyperlink_rect.contains(pos)
            self.update_hover(hovering)
            cursor = Qt.CursorShape.ArrowCursor
            for r, row in enumerate(self.rows):
                for cell in row:
                    if cell.rect.contains(pos):
                        cursor = Qt.CursorShape.PointingHandCursor if cell.rect is self.hyperlink_rect else Qt.CursorShape.IBeamCursor
                    if r == 0:
                        break
                if cursor != Qt.CursorShape.ArrowCursor:
                    break
            self.setCursor(cursor)
        return QWidget.mouseMoveEvent(self, ev)

    def mousePressEvent(self, ev):
        if hasattr(
                self,
                'hyperlink_rect') and ev.button() == Qt.MouseButton.LeftButton:
            pos = ev.pos()
            if self.hyperlink_rect.contains(pos):
                self.emit_hyperlink_activated()
        return QWidget.mousePressEvent(self, ev)

    def emit_hyperlink_activated(self):
        dt = self.data['type']
        data = {'type': dt, 'name': self.html_name, 'syntax': 'html'}
        if dt == 'inline':  # style attribute
            data['sourceline_address'] = self.data['href']
        elif dt == 'elem':  # <style> tag
            data['sourceline_address'] = self.data['href']
            data['rule_address'] = self.data['rule_address']
        else:  # stylesheet
            data['name'] = self.data['href']
            data['rule_address'] = self.data['rule_address']
            data['syntax'] = 'css'
        self.hyperlink_activated.emit(data)

    def leaveEvent(self, ev):
        self.update_hover(False)
        self.setCursor(Qt.CursorShape.ArrowCursor)
        return QWidget.leaveEvent(self, ev)

    def update_hover(self, hovering):
        cell = self.rows[0][0]
        if (hovering and cell.override_color is None) or (
                not hovering and cell.override_color is not None):
            cell.override_color = QColor(
                Qt.GlobalColor.red) if hovering else None
            self.update()

    def contextMenuEvent(self, ev):
        self.context_menu_requested.emit(self, ev)