Ejemplo n.º 1
0
def generate_cover(mi, prefs=None, as_qimage=False):
    ensure_app()
    load_builtin_fonts()
    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_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', '%s %s' % (__appname__, __version__))
    if as_qimage:
        return img
    return pixmap_to_data(img)
Ejemplo n.º 2
0
def main(args=sys.argv):
    opts, args = create_option_parser().parse_args(args)
    if opts.auto_reload:
        if getattr(opts, 'daemonize', False):
            raise SystemExit(
                'Cannot specify --auto-reload and --daemonize at the same time')
        from calibre.srv.auto_reload import auto_reload, NoAutoReload
        try:
            from calibre.utils.logging import default_log
            return auto_reload(default_log, listen_on=opts.listen_on)
        except NoAutoReload as e:
            raise SystemExit(error_message(e))

    ensure_single_instance()
    if opts.userdb:
        opts.userdb = os.path.abspath(os.path.expandvars(os.path.expanduser(opts.userdb)))
        connect(opts.userdb, exc_class=SystemExit).close()
    if opts.manage_users:
        try:
            manage_users_cli(opts.userdb)
        except (KeyboardInterrupt, EOFError):
            raise SystemExit(_('Interrupted by user'))
        raise SystemExit(0)

    libraries = args[1:]
    for lib in libraries:
        if not lib or not LibraryDatabase.exists_at(lib):
            raise SystemExit(_('There is no calibre library at: %s') % lib)
    libraries = libraries or load_gui_libraries()
    if not libraries:
        if not prefs['library_path']:
            raise SystemExit(_('You must specify at least one calibre library'))
        libraries = [prefs['library_path']]

    opts.auto_reload_port = int(os.environ.get('CALIBRE_AUTORELOAD_PORT', 0))
    opts.allow_console_print = 'CALIBRE_ALLOW_CONSOLE_PRINT' in os.environ
    if opts.log and os.path.isdir(opts.log):
        raise SystemExit('The --log option must point to a file, not a directory')
    if opts.access_log and os.path.isdir(opts.access_log):
        raise SystemExit('The --access-log option must point to a file, not a directory')
    server = Server(libraries, opts)
    if getattr(opts, 'daemonize', False):
        if not opts.log and not iswindows:
            raise SystemExit(
                'In order to daemonize you must specify a log file, you can use /dev/stdout to log to screen even as a daemon'
            )
        daemonize()
    if opts.pidfile:
        with lopen(opts.pidfile, 'wb') as f:
            f.write(unicode_type(os.getpid()).encode('ascii'))
    signal.signal(signal.SIGTERM, lambda s, f: server.stop())
    if not getattr(opts, 'daemonize', False) and not iswindows:
        signal.signal(signal.SIGHUP, lambda s, f: server.stop())
    # Needed for dynamic cover generation, which uses Qt for drawing
    from calibre.gui2 import ensure_app, load_builtin_fonts
    ensure_app(), load_builtin_fonts()
    try:
        server.serve_forever()
    finally:
        shutdown_delete_service()
Ejemplo n.º 3
0
def main(args=sys.argv):
    opts, args = create_option_parser().parse_args(args)
    ensure_single_instance()
    if opts.userdb:
        opts.userdb = os.path.abspath(os.path.expandvars(os.path.expanduser(opts.userdb)))
        connect(opts.userdb, exc_class=SystemExit).close()
    if opts.manage_users:
        try:
            manage_users_cli(opts.userdb)
        except (KeyboardInterrupt, EOFError):
            raise SystemExit(_('Interrupted by user'))
        raise SystemExit(0)

    libraries = args[1:]
    for lib in libraries:
        if not lib or not LibraryDatabase.exists_at(lib):
            raise SystemExit(_('There is no calibre library at: %s') % lib)
    libraries = libraries or load_gui_libraries()
    if not libraries:
        if not prefs['library_path']:
            raise SystemExit(_('You must specify at least one calibre library'))
        libraries = [prefs['library_path']]

    if opts.auto_reload:
        if getattr(opts, 'daemonize', False):
            raise SystemExit(
                'Cannot specify --auto-reload and --daemonize at the same time')
        from calibre.srv.auto_reload import auto_reload, NoAutoReload
        try:
            from calibre.utils.logging import default_log
            return auto_reload(default_log, listen_on=opts.listen_on)
        except NoAutoReload as e:
            raise SystemExit(e.message)
    opts.auto_reload_port = int(os.environ.get('CALIBRE_AUTORELOAD_PORT', 0))
    opts.allow_console_print = 'CALIBRE_ALLOW_CONSOLE_PRINT' in os.environ
    if opts.log and os.path.isdir(opts.log):
        raise SystemExit('The --log option must point to a file, not a directory')
    if opts.access_log and os.path.isdir(opts.access_log):
        raise SystemExit('The --access-log option must point to a file, not a directory')
    server = Server(libraries, opts)
    if getattr(opts, 'daemonize', False):
        if not opts.log and not iswindows:
            raise SystemExit(
                'In order to daemonize you must specify a log file, you can use /dev/stdout to log to screen even as a daemon'
            )
        daemonize()
    if opts.pidfile:
        with lopen(opts.pidfile, 'wb') as f:
            f.write(str(os.getpid()))
    signal.signal(signal.SIGTERM, lambda s, f: server.stop())
    if not getattr(opts, 'daemonize', False) and not iswindows:
        signal.signal(signal.SIGHUP, lambda s, f: server.stop())
    # Needed for dynamic cover generation, which uses Qt for drawing
    from calibre.gui2 import ensure_app, load_builtin_fonts
    ensure_app(), load_builtin_fonts()
    try:
        server.serve_forever()
    finally:
        shutdown_delete_service()
Ejemplo n.º 4
0
def main(args=sys.argv):
    opts, args = create_option_parser().parse_args(args)
    if opts.manage_users:
        try:
            manage_users(opts.userdb)
        except (KeyboardInterrupt, EOFError):
            raise SystemExit(_('Interrupted by user'))
        raise SystemExit(0)

    libraries = args[1:]
    for lib in libraries:
        if not lib or not LibraryDatabase.exists_at(lib):
            raise SystemExit(_('There is no calibre library at: %s') % lib)
    if not libraries:
        if not prefs['library_path']:
            raise SystemExit(
                _('You must specify at least one calibre library'))
        libraries = [prefs['library_path']]

    if opts.auto_reload:
        if opts.daemonize:
            raise SystemExit(
                'Cannot specify --auto-reload and --daemonize at the same time'
            )
        from calibre.srv.auto_reload import auto_reload, NoAutoReload
        try:
            from calibre.utils.logging import default_log
            return auto_reload(default_log)
        except NoAutoReload as e:
            raise SystemExit(e.message)
    opts.auto_reload_port = int(os.environ.get('CALIBRE_AUTORELOAD_PORT', 0))
    server = Server(libraries, opts)
    if opts.daemonize:
        if not opts.log and not iswindows:
            raise SystemExit(
                'In order to daemonize you must specify a log file, you can use /dev/stdout to log to screen even as a daemon'
            )
        daemonize()
    if opts.pidfile:
        with lopen(opts.pidfile, 'wb') as f:
            f.write(str(os.getpid()))
    signal.signal(signal.SIGTERM, lambda s, f: server.stop())
    if not opts.daemonize and not iswindows:
        signal.signal(signal.SIGHUP, lambda s, f: server.stop())
    # Needed for dynamic cover generation, which uses Qt for drawing
    from calibre.gui2 import ensure_app, load_builtin_fonts
    ensure_app(), load_builtin_fonts()
    server.serve_forever()
Ejemplo n.º 5
0
def overlay_image(img, canvas=None, left=0, top=0):
    if canvas is None:
        canvas = QImage(img.size(), QImage.Format_RGB32)
        canvas.fill(Qt.white)
    if imageops is None:
        # This is for people running from source who have not updated the
        # binary and so do not have the imageops module
        from PyQt5.Qt import QPainter
        from calibre.gui2 import ensure_app
        ensure_app()
        p = QPainter(canvas)
        p.drawImage(left, top, img)
        p.end()
    else:
        imageops.overlay(img, canvas, left, top)
    return canvas
Ejemplo n.º 6
0
def main(args=sys.argv):
    opts, args=create_option_parser().parse_args(args)
    if opts.manage_users:
        try:
            manage_users(opts.userdb)
        except (KeyboardInterrupt, EOFError):
            raise SystemExit(_('Interrupted by user'))
        raise SystemExit(0)

    libraries=args[1:]
    for lib in libraries:
        if not lib or not LibraryDatabase.exists_at(lib):
            raise SystemExit(_('There is no calibre library at: %s') % lib)
    if not libraries:
        if not prefs['library_path']:
            raise SystemExit(_('You must specify at least one calibre library'))
        libraries=[prefs['library_path']]

    if opts.auto_reload:
        if opts.daemonize:
            raise SystemExit('Cannot specify --auto-reload and --daemonize at the same time')
        from calibre.srv.auto_reload import auto_reload, NoAutoReload
        try:
            from calibre.utils.logging import default_log
            return auto_reload(default_log, listen_on=opts.listen_on)
        except NoAutoReload as e:
            raise SystemExit(e.message)
    opts.auto_reload_port=int(os.environ.get('CALIBRE_AUTORELOAD_PORT', 0))
    opts.allow_console_print = 'CALIBRE_ALLOW_CONSOLE_PRINT' in os.environ
    server=Server(libraries, opts)
    if opts.daemonize:
        if not opts.log and not iswindows:
            raise SystemExit('In order to daemonize you must specify a log file, you can use /dev/stdout to log to screen even as a daemon')
        daemonize()
    if opts.pidfile:
        with lopen(opts.pidfile, 'wb') as f:
            f.write(str(os.getpid()))
    signal.signal(signal.SIGTERM, lambda s,f: server.stop())
    if not opts.daemonize and not iswindows:
        signal.signal(signal.SIGHUP, lambda s,f: server.stop())
    # Needed for dynamic cover generation, which uses Qt for drawing
    from calibre.gui2 import ensure_app, load_builtin_fonts
    ensure_app(), load_builtin_fonts()
    server.serve_forever()
Ejemplo n.º 7
0
def run_tests(find_tests=find_tests):
    from calibre.gui2 import ensure_app, load_builtin_fonts
    ensure_app(), load_builtin_fonts()  # needed for dynamic cover generation
    parser = argparse.ArgumentParser()
    parser.add_argument(
        'name',
        nargs='?',
        default=None,
        help=
        'The name of the test to run, for e.g. writing.WritingTest.many_many_basic or .many_many_basic for a shortcut'
    )
    args = parser.parse_args()
    if args.name and args.name.startswith('.'):
        tests = find_tests()
        q = args.name[1:]
        if not q.startswith('test_'):
            q = 'test_' + q
        ans = None
        try:
            for suite in tests:
                for test in suite._tests:
                    if test.__class__.__name__ == 'ModuleImportFailure':
                        raise Exception('Failed to import a test module: %s' %
                                        test)
                    for s in test:
                        if s._testMethodName == q:
                            ans = s
                            raise StopIteration()
        except StopIteration:
            pass
        if ans is None:
            print('No test named %s found' % args.name)
            raise SystemExit(1)
        tests = ans
    else:
        tests = unittest.defaultTestLoader.loadTestsFromName(
            args.name) if args.name else find_tests()
    r = unittest.TextTestRunner
    r.resultclass = TestResult
    r(verbosity=4).run(tests)
Ejemplo n.º 8
0
def generate_cover(mi, prefs=None, as_qimage=False):
    ensure_app()
    load_builtin_fonts()
    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_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', '%s %s' % (__appname__, __version__))
    if as_qimage:
        return img
    return pixmap_to_data(img)
Ejemplo n.º 9
0
def init_environment():
    ensure_app()
    load_builtin_fonts()
Ejemplo n.º 10
0
def init_environment():
    ensure_app()
    load_builtin_fonts()
Ejemplo n.º 11
0
    def test_qt(self):
        from PyQt5.QtCore import QTimer
        from PyQt5.QtWidgets import QApplication
        from PyQt5.QtWebEngineWidgets import QWebEnginePage
        from PyQt5.QtGui import QImageReader, QFontDatabase
        from PyQt5.QtNetwork import QNetworkAccessManager
        from calibre.utils.img import image_from_data, image_to_data, test
        # Ensure that images can be read before QApplication is constructed.
        # Note that this requires QCoreApplication.libraryPaths() to return the
        # path to the Qt plugins which it always does in the frozen build,
        # because Qt is patched to know the layout of the calibre application
        # package. On non-frozen builds, it should just work because the
        # hard-coded paths of the Qt installation should work. If they do not,
        # then it is a distro problem.
        fmts = set(map(lambda x: x.data().decode('utf-8'), QImageReader.supportedImageFormats()))  # no2to3
        testf = {'jpg', 'png', 'svg', 'ico', 'gif'}
        self.assertEqual(testf.intersection(fmts), testf, "Qt doesn't seem to be able to load some of its image plugins. Available plugins: %s" % fmts)
        data = P('images/blank.png', allow_user_override=False, data=True)
        img = image_from_data(data)
        image_from_data(P('catalog/mastheadImage.gif', allow_user_override=False, data=True))
        for fmt in 'png bmp jpeg'.split():
            d = image_to_data(img, fmt=fmt)
            image_from_data(d)
        # Run the imaging tests
        test()

        from calibre.gui2 import ensure_app, destroy_app
        display_env_var = os.environ.pop('DISPLAY', None)
        try:
            ensure_app()
            self.assertGreaterEqual(len(QFontDatabase().families()), 5, 'The QPA headless plugin is not able to locate enough system fonts via fontconfig')
            from calibre.ebooks.covers import create_cover
            create_cover('xxx', ['yyy'])
            na = QNetworkAccessManager()
            self.assertTrue(hasattr(na, 'sslErrors'), 'Qt not compiled with openssl')
            if iswindows:
                from PyQt5.Qt import QtWin
                QtWin
            p = QWebEnginePage()

            def callback(result):
                callback.result = result
                if hasattr(print_callback, 'result'):
                    QApplication.instance().quit()

            def print_callback(result):
                print_callback.result = result
                if hasattr(callback, 'result'):
                    QApplication.instance().quit()

            p.runJavaScript('1 + 1', callback)
            p.printToPdf(print_callback)
            QTimer.singleShot(5000, lambda: QApplication.instance().quit())
            QApplication.instance().exec_()
            test_flaky = ismacos and not is_ci
            if not test_flaky:
                self.assertEqual(callback.result, 2, 'Simple JS computation failed')
                self.assertIn(b'Skia/PDF', bytes(print_callback.result), 'Print to PDF failed')
            del p
            del na
            destroy_app()
            del QWebEnginePage
        finally:
            if display_env_var is not None:
                os.environ['DISPLAY'] = display_env_var
Ejemplo n.º 12
0
def setUpModule():
    # Needed for cover generation
    from calibre.gui2 import ensure_app, load_builtin_fonts
    ensure_app(), load_builtin_fonts()
Ejemplo n.º 13
0
def create_cover_page(top_lines, bottom_lines, display_image, options,
                      image_path, output_format='jpg'):
    from calibre.gui2 import ensure_app
    ensure_app()
    (width, height) = options.get(cfg.KEY_SIZE, (590, 750))
    margins = options.get(cfg.KEY_MARGINS)
    (top_mgn, bottom_mgn, left_mgn, right_mgn, image_mgn) = (
        margins['top'], margins['bottom'], margins['left'],
        margins['right'], margins['image'])
    left_mgn = min([left_mgn, (width / 2) - 10])
    left_text_margin = left_mgn if left_mgn > 0 else 10
    right_mgn = min([right_mgn, (width / 2) - 10])
    right_text_margin = right_mgn if right_mgn > 0 else 10

    colors = options[cfg.KEY_COLORS]
    bgcolor, border_color, fill_color, stroke_color = (
        colors['background'], colors['border'], colors['fill'],
        colors['stroke'])
    if not options.get(cfg.KEY_COLOR_APPLY_STROKE, False):
        stroke_color = None
    auto_reduce_font = options.get(cfg.KEY_FONTS_AUTOREDUCED, False)
    borders = options[cfg.KEY_BORDERS]
    (cover_border_width, image_border_width) = (
        borders['coverBorder'], borders['imageBorder'])
    is_background_image = options.get(cfg.KEY_BACKGROUND_IMAGE, False)
    if image_path:
        if not os.path.exists(image_path) or os.path.getsize(image_path) == 0:
            display_image = is_background_image = False

    canvas = create_canvas(width - cover_border_width * 2,
                           height - cover_border_width * 2, bgcolor)
    if cover_border_width > 0:
        canvas = add_border(canvas, cover_border_width, border_color, bgcolor)

    if is_background_image:
        logo = Image()
        logo.open(image_path)
        outer_margin = 0 if cover_border_width == 0 else cover_border_width
        logo.size = (width - outer_margin * 2, height - outer_margin * 2)
        left = top = outer_margin
        canvas.compose(logo, int(left), int(top))

    top = top_mgn
    if len(top_lines) > 0:
        for line in top_lines:
            twand = create_colored_text_wand(line, fill_color, stroke_color)
            top = draw_sized_text(
                canvas, twand, line, top, left_text_margin,
                right_text_margin, auto_reduce_font)
            top += line.bottom_margin
        top -= top_lines[-1].bottom_margin

    if len(bottom_lines) > 0:
        # Draw this on a fake canvas so can determine the space required
        fake_canvas = create_canvas(width, height, bgcolor)
        footer_height = 0
        for line in bottom_lines:
            line.twand = create_colored_text_wand(
                line, fill_color, stroke_color)
            footer_height = draw_sized_text(
                fake_canvas, line.twand, line, footer_height, left_text_margin,
                right_text_margin, auto_reduce_font)
            footer_height += line.bottom_margin
        footer_height -= bottom_lines[-1].bottom_margin

        footer_top = height - footer_height - bottom_mgn
        bottom = footer_top
        # Re-use the text wand from previously which we will have adjusted the
        # font size on
        for line in bottom_lines:
            bottom = draw_sized_text(
                canvas, line.twand, line, bottom, left_text_margin,
                right_text_margin, auto_reduce_font=False)
            bottom += line.bottom_margin
        available = (width - (left_mgn + right_mgn),
                     int(footer_top - top) - (image_mgn * 2))
    else:
        available = (width - (left_mgn + right_mgn),
                     int(height - top) - bottom_mgn - (image_mgn * 2))

    if not is_background_image and display_image and available[1] > 40:
        logo = Image()
        logo.open(image_path)
        lwidth, lheight = logo.size
        available = (available[0] - image_border_width * 2,
                     available[1] - image_border_width * 2)
        scaled, lwidth, lheight = fit_image(lwidth, lheight, *available)
        if not scaled and options.get(cfg.KEY_RESIZE_IMAGE_TO_FIT, False):
            scaled, lwidth, lheight = scaleup_image(
                lwidth, lheight, *available)
        if scaled:
            logo.size = (lwidth, lheight)
        if image_border_width > 0:
            logo = add_border(logo, image_border_width, border_color, bgcolor)

        left = int(max(0, (width - lwidth) / 2.))
        top = top + image_mgn + ((available[1] - lheight) / 2.)
        canvas.compose(logo, int(left), int(top))

    return canvas.export(output_format)
Ejemplo n.º 14
0
def setUpModule():
    # Needed for cover generation
    from calibre.gui2 import ensure_app, load_builtin_fonts
    ensure_app(), load_builtin_fonts()