Esempio n. 1
0
 def adv_search_string(self):
     mk = self.matchkind.currentIndex()
     if mk == CONTAINS_MATCH:
         self.mc = ''
     elif mk == EQUALS_MATCH:
         self.mc = '='
     else:
         self.mc = '~'
     all, any, phrase, none = map(lambda x: unicode_type(x.text()),
             (self.all, self.any, self.phrase, self.none))
     all, any, none = map(self.tokens, (all, any, none))
     phrase = phrase.strip()
     all = ' and '.join(all)
     any = ' or '.join(any)
     none = ' and not '.join(none)
     ans = ''
     if phrase:
         ans += '"%s"'%phrase
     if all:
         ans += (' and ' if ans else '') + all
     if none:
         ans += (' and not ' if ans else 'not ') + none
     if any:
         ans += (' or ' if ans else '') + any
     return ans
Esempio n. 2
0
    def __init__(self, sfnt):
        for table in (b'head', b'hhea', b'hmtx', b'cmap', b'OS/2', b'post',
                      b'name'):
            if table not in sfnt:
                raise UnsupportedFont('This font has no %s table'%table)
        self.sfnt = sfnt

        self.head = self.sfnt[b'head']
        hhea = self.sfnt[b'hhea']
        hhea.read_data(self.sfnt[b'hmtx'])
        self.ascent = hhea.ascender
        self.descent = hhea.descender
        self.bbox = (self.head.x_min, self.head.y_min, self.head.x_max,
                     self.head.y_max)
        self._advance_widths = hhea.advance_widths
        self.cmap = self.sfnt[b'cmap']
        self.units_per_em = self.head.units_per_em
        self.os2 = self.sfnt[b'OS/2']
        self.os2.read_data()
        self.post = self.sfnt[b'post']
        self.post.read_data()
        self.names = get_all_font_names(self.sfnt[b'name'].raw, raw_is_table=True)
        self.is_otf = 'CFF ' in self.sfnt.tables
        self._sig = hash(self.sfnt[b'name'].raw)

        # Metrics for embedding in PDF
        pdf_scale = self.pdf_scale = lambda x:int(round(x*1000./self.units_per_em))
        self.pdf_ascent, self.pdf_descent = map(pdf_scale,
                        (self.os2.typo_ascender, self.os2.typo_descender))
        self.pdf_bbox = tuple(map(pdf_scale, self.bbox))
        self.pdf_capheight = pdf_scale(getattr(self.os2, 'cap_height',
                                               self.os2.typo_ascender))
        self.pdf_avg_width = pdf_scale(self.os2.average_char_width)
        self.pdf_stemv = 50 + int((self.os2.weight_class / 65.0) ** 2)
Esempio n. 3
0
    def __init__(self, feeds):
        list.__init__(self, [f for f in feeds if len(f.articles) > 0])
        found_articles = set()
        duplicates = set()

        def in_set(s, a):
            for x in s:
                if a.is_same_as(x):
                    return x
            return None

        print('#feeds', len(self))
        print(list(map(len, self)))
        for f in self:
            dups = []
            for a in f:
                first = in_set(found_articles, a)
                if first is not None:
                    dups.append(a)
                    duplicates.add((first, f))
                else:
                    found_articles.add(a)
            for x in dups:
                f.articles.remove(x)

        self.duplicates = duplicates
        print(len(duplicates))
        print(list(map(len, self)))
Esempio n. 4
0
def convert_color_for_font_tag(val):
    rgba = parse_color_string(unicode_type(val or ''))
    if rgba is None or rgba == 'currentColor':
        return val
    clamp = lambda x: min(x, max(0, x), 1)
    rgb = map(clamp, rgba[:3])
    return '#' + ''.join(map(lambda x:'%02x' % int(x * 255), rgb))
Esempio n. 5
0
 def __init__(self, img, opts, log, idc):
     Element.__init__(self)
     self.opts, self.log = opts, log
     self.id = next(idc)
     self.top, self.left, self.width, self.height, self.iwidth, self.iheight = \
       map(float, map(img.get, ('top', 'left', 'rwidth', 'rheight', 'iwidth',
           'iheight')))
     self.src = img.get('src')
     self.bottom = self.top + self.height
     self.right = self.left + self.width
Esempio n. 6
0
 def apply_color_space(self, color, pattern, stroke=False):
     wl = self.current_page.write_line
     if color is not None and pattern is None:
         wl(' '.join(map(fmtnum, color)) + (' RG' if stroke else ' rg'))
     elif color is None and pattern is not None:
         wl('/Pattern %s /%s %s'%('CS' if stroke else 'cs', pattern,
                                  'SCN' if stroke else 'scn'))
     elif color is not None and pattern is not None:
         col = ' '.join(map(fmtnum, color))
         wl('/PCSp %s %s /%s %s'%('CS' if stroke else 'cs', col, pattern,
                                  'SCN' if stroke else 'scn'))
Esempio n. 7
0
def main(args):
    import sys, time
    from calibre import prints
    parser = option_parser()
    opts, args = parser.parse_args(args)
    if len(args) < 4 or len(args) > 4:
        parser.print_help()
        raise SystemExit(1)
    iff, off, chars = args[1:]
    with open(iff, 'rb') as f:
        orig = f.read()

    chars = [x for x in chars.split(',')]
    individual, ranges = set(), set()

    def not_single(c):
        if len(c) > 1:
            prints(c, 'is not a single character', file=sys.stderr)
            raise SystemExit(1)

    def conv_code(c):
        if c.upper()[:2] in ('U+', '0X'):
            c = int(c[2:], 16)
        return safe_chr(int(c))

    for c in chars:
        if '-' in c:
            parts = [x.strip() for x in c.split('-')]
            if len(parts) != 2:
                prints('Invalid range:', c, file=sys.stderr)
                raise SystemExit(1)
            if opts.codes:
                parts = tuple(map(conv_code, parts))
            tuple(map(not_single, parts))
            ranges.add(tuple(parts))
        else:
            if opts.codes:
                c = conv_code(c)
            not_single(c)
            individual.add(c)
    st = time.time()
    sf, old_stats, new_stats = subset(orig, individual, ranges)
    taken = time.time() - st
    reduced = (len(sf)/len(orig)) * 100

    def sz(x):
        return '%gKB'%(len(x)/1024.)
    print_stats(old_stats, new_stats)
    prints('Original size:', sz(orig), 'Subset size:', sz(sf), 'Reduced to: %g%%'%(reduced))
    prints('Subsetting took %g seconds'%taken)
    with open(off, 'wb') as f:
        f.write(sf)
    prints('Subset font written to:', off)
Esempio n. 8
0
def get(ctx, rd, what, book_id, library_id):
    book_id, rest = book_id.partition('_')[::2]
    try:
        book_id = int(book_id)
    except Exception:
        raise HTTPNotFound('Book with id %r does not exist' % book_id)
    db = get_db(ctx, rd, library_id)
    if db is None:
        raise HTTPNotFound('Library %r not found' % library_id)
    with db.safe_read_lock:
        if not ctx.has_id(rd, db, book_id):
            raise BookNotFound(book_id, db)
        library_id = db.server_library_id  # in case library_id was None
        if what == 'thumb':
            sz = rd.query.get('sz')
            w, h = 60, 80
            if sz is None:
                if rest:
                    try:
                        w, h = map(int, rest.split('_'))
                    except Exception:
                        pass
            elif sz == 'full':
                w = h = None
            elif 'x' in sz:
                try:
                    w, h = map(int, sz.partition('x')[::2])
                except Exception:
                    pass
            else:
                try:
                    w = h = int(sz)
                except Exception:
                    pass
            return cover(ctx, rd, library_id, db, book_id, width=w, height=h)
        elif what == 'cover':
            return cover(ctx, rd, library_id, db, book_id)
        elif what == 'opf':
            mi = db.get_metadata(book_id, get_cover=False)
            rd.outheaders['Content-Type'] = 'application/oebps-package+xml; charset=UTF-8'
            rd.outheaders['Last-Modified'] = http_date(timestampfromdt(mi.last_modified))
            return metadata_to_opf(mi)
        elif what == 'json':
            from calibre.srv.ajax import book_to_json
            data, last_modified = book_to_json(ctx, rd, db, book_id)
            rd.outheaders['Last-Modified'] = http_date(timestampfromdt(last_modified))
            return json(ctx, rd, get, data)
        else:
            try:
                return book_fmt(ctx, rd, library_id, db, book_id, what.lower())
            except NoSuchFormat:
                raise HTTPNotFound('No %s format for the book %r' % (what.lower(), book_id))
Esempio n. 9
0
def do_list(fields, data, opts):
    from calibre.utils.terminal import geometry, ColoredStream

    separator = ' '
    widths = list(map(lambda x: 0, fields))
    for i in data:
        for j, field in enumerate(fields):
            widths[j] = max(widths[j], max(len(field), len(unicode_type(i[field]))))

    screen_width = geometry()[0]
    if not screen_width:
        screen_width = 80
    field_width = screen_width // len(fields)
    base_widths = list(map(lambda x: min(x + 1, field_width), widths))

    while sum(base_widths) < screen_width:
        adjusted = False
        for i in range(len(widths)):
            if base_widths[i] < widths[i]:
                base_widths[i] += min(
                    screen_width - sum(base_widths), widths[i] - base_widths[i]
                )
                adjusted = True
                break
        if not adjusted:
            break

    widths = list(base_widths)
    titles = map(
        lambda x, y: '%-*s%s' % (x - len(separator), y, separator), widths, fields
    )
    with ColoredStream(sys.stdout, fg='green'):
        prints(''.join(titles))

    wrappers = list(map(lambda x: TextWrapper(x - 1), widths))

    for record in data:
        text = [
            wrappers[i].wrap(unicode_type(record[field]))
            for i, field in enumerate(fields)
        ]
        lines = max(map(len, text))
        for l in range(lines):
            for i, field in enumerate(text):
                ft = text[i][l] if l < len(text[i]) else ''
                filler = '%*s' % (widths[i] - len(ft) - 1, '')
                print(ft.encode('utf-8') + filler.encode('utf-8'), end=separator)
            print()
Esempio n. 10
0
def find_identical_books(mi, data):
    author_map, aid_map, title_map, lang_map = data
    found_books = None
    for a in mi.authors:
        author_ids = author_map.get(icu_lower(a))
        if author_ids is None:
            return set()
        books_by_author = {book_id for aid in author_ids for book_id in aid_map.get(aid, ())}
        if found_books is None:
            found_books = books_by_author
        else:
            found_books &= books_by_author
        if not found_books:
            return set()

    ans = set()
    titleq = fuzzy_title(mi.title)
    for book_id in found_books:
        title = title_map.get(book_id, '')
        if fuzzy_title(title) == titleq:
            ans.add(book_id)

    langq = tuple(filter(lambda x: x and x != 'und', map(canonicalize_lang, mi.languages or ())))
    if not langq:
        return ans

    def lang_matches(book_id):
        book_langq = lang_map.get(book_id)
        return not book_langq or langq == book_langq

    return {book_id for book_id in ans if lang_matches(book_id)}
Esempio n. 11
0
 def __init__(self, accounts, subjects, aliases={}, tags={}):
     QAbstractTableModel.__init__(self)
     self.accounts = accounts
     self.subjects = subjects
     self.aliases = aliases
     self.tags = tags
     self.sorted_on = (0, True)
     self.account_order = list(self.accounts)
     self.do_sort()
     self.headers  = [_('Email'), _('Formats'), _('Subject'),
         _('Auto send'), _('Alias'), _('Auto send only tags')]
     self.default_font = QFont()
     self.default_font.setBold(True)
     self.default_font = (self.default_font)
     self.tooltips =[None] + list(map(textwrap.fill,
         [_('Formats to email. The first matching format will be sent.'),
          _('Subject of the email to use when sending. When left blank '
            'the title will be used for the subject. Also, the same '
            'templates used for "Save to disk" such as {title} and '
            '{author_sort} can be used here.'),
          '<p>'+_('If checked, downloaded news will be automatically '
                  'mailed to this email address '
                  '(provided it is in one of the listed formats and has not been filtered by tags).'),
          _('Friendly name to use for this email address'),
          _('If specified, only news with one of these tags will be sent to'
            ' this email address. All news downloads have their title as a'
            ' tag, so you can use this to easily control which news downloads'
            ' are sent to this email address.')
          ]))
Esempio n. 12
0
    def __init__(self, toc_table):
        strings = []
        for entry in toc_table:
            strings.append(entry['label'])
            aut = entry.get('author', None)
            if aut:
                strings.append(aut)
            desc = entry.get('description', None)
            if desc:
                strings.append(desc)
            kind = entry.get('kind', None)
            if kind:
                strings.append(kind)
        self.cncx = CNCX(strings)

        try:
            largest = max(x['index'] for x in toc_table)
        except ValueError:
            largest = 0
        fmt = '%0{0}X'.format(max(2, len('%X' % largest)))

        def to_entry(x):
            ans = {}
            for f in ('offset', 'length', 'depth', 'pos_fid', 'parent',
                    'first_child', 'last_child'):
                if f in x:
                    ans[f] = x[f]
            for f in ('label', 'description', 'author', 'kind'):
                if f in x:
                    ans[f] = self.cncx[x[f]]
            return (fmt % x['index'], ans)

        self.entries = list(map(to_entry, toc_table))
Esempio n. 13
0
 def read_rules(self):
     try:
         self.compiled_rules = tuple(map(compile_rule, gprefs.get('add_filter_rules', ())))
     except Exception:
         self.compiled_rules = ()
         import traceback
         traceback.print_exc()
Esempio n. 14
0
def get_newest_version():
    try:
        icon_theme_name = json.loads(I('icon-theme.json', data=True))['name']
    except Exception:
        icon_theme_name = ''
    headers={
        'CALIBRE-VERSION':__version__,
        'CALIBRE-OS': ('win' if iswindows else 'osx' if isosx else 'oth'),
        'CALIBRE-INSTALL-UUID': prefs['installation_uuid'],
        'CALIBRE-ICON-THEME': icon_theme_name,
    }
    try:
        version = get_https_resource_securely(URL, headers=headers)
    except ssl.SSLError as err:
        if getattr(err, 'reason', None) != 'CERTIFICATE_VERIFY_FAILED':
            raise
        # certificate verification failed, since the version check contains no
        # critical information, ignore and proceed
        # We have to do this as if the calibre CA certificate ever
        # needs to be revoked, then we wont be able to do version checks
        version = get_https_resource_securely(URL, headers=headers, cacerts=None)
    try:
        version = version.decode('utf-8').strip()
    except UnicodeDecodeError:
        version = u''
    ans = NO_CALIBRE_UPDATE
    m = re.match(unicode(r'(\d+)\.(\d+).(\d+)$'), version)
    if m is not None:
        ans = tuple(map(int, (m.group(1), m.group(2), m.group(3))))
    return ans
Esempio n. 15
0
 def __init__(self, raw):
     fields = raw.lstrip().replace(b'\x1b\x1b\x1b', b'\x1b').split(b'\x1b')
     self.title = fix_punct(fields[0].decode('cp950', 'replace'))
     self.num_records = int(fields[1])
     self.chapter_titles = list(map(
         lambda x: fix_punct(x.decode('cp950', 'replace').rstrip(b'\x00')),
         fields[2:]))
Esempio n. 16
0
 def apply_theme(self, theme):
     self.theme = theme
     pal = self.palette()
     pal.setColor(pal.Base, theme_color(theme, 'Normal', 'bg'))
     pal.setColor(pal.AlternateBase, theme_color(theme, 'CursorLine', 'bg'))
     pal.setColor(pal.Text, theme_color(theme, 'Normal', 'fg'))
     pal.setColor(pal.Highlight, theme_color(theme, 'Visual', 'bg'))
     pal.setColor(pal.HighlightedText, theme_color(theme, 'Visual', 'fg'))
     self.setPalette(pal)
     self.tooltip_palette = pal = QPalette()
     pal.setColor(pal.ToolTipBase, theme_color(theme, 'Tooltip', 'bg'))
     pal.setColor(pal.ToolTipText, theme_color(theme, 'Tooltip', 'fg'))
     self.line_number_palette = pal = QPalette()
     pal.setColor(pal.Base, theme_color(theme, 'LineNr', 'bg'))
     pal.setColor(pal.Text, theme_color(theme, 'LineNr', 'fg'))
     pal.setColor(pal.BrightText, theme_color(theme, 'LineNrC', 'fg'))
     self.match_paren_format = theme_format(theme, 'MatchParen')
     font = self.font()
     ff = tprefs['editor_font_family']
     if ff is None:
         ff = default_font_family()
     font.setFamily(ff)
     font.setPointSize(tprefs['editor_font_size'])
     self.tooltip_font = QFont(font)
     self.tooltip_font.setPointSize(font.pointSize() - 1)
     self.setFont(font)
     self.highlighter.apply_theme(theme)
     w = self.fontMetrics()
     self.number_width = max(map(lambda x:w.width(unicode_type(x)), range(10)))
     self.size_hint = QSize(self.expected_geometry[0] * w.averageCharWidth(), self.expected_geometry[1] * w.height())
     self.highlight_color = theme_color(theme, 'HighlightRegion', 'bg')
     self.highlight_cursor_line()
     self.completion_popup.clear_caches(), self.completion_popup.update()
Esempio n. 17
0
    def init_columns(self, defaults=False):
        # Set up columns
        self.opt_columns.blockSignals(True)
        self.model = model = self.gui.library_view.model()
        colmap = list(model.column_map)
        state = self.columns_state(defaults)
        self.hidden_cols = state['hidden_columns']
        positions = state['column_positions']
        colmap.sort(key=lambda x: positions[x])
        self.opt_columns.clear()

        db = model.db
        self.field_metadata = db.field_metadata

        self.opt_columns.setColumnCount(4)
        item = QTableWidgetItem(_('Column header'))
        self.opt_columns.setHorizontalHeaderItem(0, item)
        item = QTableWidgetItem(_('Lookup name'))
        self.opt_columns.setHorizontalHeaderItem(1, item)
        item = QTableWidgetItem(_('Type'))
        self.opt_columns.setHorizontalHeaderItem(2, item)
        item = QTableWidgetItem(_('Description'))
        self.opt_columns.setHorizontalHeaderItem(3, item)

        self.opt_columns.setRowCount(len(colmap))
        self.column_desc = dict(map(lambda x:(CreateCustomColumn.column_types[x]['datatype'],
                                         CreateCustomColumn.column_types[x]['text']),
                                  CreateCustomColumn.column_types))

        for row, col in enumerate(colmap):
            self.setup_row(self.field_metadata, row, col)

        self.restore_geometry()
        self.opt_columns.cellDoubleClicked.connect(self.row_double_clicked)
        self.opt_columns.blockSignals(False)
Esempio n. 18
0
def split_txt(txt, epub_split_size_kb=0):
    '''
    Ensure there are split points for converting
    to EPUB. A misdetected paragraph type can
    result in the entire document being one giant
    paragraph. In this case the EPUB parser will not
    be able to determine where to split the file
    to accommodate the EPUB file size limitation
    and will fail.
    '''
    # Takes care if there is no point to split
    if epub_split_size_kb > 0:
        if isinstance(txt, unicode_type):
            txt = txt.encode('utf-8')
        length_byte = len(txt)
        # Calculating the average chunk value for easy splitting as EPUB (+2 as a safe margin)
        chunk_size = long_type(length_byte / (int(length_byte / (epub_split_size_kb * 1024)) + 2))
        # if there are chunks with a superior size then go and break
        parts = txt.split(b'\n\n')
        lengths = tuple(map(len, parts))
        if lengths and max(lengths) > chunk_size:
            txt = b'\n\n'.join([
                split_string_separator(line, chunk_size) for line in parts
            ])
    if isbytestring(txt):
        txt = txt.decode('utf-8')

    return txt
Esempio n. 19
0
 def drop_event(self, event, mime_data):
     mime = 'application/calibre+from_library'
     if mime_data.hasFormat(mime):
         self.dropped_ids = tuple(map(int, str(mime_data.data(mime)).split()))
         QTimer.singleShot(1, self.do_drop)
         return True
     return False
Esempio n. 20
0
    def parse_text_assertion(self, raw, ans):
        oraw = raw
        if not raw.startswith('['):
            return oraw
        raw = raw[1:]
        ta = {}
        m, raw = self.do_match(self.ta1_pat, raw)
        if m is not None:
            before, after = m.groups()
            ta['before'] = self.unescape(before)
            if after is not None:
                ta['after'] = self.unescape(after)
        else:
            m, raw = self.do_match(self.ta2_pat, raw)
            if m is not None:
                ta['after'] = self.unescape(m.group(1))

        # parse parameters
        m, raw = self.do_match(self.parameters_pat, raw)
        if m is not None:
            params = {}
            for name, value in zip(m.captures(1), m.captures(2)):
                params[name] = tuple(map(self.unescape, self.csv_pat.match(value).captures(1)))
            if params:
                ta['params'] = params

        if not raw.startswith(']'):
            return oraw  # no closing ] or extra content in the assertion

        if ta:
            ans['text_assertion'] = ta
        return raw[1:]
Esempio n. 21
0
 def do_test(self):
     filename = self.value.strip()
     allowed = filter_filename(map(compile_rule, self.rules), filename)
     if allowed is None:
         self.result.setText(_('The filename %s did not match any rules') % filename)
     else:
         self.result.setText(_('The filename {0} will be {1}').format(filename, _('added' if allowed else 'ignored')))
Esempio n. 22
0
    def init_search_box_mixin(self):
        self.search.initialize('main_search_history', colorize=True,
                help_text=_('Search (For advanced search click the gear icon to the left)'))
        self.search.cleared.connect(self.search_box_cleared)
        # Queued so that search.current_text will be correct
        self.search.changed.connect(self.search_box_changed,
                type=Qt.QueuedConnection)
        self.search.focus_to_library.connect(self.focus_to_library)
        self.advanced_search_toggle_action.triggered.connect(self.do_advanced_search)

        self.search.clear()
        self.search.setMaximumWidth(self.width()-150)
        self.action_focus_search = QAction(self)
        shortcuts = list(
                map(lambda x:unicode_type(x.toString(QKeySequence.PortableText)),
                QKeySequence.keyBindings(QKeySequence.Find)))
        shortcuts += ['/', 'Alt+S']
        self.keyboard.register_shortcut('start search', _('Start search'),
                default_keys=shortcuts, action=self.action_focus_search)
        self.action_focus_search.triggered.connect(self.focus_search_box)
        self.addAction(self.action_focus_search)
        self.search.setStatusTip(re.sub(r'<\w+>', ' ',
            unicode_type(self.search.toolTip())))
        self.set_highlight_only_button_icon()
        self.highlight_only_button.clicked.connect(self.highlight_only_clicked)
        tt = _('Enable or disable search highlighting.') + '<br><br>'
        tt += config.help('highlight_search_matches')
        self.highlight_only_button.setToolTip(tt)
        self.highlight_only_action = ac = QAction(self)
        self.addAction(ac), ac.triggered.connect(self.highlight_only_clicked)
        self.keyboard.register_shortcut('highlight search results', _('Highlight search results'), action=self.highlight_only_action)
Esempio n. 23
0
 def refresh_ids(self, ids):
     self.cache.clear_caches(book_ids=ids)
     try:
         return list(map(self.id_to_index, ids))
     except ValueError:
         pass
     return None
Esempio n. 24
0
    def tokenize(self):
        """Main class for handling other methods. Reads the file \
        , uses method self.sub_reg to make basic substitutions,\
        and process tokens by itself"""
        # read
        with open_for_read(self.__file) as read_obj:
            input_file = read_obj.read()

        # process simple replacements and split giving us a correct list
        # remove '' and \n in the process
        tokens = self.__sub_reg_split(input_file)
        # correct unicode
        tokens = map(self.__unicode_process, tokens)
        # remove empty items created by removing \uc
        tokens = list(filter(lambda x: len(x) > 0, tokens))

        # write
        with open_for_write(self.__write_to) as write_obj:
            write_obj.write('\n'.join(tokens))
        # Move and copy
        copy_obj = copy.Copy(bug_handler=self.__bug_handler)
        if self.__copy:
            copy_obj.copy_file(self.__write_to, "tokenize.data")
        copy_obj.rename(self.__write_to, self.__file)
        os.remove(self.__write_to)
Esempio n. 25
0
def metadata_extensions():
    # Set of all known book extensions + OPF (the OPF is used to read metadata,
    # but not actually added)
    global _metadata_extensions
    if _metadata_extensions is None:
        _metadata_extensions =  frozenset(map(unicode, BOOK_EXTENSIONS)) | {'opf'}
    return _metadata_extensions
Esempio n. 26
0
    def generate_catalog(self):
        rows = self.gui.library_view.selectionModel().selectedRows()
        if not rows or len(rows) < 2:
            rows = range(self.gui.library_view.model().rowCount(QModelIndex()))
        ids = list(map(self.gui.library_view.model().id, rows))

        if not ids:
            return error_dialog(self.gui, _('No books selected'),
                    _('No books selected for catalog generation'),
                    show=True)

        db = self.gui.library_view.model().db
        dbspec = {}
        for id in ids:
            dbspec[id] = {'ondevice': db.ondevice(id, index_is_id=True)}

        # Calling gui2.tools:generate_catalog()
        ret = generate_catalog(self.gui, dbspec, ids, self.gui.device_manager,
                db)
        if ret is None:
            return

        func, args, desc, out, sync, title = ret

        fmt = os.path.splitext(out)[1][1:].upper()
        job = self.gui.job_manager.run_job(
                self.Dispatcher(self.catalog_generated), func, args=args,
                description=desc)
        job.catalog_file_path = out
        job.fmt = fmt
        job.catalog_sync, job.catalog_title = sync, title
        self.gui.status_bar.show_message(_('Generating %s catalog...')%fmt)
Esempio n. 27
0
    def commit(self, urn=None):
        urn = self.current_urn if urn is None else urn
        if not self.detail_box.isVisible() or urn is None:
            return True

        if self.account.isVisible():
            un, pw = map(unicode_type, (self.username.text(), self.password.text()))
            un, pw = un.strip(), pw.strip()
            if not un and not pw and self.schedule.isChecked():
                if not getattr(self, 'subscription_optional', False):
                    error_dialog(self, _('Need username and password'),
                            _('You must provide a username and/or password to '
                                'use this news source.'), show=True)
                    return False
            if un or pw:
                self.recipe_model.set_account_info(urn, un, pw)
            else:
                self.recipe_model.clear_account_info(urn)

        if self.schedule.isChecked():
            schedule_type, schedule = \
                    self.schedule_stack.currentWidget().schedule
            self.recipe_model.schedule_recipe(urn, schedule_type, schedule)
        else:
            self.recipe_model.un_schedule_recipe(urn)

        add_title_tag = self.add_title_tag.isChecked()
        keep_issues = u'0'
        if self.keep_issues.isEnabled():
            keep_issues = unicode_type(self.keep_issues.value())
        custom_tags = unicode_type(self.custom_tags.text()).strip()
        custom_tags = [x.strip() for x in custom_tags.split(',')]
        self.recipe_model.customize_recipe(urn, add_title_tag, custom_tags, keep_issues)
        return True
Esempio n. 28
0
 def periodical(self):
     '''
     TAGX block for the Primary index header of a periodical
     '''
     list(map(self.add_tag, (1, 2, 3, 4, 5, 21, 22, 23, 0, 69, 70, 71, 72,
         73, 0)))
     return self.header(2) + bytes(self.byts)
Esempio n. 29
0
def sort_q_values(header_val):
    'Get sorted items from an HTTP header of type: a;q=0.5, b;q=0.7...'
    if not header_val:
        return []

    def item(x):
        e, r = x.partition(';')[::2]
        p, v = r.partition('=')[::2]
        q = 1.0
        if p == 'q' and v:
            try:
                q = max(0.0, min(1.0, float(v.strip())))
            except Exception:
                pass
        return e.strip(), q
    return tuple(map(itemgetter(0), sorted(map(item, parse_http_list(header_val)), key=itemgetter(1), reverse=True)))
Esempio n. 30
0
    def create_cover_markup(self, img, preserve_aspect_ratio, width, height):
        self.count += 1
        makeelement, namespaces = self.document_relationships.namespace.makeelement, self.document_relationships.namespace.namespaces
        if preserve_aspect_ratio:
            if img.width >= img.height:
                ar = img.height / img.width
                height = ar * width
            else:
                ar = img.width / img.height
                width = ar * height

        root = etree.Element('root', nsmap=namespaces)
        ans = makeelement(root, 'w:drawing', append=False)
        parent = makeelement(ans, 'wp:anchor', **{'dist'+edge:'0' for edge in 'LRTB'})
        parent.set('simplePos', '0'), parent.set('relativeHeight', '1'), parent.set('behindDoc',"0"), parent.set('locked', "0")
        parent.set('layoutInCell', "1"), parent.set('allowOverlap', '1')
        makeelement(parent, 'wp:simplePos', x='0', y='0')
        makeelement(makeelement(parent, 'wp:positionH', relativeFrom='page'), 'wp:align').text = 'center'
        makeelement(makeelement(parent, 'wp:positionV', relativeFrom='page'), 'wp:align').text = 'center'
        width, height = map(pt_to_emu, (width, height))
        makeelement(parent, 'wp:extent', cx=unicode_type(width), cy=unicode_type(height))
        makeelement(parent, 'wp:effectExtent', l='0', r='0', t='0', b='0')
        makeelement(parent, 'wp:wrapTopAndBottom')
        self.create_docx_image_markup(parent, 'cover.jpg', _('Cover'), img.rid, width, height)
        return ans
Esempio n. 31
0
def merge_multiple_html_heads_and_bodies(root, log=None):
    heads, bodies = xpath(root, '//h:head'), xpath(root, '//h:body')
    if not (len(heads) > 1 or len(bodies) > 1):
        return root
    for child in root:
        root.remove(child)
    head = root.makeelement(XHTML('head'))
    body = root.makeelement(XHTML('body'))
    for h in heads:
        for x in h:
            head.append(x)
    for b in bodies:
        for x in b:
            body.append(x)
    tuple(map(root.append, (head, body)))
    if log is not None:
        log.warn('Merging multiple <head> and <body> sections')
    return root
Esempio n. 32
0
 def test_ssl(self):
     'Test serving over SSL'
     address = '127.0.0.1'
     with TemporaryDirectory('srv-test-ssl') as tdir:
         cert_file, key_file, ca_file = map(lambda x:os.path.join(tdir, x), 'cka')
         create_server_cert(address, ca_file, cert_file, key_file, key_size=2048)
         ctx = ssl.create_default_context(cafile=ca_file)
         with TestServer(
                 lambda data:(data.path[0] + data.read().decode('utf-8')),
                 ssl_certfile=cert_file, ssl_keyfile=key_file, listen_on=address, port=0) as server:
             conn = http_client.HTTPSConnection(address, server.address[1], context=ctx)
             conn.request('GET', '/test', 'body')
             r = conn.getresponse()
             self.ae(r.status, http_client.OK)
             self.ae(r.read(), b'testbody')
             cert = conn.sock.getpeercert()
             subject = dict(x[0] for x in cert['subject'])
             self.ae(subject['commonName'], address)
Esempio n. 33
0
 def __init__(self, plugin):
     self.name = plugin['index_name']
     self.qname = plugin.get('name', self.name)
     self.forum_link = plugin['thread_url']
     self.zip_url = SERVER + plugin['file']
     self.installed_version = None
     self.description = plugin['description']
     self.donation_link = plugin['donate']
     self.available_version = tuple(plugin['version'])
     self.release_date = datetime.datetime(*tuple(
         map(int, re.split(r'\D', plugin['last_modified'])))[:6]).date()
     self.calibre_required_version = tuple(
         plugin['minimum_calibre_version'])
     self.author = plugin['author']
     self.platforms = plugin['supported_platforms']
     self.uninstall_plugins = plugin['uninstall'] or []
     self.has_changelog = plugin['history']
     self.is_deprecated = plugin['deprecated']
Esempio n. 34
0
 def split_text(self, text, root, size):
     self.log.debug('\t\t\tSplitting text of length: %d' % len(text))
     rest = text.replace('\r', '')
     parts = re.split('\n\n', rest)
     self.log.debug('\t\t\t\tFound %d parts' % len(parts))
     if max(map(len, parts)) > size:
         raise SplitError(
             'Cannot split as file contains a <pre> tag '
             'with a very large paragraph', root)
     ans = []
     buf = ''
     for part in parts:
         if len(buf) + len(part) < size:
             buf += '\n\n' + part
         else:
             ans.append(buf)
             buf = part
     return ans
Esempio n. 35
0
    def save_to_disk(self, checked, single_dir=False, single_format=None,
            rows=None, write_opf=None, save_cover=None):
        if rows is None:
            rows = self.gui.current_view().selectionModel().selectedRows()
        if not rows or len(rows) == 0:
            return error_dialog(self.gui, _('Cannot save to disk'),
                    _('No books selected'), show=True)
        path = choose_dir(self.gui, 'save to disk dialog',
                _('Choose destination directory'))
        if not path:
            return
        dpath = os.path.abspath(path).replace('/', os.sep)+os.sep
        lpath = self.gui.library_view.model().db.library_path.replace('/',
                os.sep)+os.sep
        if dpath.startswith(lpath):
            return error_dialog(self.gui, _('Not allowed'),
                    _('You are trying to save files into the calibre '
                      'library. This can cause corruption of your '
                      'library. Save to disk is meant to export '
                      'files from your calibre library elsewhere.'), show=True)

        if self.gui.current_view() is self.gui.library_view:
            from calibre.gui2.save import Saver
            from calibre.library.save_to_disk import config
            opts = config().parse()
            if single_format is not None:
                opts.formats = single_format
                # Special case for Kindle annotation files
                if single_format.lower() in ['mbp','pdr','tan']:
                    opts.to_lowercase = False
                    opts.save_cover = False
                    opts.write_opf = False
                    opts.template = opts.send_template
            opts.single_dir = single_dir
            if write_opf is not None:
                opts.write_opf = write_opf
            if save_cover is not None:
                opts.save_cover = save_cover
            book_ids = set(map(self.gui.library_view.model().id, rows))
            Saver(book_ids, self.gui.current_db, opts, path, parent=self.gui, pool=self.gui.spare_pool())
        else:
            paths = self.gui.current_view().model().paths(rows)
            self.gui.device_manager.save_books(
                    Dispatcher(self.books_saved), paths, path)
Esempio n. 36
0
    def load(self, path_to_zip_file):
        if not os.access(path_to_zip_file, os.R_OK):
            raise PluginNotFound('Cannot access %r'%path_to_zip_file)

        with zipfile.ZipFile(path_to_zip_file) as zf:
            plugin_name = self._locate_code(zf, path_to_zip_file)

        try:
            ans = None
            plugin_module = 'calibre_plugins.%s'%plugin_name
            m = sys.modules.get(plugin_module, None)
            if m is not None:
                reload(m)
            else:
                m = importlib.import_module(plugin_module)
            plugin_classes = []
            for obj in itervalues(m.__dict__):
                if isinstance(obj, type) and issubclass(obj, Plugin) and \
                        obj.name != 'Trivial Plugin':
                    plugin_classes.append(obj)
            if not plugin_classes:
                raise InvalidPlugin('No plugin class found in %s:%s'%(
                    as_unicode(path_to_zip_file), plugin_name))
            if len(plugin_classes) > 1:
                plugin_classes.sort(key=lambda c:(getattr(c, '__module__', None) or '').count('.'))

            ans = plugin_classes[0]

            if ans.minimum_calibre_version > numeric_version:
                raise InvalidPlugin(
                    'The plugin at %s needs a version of calibre >= %s' %
                    (as_unicode(path_to_zip_file), '.'.join(map(unicode_type,
                        ans.minimum_calibre_version))))

            if platform not in ans.supported_platforms:
                raise InvalidPlugin(
                    'The plugin at %s cannot be used on %s' %
                    (as_unicode(path_to_zip_file), platform))

            return ans
        except:
            with self._lock:
                del self.loaded_plugins[plugin_name]
            raise
Esempio n. 37
0
def custom_dictionaries(reread=False):
    global _custom
    if _custom is None or reread:
        dics = []
        for lc in glob.glob(os.path.join(config_dir, 'dictionaries', '*/locales')):
            locales = list(filter(None, open(lc, 'rb').read().decode('utf-8').splitlines()))
            try:
                name, locale, locales = locales[0], locales[1], locales[1:]
            except IndexError:
                continue
            base = os.path.dirname(lc)
            ploc = parse_lang_code(locale)
            if ploc.countrycode is None:
                continue
            dics.append(Dictionary(
                ploc, frozenset(filter(lambda x:x.countrycode is not None, map(parse_lang_code, locales))), os.path.join(base, '%s.dic' % locale),
                os.path.join(base, '%s.aff' % locale), False, name, os.path.basename(base)))
        _custom = frozenset(dics)
    return _custom
Esempio n. 38
0
    def metadata_from_path(cls, path):
        def check_unicode(txt):
            if not isinstance(txt, unicode_type):
                txt = txt.decode(filesystem_encoding, 'replace')
            txt = txt.replace('_', ' ')
            return txt

        mi = cls.metadata_from_formats([path])

        if (mi.title==_('Unknown') or mi.authors==[_('Unknown')]) \
                and '#' in mi.title:
            fn = os.path.splitext(os.path.basename(path))[0]
            match = cls.JETBOOK_FILE_NAME_PATTERN.match(fn)
            if match is not None:
                mi.title = check_unicode(match.group('title'))
                authors = string_to_authors(match.group('authors'))
                mi.authors = list(map(check_unicode, authors))

        return mi
Esempio n. 39
0
 def serialize_node(node):
     return {
         'title':
         node.data(0, Qt.DisplayRole),
         'toc_node':
         node.data(0, Qt.UserRole),
         'icon':
         node.data(0, Qt.DecorationRole),
         'tooltip':
         node.data(0, Qt.ToolTipRole),
         'is_selected':
         node.isSelected(),
         'is_expanded':
         node.isExpanded(),
         'children':
         list(
             map(serialize_node,
                 (node.child(i) for i in range(node.childCount())))),
     }
Esempio n. 40
0
def create_skeleton(opts, namespaces=None):
    namespaces = namespaces or DOCXNamespace().namespaces

    def w(x):
        return '{%s}%s' % (namespaces['w'], x)
    dn = {k:v for k, v in iteritems(namespaces) if k in {'w', 'r', 'm', 've', 'o', 'wp', 'w10', 'wne', 'a', 'pic'}}
    E = ElementMaker(namespace=dn['w'], nsmap=dn)
    doc = E.document()
    body = E.body()
    doc.append(body)
    width, height = page_size(opts)
    width, height = int(20 * width), int(20 * height)

    def margin(which):
        val = page_margin(opts, which)
        return w(which), str(int(val * 20))
    body.append(E.sectPr(
        E.pgSz(**{w('w'):str(width), w('h'):str(height)}),
        E.pgMar(**dict(map(margin, 'left top right bottom'.split()))),
        E.cols(**{w('space'):'720'}),
        E.docGrid(**{w('linePitch'):"360"}),
    ))

    dn = {k:v for k, v in iteritems(namespaces) if k in tuple('wra') + ('wp',)}
    E = ElementMaker(namespace=dn['w'], nsmap=dn)
    styles = E.styles(
        E.docDefaults(
            E.rPrDefault(
                E.rPr(
                    E.rFonts(**{w('asciiTheme'):"minorHAnsi", w('eastAsiaTheme'):"minorEastAsia", w('hAnsiTheme'):"minorHAnsi", w('cstheme'):"minorBidi"}),
                    E.sz(**{w('val'):'22'}),
                    E.szCs(**{w('val'):'22'}),
                    E.lang(**{w('val'):'en-US', w('eastAsia'):"en-US", w('bidi'):"ar-SA"})
                )
            ),
            E.pPrDefault(
                E.pPr(
                    E.spacing(**{w('after'):"0", w('line'):"276", w('lineRule'):"auto"})
                )
            )
        )
    )
    return doc, styles, body
Esempio n. 41
0
def create_indexing_data(spine, toc):
    if not toc:
        return
    f = partial(IndexEntry, spine)
    index_entries = list(
        map(f, (t for t in toc.flat() if t is not toc),
            (i - 1 for i, t in enumerate(toc.flat()) if t is not toc)))
    index_entries.sort(key=attrgetter('sort_key'))
    [i.find_end(index_entries) for i in index_entries]

    ie = namedtuple('IndexEntry', 'entry start_anchor end_anchor')

    for spine_pos, spine_item in enumerate(spine):
        for i in index_entries:
            if i.end_spine_pos < spine_pos or i.spine_pos > spine_pos:
                continue  # Does not touch this file
            start = i.anchor if i.spine_pos == spine_pos else None
            end = i.end_anchor if i.spine_pos == spine_pos else None
            spine_item.index_entries.append(ie(i, start, end))
Esempio n. 42
0
def simple_load_icon(module, index, as_data=False, size=ICON_SIZE):
    ' Use the win32 API ExtractIcon to load the icon. This restricts icon size to 32x32, but has less chance of failing '
    try:
        large_icons, small_icons = win32gui.ExtractIconEx(module, index, 10)
    except pywintypes.error as err:
        if err.winerror != winerror.ERROR_FILE_NOT_FOUND:
            raise
        prints('File %r does not exist, cannot load icon' % module)
        return
    icons = large_icons + small_icons
    try:
        if icons:
            must_use_qt()
            pixmap = copy_to_size(QtWin.fromHICON(icons[0]), size=size)
            if as_data:
                return pixmap_to_data(pixmap)
            return QIcon(pixmap)
    finally:
        tuple(map(win32gui.DestroyIcon, icons))
Esempio n. 43
0
def remove_links_to(container, predicate):
    ''' predicate must be a function that takes the arguments (name, href,
    fragment=None) and returns True iff the link should be removed '''
    from calibre.ebooks.oeb.base import iterlinks, OEB_DOCS, OEB_STYLES, XPath, XHTML
    stylepath = XPath('//h:style')
    styleattrpath = XPath('//*[@style]')
    changed = set()
    for name, mt in iteritems(container.mime_map):
        removed = False
        if mt in OEB_DOCS:
            root = container.parsed(name)
            for el, attr, href, pos in iterlinks(root, find_links_in_css=False):
                hname = container.href_to_name(href, name)
                frag = href.partition('#')[-1]
                if predicate(hname, href, frag):
                    if attr is None:
                        el.text = None
                    else:
                        if el.tag == XHTML('link') or el.tag == XHTML('img'):
                            extract(el)
                        else:
                            del el.attrib[attr]
                    removed = True
            for tag in stylepath(root):
                if tag.text and (tag.get('type') or 'text/css').lower() == 'text/css':
                    sheet = container.parse_css(tag.text)
                    if remove_links_in_sheet(partial(container.href_to_name, base=name), sheet, predicate):
                        tag.text = css_text(sheet)
                        removed = True
            for tag in styleattrpath(root):
                style = tag.get('style')
                if style:
                    style = container.parse_css(style, is_declaration=True)
                    if remove_links_in_declaration(partial(container.href_to_name, base=name), style, predicate):
                        removed = True
                        tag.set('style', css_text(style))
        elif mt in OEB_STYLES:
            removed = remove_links_in_sheet(partial(container.href_to_name, base=name), container.parsed(name), predicate)
        if removed:
            changed.add(name)
    tuple(map(container.dirty, changed))
    return changed
Esempio n. 44
0
    def init_search_box_mixin(self):
        self.search.initialize(
            'main_search_history',
            colorize=True,
            help_text=_(
                'Search (For advanced search click the gear icon to the left)')
        )
        self.search.cleared.connect(self.search_box_cleared)
        # Queued so that search.current_text will be correct
        self.search.changed.connect(self.search_box_changed,
                                    type=Qt.ConnectionType.QueuedConnection)
        self.search.focus_to_library.connect(self.focus_to_library)
        self.advanced_search_toggle_action.triggered.connect(
            self.do_advanced_search)

        self.search.clear()
        self.search.setMaximumWidth(self.width() - 150)
        self.action_focus_search = QAction(self)
        shortcuts = list(
            map(
                lambda x: unicode_type(
                    x.toString(QKeySequence.SequenceFormat.PortableText)),
                QKeySequence.keyBindings(QKeySequence.StandardKey.Find)))
        shortcuts += ['/', 'Alt+S']
        self.keyboard.register_shortcut('start search',
                                        _('Start search'),
                                        default_keys=shortcuts,
                                        action=self.action_focus_search)
        self.action_focus_search.triggered.connect(self.focus_search_box)
        self.addAction(self.action_focus_search)
        self.search.setStatusTip(
            re.sub(r'<\w+>', ' ', unicode_type(self.search.toolTip())))
        self.set_highlight_only_button_icon()
        self.highlight_only_button.clicked.connect(self.highlight_only_clicked)
        tt = _('Enable or disable search highlighting.') + '<br><br>'
        tt += config.help('highlight_search_matches')
        self.highlight_only_button.setToolTip(tt)
        self.highlight_only_action = ac = QAction(self)
        self.addAction(ac), ac.triggered.connect(self.highlight_only_clicked)
        self.keyboard.register_shortcut('highlight search results',
                                        _('Highlight search results'),
                                        action=self.highlight_only_action)
Esempio n. 45
0
def builtin_dictionaries():
    global _builtins
    if _builtins is None:
        dics = []
        for lc in glob.glob(
                os.path.join(P('dictionaries', allow_user_override=False),
                             '*/locales')):
            locales = list(
                filter(None,
                       open(lc, 'rb').read().decode('utf-8').splitlines()))
            locale = locales[0]
            base = os.path.dirname(lc)
            dics.append(
                Dictionary(parse_lang_code(locale),
                           frozenset(map(parse_lang_code, locales)),
                           os.path.join(base, '%s.dic' % locale),
                           os.path.join(base, '%s.aff' % locale), True, None,
                           None))
        _builtins = frozenset(dics)
    return _builtins
Esempio n. 46
0
def parse_nav(container, nav_name):
    root = container.parsed(nav_name)
    toc_root = TOC()
    toc_root.lang = toc_root.uid = None
    et = '{%s}type' % EPUB_NS
    for nav in root.iterdescendants(XHTML('nav')):
        if nav.get(et) == 'toc':
            ol = first_child(nav, XHTML('ol'))
            if ol is not None:
                process_nav_node(container, ol, toc_root, nav_name)
                for h in nav.iterchildren(
                        *map(XHTML, 'h1 h2 h3 h4 h5 h6'.split())):
                    text = etree.tostring(
                        h, method='text', encoding='unicode',
                        with_tail=False) or h.get('title')
                    if text:
                        toc_root.toc_title = text
                        break
                break
    return toc_root
Esempio n. 47
0
 def dropMimeData(self, md, action, row, column, parent):
     if action != Qt.MoveAction or not md.hasFormat(
             'application/calibre_charcode_indices'
     ) or row < 0 or column != 0:
         return False
     indices = list(
         map(
             int,
             bytes(md.data('application/calibre_charcode_indices')).decode(
                 'ascii').split(',')))
     codes = [self.chars[x] for x in indices]
     for x in indices:
         self.chars[x] = None
     for x in reversed(codes):
         self.chars.insert(row, x)
     self.beginResetModel()
     self.chars = [x for x in self.chars if x is not None]
     self.endResetModel()
     tprefs['charmap_favorites'] = list(self.chars)
     return True
Esempio n. 48
0
 def apply_settings(self):
     self.keyboard.finalize()
     self.setDockNestingEnabled(tprefs['nestable_dock_widgets'])
     for v, h in product(('top', 'bottom'), ('left', 'right')):
         p = 'dock_%s_%s' % (v, h)
         pref = tprefs[p] or tprefs.defaults[p]
         area = getattr(
             Qt, '%sDockWidgetArea' % capitalize({
                 'vertical': h,
                 'horizontal': v
             }[pref]))
         self.setCorner(
             getattr(Qt, '%s%sCorner' % tuple(map(capitalize, (v, h)))),
             area)
     self.preview.apply_settings()
     self.live_css.apply_theme()
     for bar in (self.global_bar, self.tools_bar, self.plugins_bar):
         bar.setIconSize(
             QSize(tprefs['toolbar_icon_size'],
                   tprefs['toolbar_icon_size']))
Esempio n. 49
0
    def test_qt(self):
        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 the QT_PLUGIN_PATH env var is set. 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 Application
        os.environ.pop('DISPLAY', None)
        has_headless = isosx or islinux
        app = Application([], headless=has_headless)
        self.assertGreaterEqual(len(QFontDatabase().families()), 5, 'The QPA headless plugin is not able to locate enough system fonts via fontconfig')
        if has_headless:
            from calibre.ebooks.covers import create_cover
            create_cover('xxx', ['yyy'])
        na = QNetworkAccessManager()
        self.assertTrue(hasattr(na, 'sslErrors'), 'Qt not compiled with openssl')
        from PyQt5.QtWebKitWidgets import QWebView
        if iswindows:
            from PyQt5.Qt import QtWin
            QtWin
        QWebView()
        del QWebView
        del na
        del app
Esempio n. 50
0
    def write_widths(self, objects):
        glyphs = sorted(self.used_glyphs|{0})
        widths = {g:self.metrics.pdf_scale(w) for g, w in zip(glyphs,
                                        self.metrics.glyph_widths(glyphs))}
        counter = Counter()
        for g, w in widths.iteritems():
            counter[w] += 1
        most_common = counter.most_common(1)[0][0]
        self.descendant_font['DW'] = most_common
        widths = {g:w for g, w in widths.iteritems() if w != most_common}

        groups = Array()
        for k, g in groupby(enumerate(widths.iterkeys()), lambda i_x:i_x[0]-i_x[1]):
            group = list(map(itemgetter(1), g))
            gwidths = [widths[g] for g in group]
            if len(set(gwidths)) == 1 and len(group) > 1:
                w = (min(group), max(group), gwidths[0])
            else:
                w = (min(group), Array(gwidths))
            groups.extend(w)
        self.descendant_font['W'] = objects.add(groups)
Esempio n. 51
0
 def refresh_ids(self, db, ids):
     '''
     Refresh the data in the cache for books identified by ids.
     Returns a list of affected rows or None if the rows are filtered.
     '''
     for id in ids:
         try:
             self._data[id] = CacheRow(db, self.composites, self.datetimes,
                     db.conn.get('SELECT * from meta2 WHERE id=?', (id,))[0],
                     self.series_col, self.series_sort_col)
             self._data[id].append(db.book_on_device_string(id))
             self._data[id].append(self.marked_ids_dict.get(id, None))
             self._data[id].append(None)
             self._uuid_map[self._data[id][self._uuid_column_index]] = id
         except IndexError:
             return None
     try:
         return list(map(self.row, ids))
     except ValueError:
         pass
     return None
Esempio n. 52
0
 def template(self):
     if not self.color or not self.conditions:
         return None
     conditions = [x for x in map(self.apply_condition, self.conditions) if x is not None]
     conditions = (',\n' + ' '*9).join(conditions)
     if len(self.conditions) > 1:
         return dedent('''\
                 program:
                 {sig}
                 test(and(
                          {conditions}
                     ), '{color}', '');
                 ''').format(sig=self.signature, conditions=conditions,
                         color=self.color)
     else:
         return dedent('''\
                 program:
                 {sig}
                 test({conditions}, '{color}', '');
                 ''').format(sig=self.signature, conditions=conditions,
                         color=self.color)
class ChunkIndex(Index):

    tag_types = tuple(map(TagMeta, (
        ('cncx_offset',     2, 1, 1, 0),
        ('file_number',     3, 1, 2, 0),
        ('sequence_number', 4, 1, 4, 0),
        ('geometry',        6, 2, 8, 0),
        EndTagTable
    )))

    def __init__(self, chunk_table):
        self.cncx = CNCX(c.selector for c in chunk_table)

        self.entries = [
                ('%010d'%c.insert_pos, {

                    'cncx_offset':self.cncx[c.selector],
                    'file_number':c.file_number,
                    'sequence_number':c.sequence_number,
                    'geometry':(c.start_pos, c.length),
                    }) for c in chunk_table
        ]
Esempio n. 54
0
def iterusbdevices():
    buf = None
    pat = devid_pat()
    for dev_list, devinfo in DeviceSet(guid=None,
                                       enumerator='USB',
                                       flags=DIGCF_PRESENT
                                       | DIGCF_ALLCLASSES).devices():
        buf, devid = get_device_registry_property(dev_list,
                                                  byref(devinfo),
                                                  buf=buf)
        if devid:
            devid = devid[0].lower()
            m = pat.search(devid)
            if m is None:
                yield USBDevice(None, None, None, devid, devinfo.DevInst)
            else:
                try:
                    vid, pid, bcd = map(parse_hex, m.group(1, 2, 3))
                except Exception:
                    yield USBDevice(None, None, None, devid, devinfo.DevInst)
                else:
                    yield USBDevice(vid, pid, bcd, devid, devinfo.DevInst)
Esempio n. 55
0
    def load_huff(self, huff):
        if huff[0:8] != b'HUFF\x00\x00\x00\x18':
            raise MobiError('Invalid HUFF header')
        off1, off2 = struct.unpack_from(b'>LL', huff, 8)

        def dict1_unpack(v):
            codelen, term, maxcode = v&0x1f, v&0x80, v>>8
            assert codelen != 0
            if codelen <= 8:
                assert term
            maxcode = ((maxcode + 1) << (32 - codelen)) - 1
            return (codelen, term, maxcode)
        self.dict1 = tuple(map(dict1_unpack, struct.unpack_from(b'>256L', huff, off1)))

        dict2 = struct.unpack_from(b'>64L', huff, off2)
        self.mincode, self.maxcode = (), ()
        for codelen, mincode in enumerate((0,) + dict2[0::2]):
            self.mincode += (mincode << (32 - codelen), )
        for codelen, maxcode in enumerate((0,) + dict2[1::2]):
            self.maxcode += (((maxcode + 1) << (32 - codelen)) - 1, )

        self.dictionary = []
Esempio n. 56
0
def text_to_regex(text):
    has_leading = text.lstrip() != text
    has_trailing = text.rstrip() != text
    if text and not text.strip():
        return r'\s+'
    ans = []
    for wpart in spat.split(text.strip()):
        if not wpart.strip():
            ans.append(r'\s+')
        else:
            for part in qpat.split(wpart):
                r = quote_map.get(part)
                if r is not None:
                    ans.append('[' + r + ']')
                else:
                    part = invisible_chars.join(map(regex.escape, part))
                    ans.append(part)
    if has_leading:
        ans.insert(0, r'\s+')
    if has_trailing:
        ans.append(r'\s+')
    return ''.join(ans)
Esempio n. 57
0
    def commit(self, urn=None):
        urn = self.current_urn if urn is None else urn
        if not self.detail_box.isVisible() or urn is None:
            return True

        if self.account.isVisible():
            un, pw = map(unicode_type,
                         (self.username.text(), self.password.text()))
            un, pw = un.strip(), pw.strip()
            if not un and not pw and self.schedule.isChecked():
                if not getattr(self, 'subscription_optional', False):
                    error_dialog(
                        self,
                        _('Need username and password'),
                        _('You must provide a username and/or password to '
                          'use this news source.'),
                        show=True)
                    return False
            if un or pw:
                self.recipe_model.set_account_info(urn, un, pw)
            else:
                self.recipe_model.clear_account_info(urn)

        if self.schedule.isChecked():
            schedule_type, schedule = \
                    self.schedule_stack.currentWidget().schedule
            self.recipe_model.schedule_recipe(urn, schedule_type, schedule)
        else:
            self.recipe_model.un_schedule_recipe(urn)

        add_title_tag = self.add_title_tag.isChecked()
        keep_issues = '0'
        if self.keep_issues.isEnabled():
            keep_issues = unicode_type(self.keep_issues.value())
        custom_tags = unicode_type(self.custom_tags.text()).strip()
        custom_tags = [x.strip() for x in custom_tags.split(',')]
        self.recipe_model.customize_recipe(urn, add_title_tag, custom_tags,
                                           keep_issues)
        return True
Esempio n. 58
0
    def update_found(self, calibre_version, number_of_plugin_updates, force=False, no_show_popup=False):
        self.last_newest_calibre_version = calibre_version
        has_calibre_update = calibre_version != NO_CALIBRE_UPDATE and calibre_version[0] > 0
        has_plugin_updates = number_of_plugin_updates > 0
        self.plugin_update_found(number_of_plugin_updates)
        version_url = as_hex_unicode(msgpack_dumps((calibre_version, number_of_plugin_updates)))
        calibre_version = u'.'.join(map(unicode_type, calibre_version))

        if not has_calibre_update and not has_plugin_updates:
            self.status_bar.update_label.setVisible(False)
            return
        if has_calibre_update:
            plt = u''
            if has_plugin_updates:
                plt = ngettext(' (one plugin update)', ' ({} plugin updates)', number_of_plugin_updates).format(number_of_plugin_updates)
            msg = (u'<span style="color:green; font-weight: bold">%s: '
                    u'<a href="update:%s">%s%s</a></span>') % (
                        _('Update found'), version_url, calibre_version, plt)
        else:
            plt = ngettext('updated plugin', 'updated plugins', number_of_plugin_updates)
            msg = (u'<a href="update:%s">%d %s</a>')%(version_url, number_of_plugin_updates, plt)
        self.status_bar.update_label.setText(msg)
        self.status_bar.update_label.setVisible(True)

        if has_calibre_update:
            if (force or (config.get('new_version_notification') and not is_version_notified(calibre_version))):
                if not no_show_popup:
                    self._update_notification__ = UpdateNotification(calibre_version,
                            number_of_plugin_updates, parent=self)
                    self._update_notification__.show()
        elif has_plugin_updates:
            if force:
                from calibre.gui2.dialogs.plugin_updater import (PluginUpdaterDialog,
                    FILTER_UPDATE_AVAILABLE)
                d = PluginUpdaterDialog(self,
                        initial_filter=FILTER_UPDATE_AVAILABLE)
                d.exec_()
                if d.do_restart:
                    self.quit(restart=True)
Esempio n. 59
0
def add_anchors_markup(root, uuid, anchors):
    body = last_tag(root)
    div = body.makeelement(
        XHTML('div'),
        id=uuid,
        style=
        'display:block !important; page-break-before: always !important; break-before: always !important; white-space: pre-wrap !important'
    )
    div.text = '\n\n'
    body.append(div)

    def a(anchor):
        a = div.makeelement(
            XHTML('a'),
            href='#' + anchor,
            style=
            'min-width: 10px !important; min-height: 10px !important; border: solid 1px !important;'
        )
        a.text = a.tail = ' '
        div.append(a)

    tuple(map(a, anchors))
    a(uuid)
Esempio n. 60
0
def get_covers(themes, callback, num_of_workers=8):
    items = Queue()
    tuple(map(items.put, themes))

    def run():
        while True:
            try:
                metadata = items.get_nowait()
            except Empty:
                return
            try:
                cdata = get_cover(metadata)
            except Exception as e:
                import traceback
                traceback.print_exc()
                callback(metadata, e)
            else:
                callback(metadata, cdata)

    for w in xrange(num_of_workers):
        t = Thread(name='IconThemeCover', target=run)
        t.daemon = True
        t.start()