Esempio n. 1
0
def dnd_get_local_image_and_pixmap(md, image_exts=None):
    if md.hasImage():
        for x in md.formats():
            x = unicode_type(x)
            if x.startswith('image/'):
                cdata = bytes(md.data(x))
                pmap = QPixmap()
                pmap.loadFromData(cdata)
                if not pmap.isNull():
                    return pmap, cdata
    if md.hasFormat('application/octet-stream'):
        cdata = bytes(md.data('application/octet-stream'))
        pmap = QPixmap()
        pmap.loadFromData(cdata)
        if not pmap.isNull():
            return pmap, cdata

    if image_exts is None:
        image_exts = image_extensions()

    # No image, look for an URL pointing to an image
    urls = urls_from_md(md)
    paths = [path_from_qurl(u) for u in urls]
    # Look for a local file
    images = [xi for xi in paths if extension(xi) in image_exts]
    images = [xi for xi in images if os.path.exists(xi)]
    for path in images:
        try:
            with open(path, 'rb') as f:
                cdata = f.read()
        except Exception:
            continue
        p = QPixmap()
        p.loadFromData(cdata)
        if not p.isNull():
            return p, cdata

    return None, None
Esempio n. 2
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
Esempio n. 3
0
 def load_pixmap(self, data):
     pmap = QPixmap()
     pmap.loadFromData(data)
     pmap.setDevicePixelRatio(QApplication.instance().devicePixelRatio())
     return pmap
Esempio n. 4
0
    def initialize_metadata_options(self):
        self.initialize_combos()
        self.author.editTextChanged.connect(self.deduce_author_sort)

        mi = self.db.get_metadata(self.book_id, index_is_id=True)
        self.title.setText(mi.title), self.title.home(False)
        self.publisher.show_initial_value(mi.publisher if mi.publisher else '')
        self.publisher.home(False)
        self.author_sort.setText(mi.author_sort if mi.author_sort else '')
        self.author_sort.home(False)
        self.tags.setText(', '.join(mi.tags if mi.tags else []))
        self.tags.update_items_cache(self.db.new_api.all_field_names('tags'))
        self.tags.home(False)
        self.comment.html = comments_to_html(
            mi.comments) if mi.comments else ''
        self.series.show_initial_value(mi.series if mi.series else '')
        self.series.home(False)
        if mi.series_index is not None:
            try:
                self.series_index.setValue(mi.series_index)
            except:
                self.series_index.setValue(1.0)

        cover = self.db.cover(self.book_id, index_is_id=True)
        if cover:
            pm = QPixmap()
            pm.loadFromData(cover)
            if not pm.isNull():
                pm.setDevicePixelRatio(
                    getattr(self, 'devicePixelRatioF',
                            self.devicePixelRatio)())
                self.cover.setPixmap(pm)
                self.cover_data = cover
                self.set_cover_tooltip(pm)
        else:
            pm = QPixmap(I('default_cover.png'))
            pm.setDevicePixelRatio(
                getattr(self, 'devicePixelRatioF', self.devicePixelRatio)())
            self.cover.setPixmap(pm)
            self.cover.setToolTip(_('This book has no cover'))
        for x in ('author', 'series', 'publisher'):
            x = getattr(self, x)
            x.lineEdit().deselect()
        self.series_changed()
Esempio n. 5
0
 def __init__(self, parent=None):
     QWidget.__init__(self, parent)
     self.current_pixmap_size = QSize(0, 0)
     self.pixmap = QPixmap()
     self.setSizePolicy(QSizePolicy.Policy.Expanding,
                        QSizePolicy.Policy.Expanding)
Esempio n. 6
0
 def __init__(self, parent):
     self.current_img = QPixmap()
     self.current_url = QUrl()
     self.parent = parent
     self.dialogs = []
Esempio n. 7
0
        self.current_url = QUrl()
        self.parent = parent
        self.dialogs = []

    def __call__(self):
        if self.current_img.isNull():
            return
        d = ImageView(self.parent, self.current_img, self.current_url)
        self.dialogs.append(d)
        d.finished.connect(self.cleanup,
                           type=Qt.ConnectionType.QueuedConnection)
        d()

    def cleanup(self):
        for d in tuple(self.dialogs):
            if not d.isVisible():
                self.dialogs.remove(d)


if __name__ == '__main__':
    import sys

    from calibre.gui2 import Application
    app = Application([])
    p = QPixmap()
    p.load(sys.argv[-1])
    u = QUrl.fromLocalFile(sys.argv[-1])
    d = ImageView(None, p, u)
    d()
    app.exec()
Esempio n. 8
0
class ImageView(QWidget, ImageDropMixin):

    BORDER_WIDTH = 1
    cover_changed = pyqtSignal(object)

    def __init__(self,
                 parent=None,
                 show_size_pref_name=None,
                 default_show_size=False):
        QWidget.__init__(self, parent)
        self.show_size_pref_name = (
            'show_size_on_cover_' +
            show_size_pref_name) if show_size_pref_name else None
        self._pixmap = QPixmap()
        self.setMinimumSize(QSize(150, 200))
        ImageDropMixin.__init__(self)
        self.draw_border = True
        self.show_size = False
        if self.show_size_pref_name:
            self.show_size = gprefs.get(self.show_size_pref_name,
                                        default_show_size)

    def setPixmap(self, pixmap):
        if not isinstance(pixmap, QPixmap):
            raise TypeError('Must use a QPixmap')
        self._pixmap = pixmap
        self.updateGeometry()
        self.update()

    def build_context_menu(self):
        m = ImageDropMixin.build_context_menu(self)
        if self.show_size_pref_name:
            text = _('Hide size in corner') if self.show_size else _(
                'Show size in corner')
            m.addAction(text, self.toggle_show_size)
        return m

    def toggle_show_size(self):
        self.show_size ^= True
        if self.show_size_pref_name:
            gprefs[self.show_size_pref_name] = self.show_size
        self.update()

    def pixmap(self):
        return self._pixmap

    def sizeHint(self):
        if self._pixmap.isNull():
            return self.minimumSize()
        return self._pixmap.size()

    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()
Esempio n. 9
0
 def data(self, index, role):
     row, col = index.row(), index.column()
     if row >= len(self.matches):
         return None
     result = self.matches[row]
     if role == Qt.ItemDataRole.DisplayRole:
         if col == 1:
             t = result.title if result.title else _('Unknown')
             a = result.author if result.author else ''
             return (f'<b>{t}</b><br><i>{a}</i>')
         elif col == 2:
             return (result.price)
         elif col == 4:
             return (f'<span>{result.store_name}<br>{result.formats}</span>')
         return None
     elif role == Qt.ItemDataRole.DecorationRole:
         if col == 0 and result.cover_data:
             p = QPixmap()
             p.loadFromData(result.cover_data)
             p.setDevicePixelRatio(QApplication.instance().devicePixelRatio())
             return p
         if col == 3:
             if result.drm == SearchResult.DRM_LOCKED:
                 return (self.DRM_LOCKED_ICON)
             elif result.drm == SearchResult.DRM_UNLOCKED:
                 return (self.DRM_UNLOCKED_ICON)
             elif result.drm == SearchResult.DRM_UNKNOWN:
                 return (self.DRM_UNKNOWN_ICON)
         if col == 5:
             if result.downloads:
                 return (self.DOWNLOAD_ICON)
         if col == 6:
             if result.affiliate:
                 return (self.DONATE_ICON)
     elif role == Qt.ItemDataRole.ToolTipRole:
         if col == 1:
             return ('<p>%s</p>' % result.title)
         elif col == 2:
             if result.price:
                 return ('<p>' + _(
                     'Detected price as: %s. Check with the store before making a purchase'
                     ' to verify this price is correct. This price often does not include'
                     ' promotions the store may be running.') % result.price + '</p>')
             return '<p>' + _(
                 'No price was found')
         elif col == 3:
             if result.drm == SearchResult.DRM_LOCKED:
                 return ('<p>' + _('This book as been detected as having DRM restrictions. This book may not work with your reader and you will have limitations placed upon you as to what you can do with this book. Check with the store before making any purchases to ensure you can actually read this book.') + '</p>')  # noqa
             elif result.drm == SearchResult.DRM_UNLOCKED:
                 return ('<p>' + _('This book has been detected as being DRM Free. You should be able to use this book on any device provided it is in a format calibre supports for conversion. However, before making a purchase double check the DRM status with the store. The store may not be disclosing the use of DRM.') + '</p>')  # noqa
             else:
                 return ('<p>' + _('The DRM status of this book could not be determined. There is a very high likelihood that this book is actually DRM restricted.') + '</p>')  # noqa
         elif col == 4:
             return ('<p>%s</p>' % result.formats)
         elif col == 5:
             if result.downloads:
                 return ('<p>' + _('The following formats can be downloaded directly: %s.') % ', '.join(result.downloads.keys()) + '</p>')
         elif col == 6:
             if result.affiliate:
                 return ('<p>' + _('Buying from this store supports the calibre developer: %s.') % result.plugin_author + '</p>')
     elif role == Qt.ItemDataRole.SizeHintRole:
         return QSize(64, 64)
     return None
Esempio n. 10
0
 def __init__(self, parent, prefs=gprefs):
     self.current_img = QPixmap()
     self.current_url = QUrl()
     self.parent = parent
     self.dialogs = []
     self.prefs = prefs