예제 #1
0
 def files_dropped_on_book(self, event, paths, cid=None, do_confirm=True):
     accept = False
     if self.gui.current_view() is not self.gui.library_view:
         return
     db = self.gui.library_view.model().db
     cover_changed = False
     current_idx = self.gui.library_view.currentIndex()
     if cid is None:
         if not current_idx.isValid():
             return
         cid = db.id(current_idx.row()) if cid is None else cid
     formats = []
     from calibre.gui2.dnd import image_extensions
     image_exts = set(image_extensions()) - set(
         tweaks['cover_drop_exclude'])
     if iswindows:
         from calibre.gui2.add import resolve_windows_links
         paths = list(
             resolve_windows_links(paths,
                                   hwnd=int(self.gui.effectiveWinId())))
     for path in paths:
         ext = os.path.splitext(path)[1].lower()
         if ext:
             ext = ext[1:]
         if ext in image_exts:
             pmap = QPixmap()
             pmap.load(path)
             if not pmap.isNull():
                 accept = True
                 db.set_cover(cid, pmap)
                 cover_changed = True
         else:
             formats.append((ext, path))
             accept = True
     if accept and event is not None:
         event.accept()
     add_as_book = False
     if do_confirm and formats:
         ok, add_as_book = confirm(_(
             'You have dropped some files onto the book <b>%s</b>. This will'
             ' add or replace the files for this book. Do you want to proceed?'
         ) % db.title(cid, index_is_id=True),
                                   'confirm_drop_on_book',
                                   parent=self.gui,
                                   extra_button=ngettext(
                                       'Add as new book',
                                       'Add as new books', len(formats)))
         if ok and add_as_book:
             add_as_book = [path for ext, path in formats]
         if not ok or add_as_book:
             formats = []
     for ext, path in formats:
         db.add_format_with_hooks(cid, ext, path, index_is_id=True)
     if current_idx.isValid():
         self.gui.library_view.model().current_changed(
             current_idx, current_idx)
     if cover_changed:
         self.gui.refresh_cover_browser()
     if add_as_book:
         self.files_dropped(add_as_book)
예제 #2
0
파일: widgets.py 프로젝트: cbhaley/calibre
    def dropEvent(self, event):
        event.setDropAction(Qt.DropAction.CopyAction)
        md = event.mimeData()
        pmap, data = dnd_get_local_image_and_pixmap(md)
        if pmap is not None:
            self.handle_image_drop(pmap, data)
            return

        x, y = dnd_get_image(md)
        if x is not None:
            # We have an image, set cover
            event.accept()
            if y is None:
                # Local image
                self.handle_image_drop(x)
            else:
                # Remote files, use the first file
                d = DownloadDialog(x, y, self)
                d.start_download()
                if d.err is None:
                    pmap = QPixmap()
                    with lopen(d.fpath, 'rb') as f:
                        data = f.read()
                    pmap.loadFromData(data)
                    if not pmap.isNull():
                        self.handle_image_drop(pmap, data=data)
예제 #3
0
def load_icon_resource_as_pixmap(icon_resource, size=ICON_SIZE):
    if not icon_resource:
        return
    parts = tuple(filter(None, re.split(r',([-0-9]+$)', icon_resource)))
    if len(parts) != 2:
        return
    module, index = parts
    index = int(index)
    if module.startswith('"') and module.endswith('"'):
        module = split_commandline(module)[0]
    hmodule = winutil.load_library(
        module, winutil.LOAD_LIBRARY_AS_DATAFILE
        | winutil.LOAD_LIBRARY_AS_IMAGE_RESOURCE)
    icons = winutil.load_icons(hmodule, index)
    pixmaps = []
    must_use_qt()
    for icon_data, icon_handle in icons:
        pixmap = QPixmap()
        pixmap.loadFromData(icon_data)
        if pixmap.isNull() and bool(icon_handle):
            pixmap = hicon_to_pixmap(icon_handle)
        if pixmap.isNull():
            continue
        pixmaps.append(pixmap)
    if not pixmaps:
        return

    def area(p):
        return p.width() * p.height()

    pixmaps.sort(key=area)
    q = size * size
    for pmap in pixmaps:
        if area(pmap) >= q:
            if area(pmap) == q:
                return pmap
            return pmap.scaled(
                size,
                size,
                aspectRatioMode=Qt.AspectRatioMode.KeepAspectRatio,
                transformMode=Qt.TransformationMode.SmoothTransformation)
    return pixmaps[-1].scaled(
        size,
        size,
        aspectRatioMode=Qt.AspectRatioMode.KeepAspectRatio,
        transformMode=Qt.TransformationMode.SmoothTransformation)
예제 #4
0
 def load(data):
     p = QPixmap()
     p.loadFromData(as_bytes(data))
     try:
         dpr = self.devicePixelRatioF()
     except AttributeError:
         dpr = self.devicePixelRatio()
     p.setDevicePixelRatio(dpr)
     if data and p.isNull():
         p = self.failed_img
     return p
예제 #5
0
def dnd_get_local_image_and_pixmap(md, image_exts=None):
    if md.hasImage():
        for x in md.formats():
            x = str(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
예제 #6
0
파일: diff.py 프로젝트: sazaed/calibre
 def from_mi(self, mi):
     p = getattr(mi, 'cover', None)
     if p and os.path.exists(p):
         pmap = QPixmap()
         with open(p, 'rb') as f:
             pmap.loadFromData(f.read())
         if not pmap.isNull():
             self.pixmap = pmap
             self.update()
             self.changed.emit()
             return
     cd = getattr(mi, 'cover_data', (None, None))
     if cd and cd[1]:
         pmap = QPixmap()
         pmap.loadFromData(cd[1])
         if not pmap.isNull():
             self.pixmap = pmap
             self.update()
             self.changed.emit()
             return
     self.pixmap = None
     self.update()
     self.changed.emit()
예제 #7
0
 def update_cover(self, pmap=None, cdata=None):
     if pmap is None:
         pmap = QPixmap()
         pmap.loadFromData(cdata)
     if pmap.isNull():
         return
     if pmap.hasAlphaChannel():
         pmap = QPixmap.fromImage(blend_image(image_from_x(pmap)))
     self.pixmap = pmap
     self.do_layout()
     self.update()
     self.update_tooltip(getattr(self.parent(), 'current_path', ''))
     if not config['disable_animations']:
         self.animation.start()
     id_ = self.data.get('id', None)
     if id_ is not None:
         self.cover_changed.emit(id_, cdata or pixmap_to_data(pmap))
예제 #8
0
def entry_to_icon_text(entry, only_text=False):
    if only_text:
        return entry.get('name', entry.get('Name')) or _('Unknown')
    data = entry.get('icon_data')
    if isinstance(data, str):
        with suppress(Exception):
            from base64 import standard_b64decode
            data = bytearray(standard_b64decode(data))
    if not isinstance(data, (bytearray, bytes)):
        icon = QIcon(I('blank.png'))
    else:
        pmap = QPixmap()
        pmap.loadFromData(bytes(data))
        if pmap.isNull():
            icon = QIcon(I('blank.png'))
        else:
            icon = QIcon(pmap)
    return icon, entry.get('name', entry.get('Name')) or _('Unknown')
예제 #9
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()
예제 #10
0
 def select_cover(self):
     files = choose_images(
         self, 'change cover dialog',
         _('Choose cover for ') + unicode_type(self.title.text()))
     if not files:
         return
     _file = files[0]
     if _file:
         _file = os.path.abspath(_file)
         if not os.access(_file, os.R_OK):
             d = error_dialog(
                 self.parent(), _('Cannot read'),
                 _('You do not have permission to read the file: ') + _file)
             d.exec_()
             return
         cover = None
         try:
             with open(_file, "rb") as f:
                 cover = f.read()
         except IOError as e:
             d = error_dialog(
                 self.parent(), _('Error reading file'),
                 _("<p>There was an error reading from file: <br /><b>") +
                 _file + "</b></p><br />" + unicode_type(e))
             d.exec_()
         if cover:
             pix = QPixmap()
             pix.loadFromData(cover)
             pix.setDevicePixelRatio(
                 getattr(self, 'devicePixelRatioF',
                         self.devicePixelRatio)())
             if pix.isNull():
                 d = error_dialog(self.parent(), _('Error reading file'),
                                  _file + _(" is not a valid picture"))
                 d.exec_()
             else:
                 self.cover_path.setText(_file)
                 self.set_cover_tooltip(pix)
                 self.cover.setPixmap(pix)
                 self.cover_changed = True
                 self.cpixmap = pix
                 self.cover_data = cover
예제 #11
0
class ImagePopup(object):
    def __init__(self, parent):
        self.current_img = QPixmap()
        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)
예제 #12
0
파일: model.py 프로젝트: smdx023/calibre
 def data(self, role):
     if role == Qt.ItemDataRole.DisplayRole:
         return (self.title)
     if role == Qt.ItemDataRole.DecorationRole:
         if self.icon is None:
             icon = '%s.png' % self.urn[8:]
             p = QPixmap()
             if icon in self.favicons:
                 try:
                     with zipfile.ZipFile(self.zf, 'r') as zf:
                         p.loadFromData(zf.read(self.favicons[icon]))
                 except Exception:
                     pass
             if not p.isNull():
                 self.icon = (QIcon(p))
             else:
                 self.icon = self.default_icon
         return self.icon
     if role == Qt.ItemDataRole.UserRole:
         return self.urn
예제 #13
0
 def bd_open_cover_with(self, book_id, entry):
     cpath = self.current_db.new_api.format_abspath(book_id,
                                                    '__COVER_INTERNAL__')
     if cpath:
         if entry is None:
             pm = QPixmap()
             pm.load(cpath)
             pm.setDevicePixelRatio(self.devicePixelRatioF())
             if pm.isNull():
                 open_local_file(cpath)
             else:
                 from calibre.gui2.image_popup import ImageView
                 iv = ImageView(QApplication.instance().focusWindow(),
                                pm,
                                QUrl.fromLocalFile(cpath),
                                geom_name='book_details_image_view')
                 iv(use_exec=True)
             return
         from calibre.gui2.open_with import run_program
         run_program(entry, cpath, self)
예제 #14
0
class CoverView(QWidget):
    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)

    def set_pixmap(self, data):
        self.pixmap.loadFromData(data)
        self.current_pixmap_size = self.pixmap.size()
        self.update()

    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()

    def sizeHint(self):
        return QSize(300, 400)
예제 #15
0
 def set_color(self):
     r, g, b = gprefs['cover_grid_color']
     tex = gprefs['cover_grid_texture']
     pal = self.palette()
     pal.setColor(QPalette.ColorRole.Base, QColor(r, g, b))
     self.setPalette(pal)
     ss = ''
     if tex:
         from calibre.gui2.preferences.texture_chooser import texture_path
         path = texture_path(tex)
         if path:
             path = os.path.abspath(path).replace(os.sep, '/')
             ss += 'background-image: url({});'.format(path)
             ss += 'background-attachment: fixed;'
             pm = QPixmap(path)
             if not pm.isNull():
                 val = pm.scaled(1, 1).toImage().pixel(0, 0)
                 r, g, b = qRed(val), qGreen(val), qBlue(val)
     dark = max(r, g, b) < 115
     col = '#eee' if dark else '#111'
     ss += 'color: {};'.format(col)
     self.delegate.highlight_color = QColor(col)
     self.setStyleSheet('QListView {{ {} }}'.format(ss))
예제 #16
0
파일: widgets.py 프로젝트: cbhaley/calibre
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()