diff --git a/session.vim b/session.vim index 454b468ae0..f33590c838 100644 --- a/session.vim +++ b/session.vim @@ -1,5 +1,5 @@ " Project wide builtins -let g:pyflakes_builtins += ["dynamic_property", '__'] +let g:pyflakes_builtins += ["dynamic_property", "__"] python << EOFPY import os diff --git a/src/calibre/constants.py b/src/calibre/constants.py index 817452d558..9d9fc7310a 100644 --- a/src/calibre/constants.py +++ b/src/calibre/constants.py @@ -2,7 +2,7 @@ __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' __docformat__ = 'restructuredtext en' __appname__ = 'calibre' -__version__ = '0.5.3' +__version__ = '0.5.4' __author__ = "Kovid Goyal " ''' Various run time constants. diff --git a/src/calibre/ebooks/metadata/opf2.py b/src/calibre/ebooks/metadata/opf2.py index 24e5dd83fc..f6b5a9bd1a 100644 --- a/src/calibre/ebooks/metadata/opf2.py +++ b/src/calibre/ebooks/metadata/opf2.py @@ -510,8 +510,6 @@ class OPF(object): except: pass - - def get_text(self, elem): return u''.join(self.CONTENT(elem) or self.TEXT(elem)) diff --git a/src/calibre/ebooks/metadata/toc.py b/src/calibre/ebooks/metadata/toc.py index 8ea73be478..65e95f4c6b 100644 --- a/src/calibre/ebooks/metadata/toc.py +++ b/src/calibre/ebooks/metadata/toc.py @@ -1,7 +1,7 @@ #!/usr/bin/env python __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal ' -import os, glob +import os, glob, re from urlparse import urlparse from urllib import unquote @@ -10,17 +10,17 @@ from calibre.ebooks.BeautifulSoup import BeautifulStoneSoup, BeautifulSoup from calibre.ebooks.chardet import xml_to_unicode class NCXSoup(BeautifulStoneSoup): - + NESTABLE_TAGS = {'navpoint':[]} - + def __init__(self, raw): - BeautifulStoneSoup.__init__(self, raw, + BeautifulStoneSoup.__init__(self, raw, convertEntities=BeautifulSoup.HTML_ENTITIES, selfClosingTags=['meta', 'content']) class TOC(list): - - def __init__(self, href=None, fragment=None, text=None, parent=None, play_order=0, + + def __init__(self, href=None, fragment=None, text=None, parent=None, play_order=0, base_path=os.getcwd(), type='unknown'): self.href = href self.fragment = fragment @@ -31,7 +31,7 @@ class TOC(list): self.base_path = base_path self.play_order = play_order self.type = type - + def __str__(self): lines = ['TOC: %s#%s'%(self.href, self.fragment)] for child in self: @@ -39,10 +39,10 @@ class TOC(list): for l in c: lines.append('\t'+l) return '\n'.join(lines) - + def count(self, type): return len([i for i in self.flat() if i.type == type]) - + def purge(self, types, max=0): remove = [] for entry in self.flat(): @@ -54,23 +54,23 @@ class TOC(list): continue entry.parent.remove(entry) return remove - + def remove(self, entry): list.remove(self, entry) entry.parent = None - + def add_item(self, href, fragment, text, play_order=None, type='unknown'): if play_order is None: play_order = (self[-1].play_order if len(self) else self.play_order) + 1 self.append(TOC(href=href, fragment=fragment, text=text, parent=self, base_path=self.base_path, play_order=play_order, type=type)) return self[-1] - + def top_level_items(self): for item in self: if item.text is not None: yield item - + def depth(self): depth = 1 for obj in self: @@ -78,14 +78,14 @@ class TOC(list): if c > depth - 1: depth = c + 1 return depth - + def flat(self): 'Depth first iteration over the tree rooted at self' yield self for obj in self: for i in obj.flat(): yield i - + @dynamic_property def abspath(self): doc='Return the file this toc entry points to as a absolute path to a file on the system.' @@ -96,9 +96,9 @@ class TOC(list): if not os.path.isabs(path): path = os.path.join(self.base_path, path) return path - - return property(fget=fget, doc=doc) - + + return property(fget=fget, doc=doc) + def read_from_opf(self, opfreader): toc = opfreader.soup.find('spine', toc=True) if toc is not None: @@ -111,7 +111,7 @@ class TOC(list): if 'toc' in item.href().lower(): toc = item.href() break - + if toc is not None: if toc.lower() not in ('ncx', 'ncxtoc'): toc = urlparse(unquote(toc))[2] @@ -123,7 +123,7 @@ class TOC(list): bn = os.path.basename(toc) bn = bn.replace('_top.htm', '_toc.htm') # Bug in BAEN OPF files toc = os.path.join(os.path.dirname(toc), bn) - + self.read_html_toc(toc) except: print 'WARNING: Could not read Table of Contents. Continuing anyway.' @@ -141,43 +141,43 @@ class TOC(list): if m: toc = m[0] self.read_ncx_toc(toc) - + def read_ncx_toc(self, toc): self.base_path = os.path.dirname(toc) soup = NCXSoup(xml_to_unicode(open(toc, 'rb').read())[0]) - + def process_navpoint(np, dest): play_order = np.get('playOrder', None) if play_order is None: play_order = int(np.get('playorder', 1)) href = fragment = text = None - nl = np.find('navlabel') + nl = np.find(re.compile('navlabel')) if nl is not None: text = u'' - for txt in nl.findAll('text'): + for txt in nl.findAll(re.compile('text')): text += ''.join([unicode(s) for s in txt.findAll(text=True)]) - content = np.find('content') + content = np.find(re.compile('content')) if content is None or not content.has_key('src') or not txt: return - + purl = urlparse(unquote(content['src'])) href, fragment = purl[2], purl[5] nd = dest.add_item(href, fragment, text) nd.play_order = play_order - + for c in np: - if getattr(c, 'name', None) == 'navpoint': + if 'navpoint' in getattr(c, 'name', ''): process_navpoint(c, nd) - - nm = soup.find('navmap') + + nm = soup.find(re.compile('navmap')) if nm is None: raise ValueError('NCX files must have a element.') - + for elem in nm: - if getattr(elem, 'name', None) == 'navpoint': + if 'navpoint' in getattr(elem, 'name', ''): process_navpoint(elem, self) - - + + def read_html_toc(self, toc): self.base_path = os.path.dirname(toc) soup = BeautifulSoup(open(toc, 'rb').read(), convertEntities=BeautifulSoup.HTML_ENTITIES) @@ -191,13 +191,13 @@ class TOC(list): else: fragment = fragment.strip() href = href.strip() - + txt = ''.join([unicode(s).strip() for s in a.findAll(text=True)]) add = True for i in self.flat(): if i.href == href and i.fragment == fragment: add = False - break + break if add: self.add_item(href, fragment, txt) @@ -208,4 +208,4 @@ class TOC(list): template = MarkupTemplate(ncx_template) raw = template.generate(uid=uid, toc=self, __appname__=__appname__) raw = raw.render(doctype=doctype) - stream.write(raw) \ No newline at end of file + stream.write(raw) diff --git a/src/calibre/gui2/dialogs/config.py b/src/calibre/gui2/dialogs/config.py index 91bc988a22..a2c77187b5 100644 --- a/src/calibre/gui2/dialogs/config.py +++ b/src/calibre/gui2/dialogs/config.py @@ -263,7 +263,7 @@ class EmailAccounts(QAbstractTableModel): def remove(self, index): if index.isValid(): - row = self.index.row() + row = index.row() account = self.account_order[row] self.accounts.pop(account) self.account_order = sorted(self.accounts.keys()) @@ -425,6 +425,8 @@ class ConfigDialog(QDialog, Ui_Dialog): self.email_view.resizeColumnsToContents() self.connect(self.test_email_button, SIGNAL('clicked(bool)'), self.test_email) + self.connect(self.email_remove, SIGNAL('clicked()'), + self.remove_email_account) def add_email_account(self, checked): index = self._email_accounts.add() @@ -432,6 +434,10 @@ class ConfigDialog(QDialog, Ui_Dialog): self.email_view.resizeColumnsToContents() self.email_view.edit(index) + def remove_email_account(self, *args): + idx = self.email_view.currentIndex() + self._email_accounts.remove(idx) + def create_gmail_relay(self, *args): self.relay_username.setText('@gmail.com') self.relay_password.setText('') diff --git a/src/calibre/gui2/dialogs/lrf_single.ui b/src/calibre/gui2/dialogs/lrf_single.ui index 271f8e7059..87c7382770 100644 --- a/src/calibre/gui2/dialogs/lrf_single.ui +++ b/src/calibre/gui2/dialogs/lrf_single.ui @@ -727,7 +727,7 @@ px - 200 + 250 20 @@ -750,7 +750,7 @@ px - 200 + 250 20 @@ -773,7 +773,7 @@ px - 200 + 250 10 @@ -796,7 +796,7 @@ px - 200 + 250 0 diff --git a/src/calibre/gui2/images/news/laprensa_ni.png b/src/calibre/gui2/images/news/laprensa_ni.png new file mode 100644 index 0000000000..226edd4308 Binary files /dev/null and b/src/calibre/gui2/images/news/laprensa_ni.png differ diff --git a/src/calibre/gui2/lrf_renderer/document.py b/src/calibre/gui2/lrf_renderer/document.py index 76c94d23f1..d9874513d6 100644 --- a/src/calibre/gui2/lrf_renderer/document.py +++ b/src/calibre/gui2/lrf_renderer/document.py @@ -6,7 +6,7 @@ from PyQt4.QtCore import Qt, QByteArray, SIGNAL from PyQt4.QtGui import QGraphicsRectItem, QGraphicsScene, QPen, \ QBrush, QColor, QFontDatabase, \ QGraphicsItem, QGraphicsLineItem - + from calibre.gui2.lrf_renderer.text import TextBlock, FontLoader, COLOR, PixmapItem @@ -25,17 +25,17 @@ class Pen(QPen): class ContentObject(object): - + has_content = True - + def reset(self): self.has_content = True class RuledLine(QGraphicsLineItem, ContentObject): - + map = {'solid': Qt.SolidLine, 'dashed': Qt.DashLine, 'dotted': Qt.DotLine, 'double': Qt.DashDotLine} - + def __init__(self, rl): QGraphicsLineItem.__init__(self, 0, 0, rl.linelength, 0) ContentObject.__init__(self) @@ -43,7 +43,7 @@ class RuledLine(QGraphicsLineItem, ContentObject): class ImageBlock(PixmapItem, ContentObject): - + def __init__(self, obj): ContentObject.__init__(self) x0, y0, x1, y1 = obj.attrs['x0'], obj.attrs['y0'], obj.attrs['x1'], obj.attrs['y1'] @@ -51,26 +51,26 @@ class ImageBlock(PixmapItem, ContentObject): data, encoding = refstream.stream, refstream.encoding PixmapItem.__init__(self, data, encoding, x0, y0, x1, y1, xsize, ysize) self.block_id = obj.id - + def object_factory(container, obj, respect_max_y=False): if hasattr(obj, 'name'): if obj.name.endswith('TextBlock'): - + return TextBlock(obj, container.font_loader, respect_max_y, container.text_width, - container.logger, container.opts, container.ruby_tags, + container.logger, container.opts, container.ruby_tags, container.link_activated) elif obj.name.endswith('ImageBlock'): return ImageBlock(obj) elif isinstance(obj, _RuledLine): return RuledLine(obj) elif isinstance(obj, __Canvas): - return Canvas(container.font_loader, obj, container.logger, container.opts, - container.ruby_tags, container.link_activated) - return None + return Canvas(container.font_loader, obj, container.logger, container.opts, + container.ruby_tags, container.link_activated) + return None class _Canvas(QGraphicsRectItem): - + def __init__(self, font_loader, logger, opts, width=0, height=0, parent=None, x=0, y=0): QGraphicsRectItem.__init__(self, x, y, width, height, parent) self.font_loader, self.logger, self.opts = font_loader, logger, opts @@ -79,7 +79,7 @@ class _Canvas(QGraphicsRectItem): pen = QPen() pen.setStyle(Qt.NoPen) self.setPen(pen) - + def layout_block(self, block, x, y): if isinstance(block, TextBlock): self.layout_text_block(block, x, y) @@ -89,17 +89,17 @@ class _Canvas(QGraphicsRectItem): self.layout_image_block(block, x, y) elif isinstance(block, Canvas): self.layout_canvas(block, x, y) - + def layout_canvas(self, canvas, x, y): if canvas.max_y + y > self.max_y and y > 0: self.is_full = True - return + return canvas.setParentItem(self) canvas.setPos(x, y) canvas.has_content = False canvas.put_objects() self.current_y += canvas.max_y - + def layout_text_block(self, block, x, y): textwidth = block.bs.blockwidth - block.bs.sidemargin if block.max_y == 0 or not block.lines: # Empty block skipping @@ -128,15 +128,15 @@ class _Canvas(QGraphicsRectItem): line = block.peek() self.current_y = y self.is_full = not block_consumed - + def layout_ruled_line(self, rl, x, y): br = rl.boundingRect() rl.setParentItem(self) rl.setPos(x, y+1) self.current_y = y + br.height() + 1 self.is_full = y > self.max_y-5 - rl.has_content = False - + rl.has_content = False + def layout_image_block(self, ib, x, y): mw, mh = self.max_x - x, self.max_y - y if self.current_y + ib.height > self.max_y-y and self.current_y > 5: @@ -161,8 +161,8 @@ class _Canvas(QGraphicsRectItem): print print ib.block_id, ib.has_content, self.is_full print self.current_y, self.max_y, y, br.height() - print - + print + def search(self, phrase): matches = [] for child in self.children(): @@ -174,11 +174,11 @@ class _Canvas(QGraphicsRectItem): else: matches.append(res) return matches - - - + + + class Canvas(_Canvas, ContentObject): - + def __init__(self, font_loader, canvas, logger, opts, ruby_tags, link_activated, width=0, height=0): if hasattr(canvas, 'canvaswidth'): width, height = canvas.canvaswidth, canvas.canvasheight @@ -198,11 +198,11 @@ class Canvas(_Canvas, ContentObject): item = object_factory(self, obj, respect_max_y=True) if item: self.items.append((item, po.x1, po.y1)) - + def put_objects(self): for block, x, y in self.items: self.layout_block(block, x, y) - + def layout_block(self, block, x, y): block.reset() _Canvas.layout_block(self, block, x, y) @@ -212,17 +212,17 @@ class Header(Canvas): Canvas.__init__(self, font_loader, header, logger, opts, ruby_tags, link_activated, page_style.textwidth, page_style.headheight) if opts.visual_debug: - self.setPen(QPen(Qt.blue, 1, Qt.DashLine)) + self.setPen(QPen(Qt.blue, 1, Qt.DashLine)) class Footer(Canvas): def __init__(self, font_loader, footer, page_style, logger, opts, ruby_tags, link_activated): Canvas.__init__(self, font_loader, footer, logger, opts, ruby_tags, link_activated, page_style.textwidth, page_style.footheight) if opts.visual_debug: - self.setPen(QPen(Qt.blue, 1, Qt.DashLine)) + self.setPen(QPen(Qt.blue, 1, Qt.DashLine)) class Screen(_Canvas): - + def __init__(self, font_loader, chapter, odd, logger, opts, ruby_tags, link_activated): self.logger, self.opts = logger, opts page_style = chapter.style @@ -231,11 +231,11 @@ class Screen(_Canvas): self.content_x = 0 + sidemargin self.text_width = page_style.textwidth self.header_y = page_style.topmargin - + self.text_y = self.header_y + page_style.headheight + page_style.headsep self.text_height = page_style.textheight self.footer_y = self.text_y + self.text_height + (page_style.footspace - page_style.footheight) - + _Canvas.__init__(self, font_loader, logger, opts, width=width, height=self.footer_y+page_style.footheight) if opts.visual_debug: self.setPen(QPen(Qt.red, 1, Qt.SolidLine)) @@ -256,57 +256,57 @@ class Screen(_Canvas): if footer: footer = Footer(font_loader, footer, page_style, logger, opts, ruby_tags, link_activated) self.layout_canvas(footer, self.content_x, self.header_y) - + self.page = None - + def set_page(self, page): if self.page is not None and self.page.scene(): - self.scene().removeItem(self.page) + self.scene().removeItem(self.page) self.page = page self.page.setPos(self.content_x, self.text_y) self.scene().addItem(self.page) - + def remove(self): if self.scene(): if self.page is not None and self.page.scene(): self.scene().removeItem(self.page) self.scene().removeItem(self) - - + + class Page(_Canvas): - + def __init__(self, font_loader, logger, opts, width, height): _Canvas.__init__(self, font_loader, logger, opts, width, height) if opts.visual_debug: self.setPen(QPen(Qt.cyan, 1, Qt.DashLine)) - + def id(self): for child in self.children(): if hasattr(child, 'block_id'): return child.block_id - + def add_block(self, block): self.layout_block(block, 0, self.current_y) - - - + + + class Chapter(object): - + num_of_pages = property(fget=lambda self: len(self.pages)) - + def __init__(self, oddscreen, evenscreen, pages, object_to_page_map): self.oddscreen, self.evenscreen, self.pages, self.object_to_page_map = \ oddscreen, evenscreen, pages, object_to_page_map - + def page_of_object(self, id): return self.object_to_page_map[id] - + def page(self, num): return self.pages[num-1] - + def screen(self, odd): return self.oddscreen if odd else self.evenscreen - + def search(self, phrase): pages = [] for i in range(len(self.pages)): @@ -314,36 +314,36 @@ class Chapter(object): if matches: pages.append([i, matches]) return pages - + class History(collections.deque): - + def __init__(self): collections.deque.__init__(self) self.pos = 0 - + def back(self): if self.pos - 1 < 0: return None self.pos -= 1 return self[self.pos] - + def forward(self): if self.pos + 1 >= len(self): return None self.pos += 1 return self[self.pos] - + def add(self, item): while len(self) > self.pos+1: self.pop() self.append(item) self.pos += 1 - - + + class Document(QGraphicsScene): - + num_of_pages = property(fget=lambda self: sum(self.chapter_layout)) - + def __init__(self, logger, opts): QGraphicsScene.__init__(self) self.logger, self.opts = logger, opts @@ -358,23 +358,23 @@ class Document(QGraphicsScene): self.last_search = iter([]) if not opts.white_background: self.setBackgroundBrush(QBrush(QColor(0xee, 0xee, 0xee))) - + def page_of(self, oid): for chapter in self.chapters: if oid in chapter.object_to_page_map: return chapter.object_to_page_map[oid] - + def get_page_num(self, chapterid, objid): cnum = self.chapter_map[chapterid] page = self.chapters[cnum].object_to_page_map[objid] return sum(self.chapter_layout[:cnum])+page - + def add_to_history(self): page = self.chapter_page(self.current_page)[1] page_id = page.id() if page_id is not None: self.history.add(page_id) - + def link_activated(self, objid, on_creation=None): if on_creation is None: cid, oid = self.link_map[objid] @@ -385,30 +385,30 @@ class Document(QGraphicsScene): else: jb = self.objects[objid] self.link_map[objid] = (jb.refpage, jb.refobj) - - + + def back(self): oid = self.history.back() if oid is not None: page = self.page_of(oid) self.show_page(page) - + def forward(self): oid = self.history.forward() if oid is not None: page = self.page_of(oid) self.show_page(page) - - + + def load_fonts(self, lrf, load_substitutions=True): font_map = {} - + for font in lrf.font_map: fdata = QByteArray(lrf.font_map[font].data) id = QFontDatabase.addApplicationFontFromData(fdata) if id != -1: font_map[font] = [str(i) for i in QFontDatabase.applicationFontFamilies(id)][0] - + if load_substitutions: from calibre.ebooks.lrf.fonts.liberation import LiberationMono_BoldItalic QFontDatabase.addApplicationFontFromData(QByteArray(LiberationMono_BoldItalic.font_data)) @@ -434,10 +434,10 @@ class Document(QGraphicsScene): QFontDatabase.addApplicationFontFromData(QByteArray(LiberationSerif_BoldItalic.font_data)) from calibre.ebooks.lrf.fonts.liberation import LiberationSans_Regular QFontDatabase.addApplicationFontFromData(QByteArray(LiberationSans_Regular.font_data)) - + self.font_loader = FontLoader(font_map, self.dpi) - - + + def render_chapter(self, chapter, lrf): oddscreen, evenscreen = Screen(self.font_loader, chapter, True, self.logger, self.opts, self.ruby_tags, self.link_activated), \ Screen(self.font_loader, chapter, False, self.logger, self.opts, self.ruby_tags, self.link_activated) @@ -459,36 +459,36 @@ class Document(QGraphicsScene): if current_page: pages.append(current_page) self.chapters.append(Chapter(oddscreen, evenscreen, pages, object_to_page_map)) - self.chapter_map[chapter.id] = len(self.chapters)-1 - - + self.chapter_map[chapter.id] = len(self.chapters)-1 + + def render(self, lrf, load_substitutions=True): self.dpi = lrf.device_info.dpi/10. self.ruby_tags = dict(**lrf.ruby_tags) self.load_fonts(lrf, load_substitutions) self.objects = lrf.objects - + num_chaps = 0 for pt in lrf.page_trees: for chapter in pt: num_chaps += 1 self.emit(SIGNAL('chapter_rendered(int)'), num_chaps) - + for pt in lrf.page_trees: for chapter in pt: self.render_chapter(chapter, lrf) - + self.emit(SIGNAL('chapter_rendered(int)'), -1) self.chapter_layout = [i.num_of_pages for i in self.chapters] self.objects = None - + def chapter_page(self, num): for chapter in self.chapters: if num <= chapter.num_of_pages: break num -= chapter.num_of_pages return chapter, chapter.page(num) - + def show_page(self, num): if num < 1 or num > self.num_of_pages or num == self.current_page: return @@ -496,33 +496,33 @@ class Document(QGraphicsScene): self.current_page = num chapter, page = self.chapter_page(num) screen = chapter.screen(odd) - + if self.current_screen is not None and self.current_screen is not screen: self.current_screen.remove() self.current_screen = screen if self.current_screen.scene() is None: self.addItem(self.current_screen) - + self.current_screen.set_page(page) self.emit(SIGNAL('page_changed(PyQt_PyObject)'), self.current_page) - - + + def next(self): self.next_by(1) - + def previous(self): self.previous_by(1) - + def next_by(self, num): self.show_page(self.current_page + num) - + def previous_by(self, num): self.show_page(self.current_page - num) - + def show_page_at_percent(self, p): num = self.num_of_pages*(p/100.) self.show_page(num) - + def search(self, phrase): if not phrase: return @@ -534,7 +534,7 @@ class Document(QGraphicsScene): matches += cmatches self.last_search = itertools.cycle(matches) self.next_match() - + def next_match(self): page_num = self.last_search.next()[0] if self.current_page == page_num: @@ -542,4 +542,4 @@ class Document(QGraphicsScene): else: self.add_to_history() self.show_page(page_num) - + diff --git a/src/calibre/gui2/viewer/documentview.py b/src/calibre/gui2/viewer/documentview.py index 161bc69aad..1b3b66ca92 100644 --- a/src/calibre/gui2/viewer/documentview.py +++ b/src/calibre/gui2/viewer/documentview.py @@ -52,29 +52,29 @@ def config(defaults=None): c = Config('viewer', desc) else: c = StringConfig(defaults, desc) - + c.add_opt('user_css', default='', help=_('Set the user CSS stylesheet. This can be used to customize the look of all books.')) - + fonts = c.add_group('FONTS', _('Font options')) - fonts('serif_family', default='Times New Roman' if iswindows else 'Liberation Serif', + fonts('serif_family', default='Times New Roman' if iswindows else 'Liberation Serif', help=_('The serif font family')) - fonts('sans_family', default='Verdana' if iswindows else 'Liberation Sans', + fonts('sans_family', default='Verdana' if iswindows else 'Liberation Sans', help=_('The sans-serif font family')) - fonts('mono_family', default='Courier New' if iswindows else 'Liberation Mono', + fonts('mono_family', default='Courier New' if iswindows else 'Liberation Mono', help=_('The monospaced font family')) fonts('default_font_size', default=20, help=_('The standard font size in px')) fonts('mono_font_size', default=16, help=_('The monospaced font size in px')) fonts('standard_font', default='serif', help=_('The standard font type')) - + return c class ConfigDialog(QDialog, Ui_Dialog): - + def __init__(self, *args): QDialog.__init__(self, *args) self.setupUi(self) - + opts = config().parse() self.serif_family.setCurrentFont(QFont(opts.serif_family)) self.sans_family.setCurrentFont(QFont(opts.sans_family)) @@ -84,7 +84,7 @@ class ConfigDialog(QDialog, Ui_Dialog): self.standard_font.setCurrentIndex({'serif':0, 'sans':1, 'mono':2}[opts.standard_font]) self.css.setPlainText(opts.user_css) self.css.setToolTip(_('Set the user CSS stylesheet. This can be used to customize the look of all books.')) - + def accept(self, *args): c = config() c.set('serif_family', unicode(self.serif_family.currentFont().family())) @@ -95,10 +95,10 @@ class ConfigDialog(QDialog, Ui_Dialog): c.set('standard_font', {0:'serif', 1:'sans', 2:'mono'}[self.standard_font.currentIndex()]) c.set('user_css', unicode(self.css.toPlainText())) return QDialog.accept(self, *args) - + class Document(QWebPage): - + def set_font_settings(self): opts = config().parse() settings = self.settings() @@ -110,14 +110,14 @@ class Document(QWebPage): settings.setFontFamily(QWebSettings.SerifFont, opts.serif_family) settings.setFontFamily(QWebSettings.SansSerifFont, opts.sans_family) settings.setFontFamily(QWebSettings.FixedFont, opts.mono_family) - + def do_config(self, parent=None): d = ConfigDialog(parent) if d.exec_() == QDialog.Accepted: self.set_font_settings() self.set_user_stylesheet() self.triggerAction(QWebPage.Reload) - + def __init__(self, *args): QWebPage.__init__(self, *args) self.setLinkDelegationPolicy(self.DelegateAllLinks) @@ -125,53 +125,53 @@ class Document(QWebPage): pal = self.palette() pal.setBrush(QPalette.Background, QColor(0xee, 0xee, 0xee)) self.setPalette(pal) - + settings = self.settings() - + # Fonts load_builtin_fonts() self.set_font_settings() - + # Security settings.setAttribute(QWebSettings.JavaEnabled, False) settings.setAttribute(QWebSettings.PluginsEnabled, False) settings.setAttribute(QWebSettings.JavascriptCanOpenWindows, False) settings.setAttribute(QWebSettings.JavascriptCanAccessClipboard, False) - + # Miscellaneous settings.setAttribute(QWebSettings.LinksIncludedInFocusChain, True) self.set_user_stylesheet() - + # Load jQuery - self.connect(self.mainFrame(), SIGNAL('javaScriptWindowObjectCleared()'), + self.connect(self.mainFrame(), SIGNAL('javaScriptWindowObjectCleared()'), self.load_javascript_libraries) - + def set_user_stylesheet(self): raw = config().parse().user_css pt = PersistentTemporaryFile('_user_stylesheet.css') pt.write(raw.encode('utf-8')) pt.close() self.settings().setUserStyleSheetUrl(QUrl.fromLocalFile(pt.name)) - + def load_javascript_libraries(self): from calibre.resources import jquery, jquery_scrollTo self.javascript(jquery) self.javascript(jquery_scrollTo) self.javascript(bookmarks) self.javascript(referencing) - + def reference_mode(self, enable): self.javascript(('enter' if enable else 'leave')+'_reference_mode()') - + def set_reference_prefix(self, prefix): self.javascript('reference_prefix = "%s"'%prefix) - + def goto(self, ref): self.javascript('goto_reference("%s")'%ref) - + def goto_bookmark(self, bm): self.javascript('scroll_to_bookmark("%s")'%bm) - + def javascript(self, string, typ=None): ans = self.mainFrame().evaluateJavaScript(string) if typ == 'int': @@ -182,65 +182,65 @@ class Document(QWebPage): if typ == 'string': return unicode(ans.toString()) return ans - + def scroll_by(self, x=0, y=0): self.javascript('window.scrollBy(%d, %d)'%(x, y)) - + def scroll_to(self, x=0, y=0): self.javascript('window.scrollTo(%d, %d)'%(x, y)) - + def jump_to_anchor(self, anchor): self.javascript('document.location.hash = "%s"'%anchor) - + def quantize(self): if self.height > self.window_height: r = self.height%self.window_height if r > 0: self.javascript('document.body.style.paddingBottom = "%dpx"'%r) - + def bookmark(self): return self.javascript('calculate_bookmark(%d)'%(self.ypos+25), 'string') - + @dynamic_property def at_bottom(self): def fget(self): return self.height - self.ypos <= self.window_height return property(fget=fget) - + @dynamic_property def at_top(self): def fget(self): return self.ypos <= 0 return property(fget=fget) - - + + def test(self): pass - + @dynamic_property def ypos(self): def fget(self): return self.javascript('window.pageYOffset', 'int') return property(fget=fget) - + @dynamic_property def window_height(self): def fget(self): return self.javascript('window.innerHeight', 'int') return property(fget=fget) - + @dynamic_property def window_width(self): def fget(self): return self.javascript('window.innerWidth', 'int') return property(fget=fget) - + @dynamic_property def xpos(self): def fget(self): return self.javascript('window.pageXOffset', 'int') return property(fget=fget) - + @dynamic_property def scroll_fraction(self): def fget(self): @@ -249,19 +249,19 @@ class Document(QWebPage): except ZeroDivisionError: return 0. return property(fget=fget) - + @dynamic_property def hscroll_fraction(self): def fget(self): return float(self.xpos)/self.width return property(fget=fget) - + @dynamic_property def height(self): def fget(self): return self.javascript('document.body.offsetHeight', 'int') # contentsSize gives inaccurate results return property(fget=fget) - + @dynamic_property def width(self): def fget(self): @@ -269,7 +269,7 @@ class Document(QWebPage): return property(fget=fget) class EntityDeclarationProcessor(object): - + def __init__(self, html): self.declared_entities = {} for match in re.finditer(r']+)>', html): @@ -281,9 +281,9 @@ class EntityDeclarationProcessor(object): self.processed_html = self.processed_html.replace('&%s;'%key, val) class DocumentView(QWebView): - - DISABLED_BRUSH = QBrush(Qt.lightGray, Qt.Dense5Pattern) - + + DISABLED_BRUSH = QBrush(Qt.lightGray, Qt.Dense5Pattern) + def __init__(self, *args): QWidget.__init__(self, *args) self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)) @@ -299,83 +299,83 @@ class DocumentView(QWebView): self.connect(self.document, SIGNAL('linkClicked(QUrl)'), self.link_clicked) self.connect(self.document, SIGNAL('linkHovered(QString,QString,QString)'), self.link_hovered) self.connect(self.document, SIGNAL('selectionChanged()'), self.selection_changed) - + def reference_mode(self, enable): self._reference_mode = enable self.document.reference_mode(enable) - + def goto(self, ref): self.document.goto(ref) - + def goto_bookmark(self, bm): self.document.goto_bookmark(bm) - + def config(self, parent=None): self.document.do_config(parent) - + def bookmark(self): return self.document.bookmark() - + def selection_changed(self): if self.manager is not None: self.manager.selection_changed(unicode(self.document.selectedText())) - + def set_manager(self, manager): self.manager = manager self.scrollbar = manager.horizontal_scrollbar self.connect(self.scrollbar, SIGNAL('valueChanged(int)'), self.scroll_horizontally) - + def scroll_horizontally(self, amount): self.document.scroll_to(y=self.document.ypos, x=amount) - + def link_hovered(self, link, text, context): link, text = unicode(link), unicode(text) if link: self.setCursor(Qt.PointingHandCursor) else: - self.unsetCursor() - + self.unsetCursor() + def link_clicked(self, url): if self.manager is not None: self.manager.link_clicked(url) - + def sizeHint(self): return self._size_hint - + @dynamic_property def scroll_fraction(self): def fget(self): return self.document.scroll_fraction return property(fget=fget) - + @dynamic_property def hscroll_fraction(self): def fget(self): return self.document.hscroll_fraction return property(fget=fget) - + @dynamic_property def content_size(self): def fget(self): return self.document.width, self.document.height return property(fget=fget) - + def search(self, text): return self.findText(text) - + def path(self): return os.path.abspath(unicode(self.url().toLocalFile())) - + def load_path(self, path, pos=0.0): self.initial_pos = pos - html = open(path, 'rb').read().decode(path.encoding) + html = open(path, 'rb').read().decode(path.encoding, 'replace') html = EntityDeclarationProcessor(html).processed_html self.setHtml(html, QUrl.fromLocalFile(path)) - + def load_started(self): if self.manager is not None: self.manager.load_started() - + def initialize_scrollbar(self): if getattr(self, 'scrollbar', None) is not None: delta = self.document.width - self.size().width() @@ -387,7 +387,7 @@ class DocumentView(QWebView): self.scrollbar.setPageStep(int(delta/10.)) self.scrollbar.blockSignals(False) self.scrollbar.setVisible(delta > 0) - + def load_finished(self, ok): self.document.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff) self.document.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff) @@ -409,8 +409,8 @@ class DocumentView(QWebView): self.document.set_reference_prefix('%d.'%(spine_index+1)) if scrolled: self.manager.scrolled(self.document.scroll_fraction) - - + + @classmethod def test_line(cls, img, y): start = img.pixel(0, y) @@ -418,7 +418,7 @@ class DocumentView(QWebView): if img.pixel(i, y) != start: return False return True - + def find_next_blank_line(self, overlap): img = QImage(self.width(), overlap, QImage.Format_ARGB32) painter = QPainter(img) @@ -428,8 +428,8 @@ class DocumentView(QWebView): if self.test_line(img, i): self.scroll_by(y=i, notify=False) return - self.scroll_by(y=overlap) - + self.scroll_by(y=overlap) + def previous_page(self): if self.document.at_top: if self.manager is not None: @@ -448,12 +448,12 @@ class DocumentView(QWebView): break if self.manager is not None: self.manager.scrolled(self.scroll_fraction) - + def wheel_event(self, down=True): - QWebView.wheelEvent(self, - QWheelEvent(QPoint(100, 100), (-120 if down else 120), + QWebView.wheelEvent(self, + QWheelEvent(QPoint(100, 100), (-120 if down else 120), Qt.NoButton, Qt.NoModifier)) - + def next_page(self): if self.document.at_bottom: if self.manager is not None: @@ -472,14 +472,14 @@ class DocumentView(QWebView): self.find_next_blank_line( self.height() - (self.document.ypos-opos) ) if self.manager is not None: self.manager.scrolled(self.scroll_fraction) - - + + def scroll_by(self, x=0, y=0, notify=True): old_pos = self.document.ypos self.document.scroll_by(x, y) if notify and self.manager is not None and self.document.ypos != old_pos: self.manager.scrolled(self.scroll_fraction) - + def scroll_to(self, pos, notify=True): old_pos = self.document.ypos if isinstance(pos, basestring): @@ -492,30 +492,30 @@ class DocumentView(QWebView): pos*(self.document.height-self.document.window_height)))) if notify and self.manager is not None and self.document.ypos != old_pos: self.manager.scrolled(self.scroll_fraction) - + def multiplier(self): return self.document.mainFrame().textSizeMultiplier() - + def magnify_fonts(self): self.document.mainFrame().setTextSizeMultiplier(self.multiplier()+0.2) return self.document.scroll_fraction - + def shrink_fonts(self): self.document.mainFrame().setTextSizeMultiplier(max(self.multiplier()-0.2, 0)) return self.document.scroll_fraction - + def changeEvent(self, event): if event.type() == event.EnabledChange: self.update() return QWebView.changeEvent(self, event) - + def paintEvent(self, event): painter = QPainter(self) self.document.mainFrame().render(painter, event.region()) if not self.isEnabled(): painter.fillRect(event.region().boundingRect(), self.DISABLED_BRUSH) painter.end() - + def wheelEvent(self, event): if event.delta() < -14: if self.document.at_bottom: @@ -533,7 +533,7 @@ class DocumentView(QWebView): if self.manager is not None: self.manager.scrolled(self.scroll_fraction) return ret - + def keyPressEvent(self, event): key = event.key() if key in [Qt.Key_PageDown, Qt.Key_Space, Qt.Key_Down]: @@ -562,14 +562,14 @@ class DocumentView(QWebView): self.scroll_by(x=15) else: return QWebView.keyPressEvent(self, event) - + def resizeEvent(self, event): ret = QWebView.resizeEvent(self, event) QTimer.singleShot(10, self.initialize_scrollbar) if self.manager is not None: self.manager.viewport_resized(self.scroll_fraction) return ret - + def mouseReleaseEvent(self, ev): opos = self.document.ypos ret = QWebView.mouseReleaseEvent(self, ev) @@ -578,4 +578,4 @@ class DocumentView(QWebView): self.manager.scrolled(self.scroll_fraction) return ret - \ No newline at end of file + diff --git a/src/calibre/gui2/viewer/js.py b/src/calibre/gui2/viewer/js.py index af5a2f5e80..063731acea 100644 --- a/src/calibre/gui2/viewer/js.py +++ b/src/calibre/gui2/viewer/js.py @@ -18,7 +18,7 @@ function find_enclosing_block(y) { if (min != 0 && min.height() < 200) break; } if (y <= 0) return document.body; - if (min == 0) { return find_enclosing_block(x, y-20); } + if (min == 0) { return find_enclosing_block(y-20); } return min; } @@ -93,7 +93,7 @@ function enter_reference_mode() { } function leave_reference_mode() { - $("p").unbind("mouseenter mouseleave", toggle_reference); + $("p").unbind("mouseenter mouseleave", toggle_reference); } function goto_reference(ref) { @@ -118,4 +118,4 @@ $(document.body).click(function(e) { $(document).ready(enter_reference_mode); -''' \ No newline at end of file +''' diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py index 9fc934b6a1..543d92904b 100644 --- a/src/calibre/gui2/viewer/main.py +++ b/src/calibre/gui2/viewer/main.py @@ -27,7 +27,7 @@ from calibre.gui2.library import SearchBox from calibre.ebooks.metadata import MetaInformation class TOCItem(QStandardItem): - + def __init__(self, toc): QStandardItem.__init__(self, toc.text if toc.text else '') self.abspath = toc.abspath @@ -35,23 +35,23 @@ class TOCItem(QStandardItem): for t in toc: self.appendRow(TOCItem(t)) self.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable) - + @classmethod def type(cls): return QStandardItem.UserType+10 class TOC(QStandardItemModel): - + def __init__(self, toc): QStandardItemModel.__init__(self) for t in toc: self.appendRow(TOCItem(t)) self.setHorizontalHeaderItem(0, QStandardItem(_('Table of Contents'))) - - + + class Worker(Thread): - + def run(self): try: Thread.run(self) @@ -61,7 +61,7 @@ class Worker(Thread): self.traceback = traceback.format_exc() class ProgressIndicator(QWidget): - + def __init__(self, *args): QWidget.__init__(self, *args) self.setGeometry(0, 0, 300, 500) @@ -76,7 +76,7 @@ class ProgressIndicator(QWidget): self.status.font().setBold(True) self.status.font().setPointSize(self.font().pointSize()+6) self.setVisible(False) - + def start(self, msg=''): view = self.parent() pwidth, pheight = view.size().width(), view.size().height() @@ -89,25 +89,25 @@ class ProgressIndicator(QWidget): self.status.setText(msg) self.setVisible(True) self.movie.setPaused(False) - + def stop(self): if self.movie.state() == self.movie.Running: self.movie.setPaused(True) self.setVisible(False) class History(collections.deque): - + def __init__(self, action_back, action_forward): self.action_back = action_back self.action_forward = action_forward collections.deque.__init__(self) self.pos = 0 self.set_actions() - + def set_actions(self): self.action_back.setDisabled(self.pos < 1) self.action_forward.setDisabled(self.pos + 1 >= len(self)) - + def back(self, from_pos): if self.pos - 1 < 0: return None if self.pos == len(self): @@ -116,56 +116,56 @@ class History(collections.deque): self.pos -= 1 self.set_actions() return self[self.pos] - + def forward(self): if self.pos + 1 >= len(self): return None self.pos += 1 self.set_actions() return self[self.pos] - + def add(self, item): while len(self) > self.pos+1: self.pop() self.append(item) self.pos += 1 self.set_actions() - + class Metadata(QLabel): - + def __init__(self, parent): QTextBrowser.__init__(self, parent.centralWidget()) self.view = parent.splitter self.setGeometry(self.view.geometry()) self.setWordWrap(True) self.setVisible(False) - + def show_opf(self, opf): mi = MetaInformation(opf) html = '

%s

%s'%(_('Metadata'), u''.join(mi.to_html())) self.setText(html) - + def setVisible(self, x): self.setGeometry(self.view.geometry()) QLabel.setVisible(self, x) - + def paintEvent(self, ev): p = QPainter(self) p.fillRect(ev.region().boundingRect(), QBrush(QColor(200, 200, 200, 220), Qt.SolidPattern)) p.end() QLabel.paintEvent(self, ev) - - + + class DoubleSpinBox(QDoubleSpinBox): - + def set_value(self, val): self.blockSignals(True) self.setValue(val) self.blockSignals(False) class HelpfulLineEdit(QLineEdit): - + HELP_TEXT = _('Go to...') - + def __init__(self, *args): QLineEdit.__init__(self, *args) self.default_palette = QApplication.palette(self) @@ -174,22 +174,22 @@ class HelpfulLineEdit(QLineEdit): self.connect(self, SIGNAL('editingFinished()'), lambda : self.emit(SIGNAL('goto(PyQt_PyObject)'), unicode(self.text()))) self.clear_to_help_mode() - + def focusInEvent(self, ev): self.setPalette(QApplication.palette(self)) if self.in_help_mode(): self.setText('') return QLineEdit.focusInEvent(self, ev) - + def in_help_mode(self): return unicode(self.text()) == self.HELP_TEXT - + def clear_to_help_mode(self): self.setPalette(self.gray) self.setText(self.HELP_TEXT) - + class EbookViewer(MainWindow, Ui_EbookViewer): - + def __init__(self, pathtoebook=None): MainWindow.__init__(self, None) self.setupUi(self) @@ -224,14 +224,14 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.action_quit = QAction(self) self.addAction(self.action_quit) self.action_quit.setShortcut(Qt.CTRL+Qt.Key_Q) - self.connect(self.action_quit, SIGNAL('triggered(bool)'), + self.connect(self.action_quit, SIGNAL('triggered(bool)'), lambda x:QApplication.instance().quit()) self.action_copy.setDisabled(True) self.action_metadata.setCheckable(True) self.action_metadata.setShortcut(Qt.CTRL+Qt.Key_I) self.action_table_of_contents.setCheckable(True) self.action_reference_mode.setCheckable(True) - self.connect(self.action_reference_mode, SIGNAL('triggered(bool)'), + self.connect(self.action_reference_mode, SIGNAL('triggered(bool)'), lambda x: self.view.reference_mode(x)) self.connect(self.action_metadata, SIGNAL('triggered(bool)'), lambda x:self.metadata.setVisible(x)) self.connect(self.action_table_of_contents, SIGNAL('triggered(bool)'), lambda x:self.toc.setVisible(x)) @@ -246,7 +246,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): lambda x:self.view.next_page()) self.connect(self.action_previous_page, SIGNAL('triggered(bool)'), lambda x:self.view.previous_page()) - self.connect(self.action_find_next, SIGNAL('triggered(bool)'), + self.connect(self.action_find_next, SIGNAL('triggered(bool)'), lambda x:self.find(unicode(self.search.text()), True, repeat=True)) self.connect(self.action_full_screen, SIGNAL('triggered(bool)'), self.toggle_fullscreen) @@ -256,17 +256,16 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.connect(self.action_forward, SIGNAL('triggered(bool)'), self.forward) self.connect(self.action_preferences, SIGNAL('triggered(bool)'), lambda x: self.view.config(self)) self.connect(self.pos, SIGNAL('valueChanged(double)'), self.goto_page) - self.connect(self.vertical_scrollbar, SIGNAL('valueChanged(int)'), + self.connect(self.vertical_scrollbar, SIGNAL('valueChanged(int)'), lambda x: self.goto_page(x/100.)) self.connect(self.search, SIGNAL('search(PyQt_PyObject, PyQt_PyObject)'), self.find) self.connect(self.toc, SIGNAL('clicked(QModelIndex)'), self.toc_clicked) self.connect(self.reference, SIGNAL('goto(PyQt_PyObject)'), self.goto) - - + self.bookmarks_menu = QMenu() self.action_bookmark.setMenu(self.bookmarks_menu) self.set_bookmarks([]) - + if pathtoebook is not None: f = functools.partial(self.load_ebook, pathtoebook) QTimer.singleShot(50, f) @@ -277,7 +276,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.tool_bar2.setContextMenuPolicy(Qt.PreventContextMenu) self.tool_bar.widgetForAction(self.action_bookmark).setPopupMode(QToolButton.MenuButtonPopup) self.action_full_screen.setCheckable(True) - + self.print_menu = QMenu() self.print_menu.addAction(QIcon(':/images/print-preview.svg'), _('Print Preview')) self.action_print.setMenu(self.print_menu) @@ -293,18 +292,18 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.showNormal() else: self.showFullScreen() - + def goto(self, ref): if ref: tokens = ref.split('.') if len(tokens) > 1: - spine_index = int(tokens[0]) -1 + spine_index = int(tokens[0]) -1 if spine_index == self.current_index: self.view.goto(ref) else: self.pending_reference = ref self.load_path(self.iterator.spine[spine_index]) - + def goto_bookmark(self, bm): m = bm[1].split('#') if len(m) > 1: @@ -314,39 +313,39 @@ class EbookViewer(MainWindow, Ui_EbookViewer): else: self.pending_bookmark = bm self.load_path(self.iterator.spine[spine_index]) - + def toc_clicked(self, index): item = self.toc_model.itemFromIndex(index) url = QUrl.fromLocalFile(item.abspath) if item.fragment: url.setFragment(item.fragment) self.link_clicked(url) - + def selection_changed(self, selected_text): self.selected_text = selected_text.strip() self.action_copy.setEnabled(bool(self.selected_text)) - + def copy(self, x): if self.selected_text: QApplication.clipboard().setText(self.selected_text) - + def back(self, x): pos = self.history.back(self.pos.value()) if pos is not None: self.goto_page(pos) - - + + def forward(self, x): pos = self.history.forward() if pos is not None: self.goto_page(pos) - + def goto_start(self): self.goto_page(1) - + def goto_end(self): self.goto_page(self.pos.maximum()) - + def goto_page(self, new_page): if self.current_page is not None: for page in self.iterator.spine: @@ -359,7 +358,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.view.scroll_to(frac) else: self.load_path(page, pos=frac) - + def open_ebook(self, checked): files = choose_files(self, 'ebook viewer open dialog', _('Choose ebook'), @@ -367,19 +366,19 @@ class EbookViewer(MainWindow, Ui_EbookViewer): select_only_single_file=True) if files: self.load_ebook(files[0]) - + def font_size_larger(self, checked): frac = self.view.magnify_fonts() self.action_font_size_larger.setEnabled(self.view.multiplier() < 3) self.action_font_size_smaller.setEnabled(self.view.multiplier() > 0.2) self.set_page_number(frac) - + def font_size_smaller(self, checked): frac = self.view.shrink_fonts() self.action_font_size_larger.setEnabled(self.view.multiplier() < 3) self.action_font_size_smaller.setEnabled(self.view.multiplier() > 0.2) self.set_page_number(frac) - + def bookmark(self, *args): title, ok = QInputDialog.getText(self, _('Add bookmark'), _('Enter title for bookmark:')) title = unicode(title).strip() @@ -388,8 +387,8 @@ class EbookViewer(MainWindow, Ui_EbookViewer): bookmark = '%d#%s'%(self.current_index, pos) self.iterator.add_bookmark((title, bookmark)) self.set_bookmarks(self.iterator.bookmarks) - - + + def find(self, text, refinement, repeat=False): if not text: return @@ -401,18 +400,18 @@ class EbookViewer(MainWindow, Ui_EbookViewer): if self.current_index > 0: index = self.iterator.search(text, 0) if index is None: - info_dialog(self, _('No matches found'), + info_dialog(self, _('No matches found'), _('No matches found for: %s')%text).exec_() return return self.pending_search = text self.load_path(self.iterator.spine[index]) - + def do_search(self, text): self.pending_search = None if self.view.search(text): self.scrolled(self.view.scroll_fraction) - + def keyPressEvent(self, event): if event.key() == Qt.Key_F3: text = unicode(self.search.text()) @@ -421,10 +420,10 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.search.setFocus(Qt.OtherFocusReason) else: return MainWindow.keyPressEvent(self, event) - + def internal_link_clicked(self, frac): self.history.add(self.pos.value()) - + def link_clicked(self, url): path = os.path.abspath(unicode(url.toLocalFile())) frag = None @@ -440,10 +439,10 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.view.scroll_to(frag) else: QDesktopServices.openUrl(url) - + def load_started(self): self.open_progress_indicator(_('Loading flow...')) - + def load_finished(self, ok): self.close_progress_indicator() path = self.view.path() @@ -467,11 +466,11 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.goto_bookmark(self.pending_bookmark) self.pending_bookmark = None return self.current_index - + def load_path(self, path, pos=0.0): self.open_progress_indicator(_('Laying out %s')%self.current_title) self.view.load_path(path, pos=pos) - + def viewport_resized(self, frac): new_page = self.pos.value() if self.current_page is not None: @@ -482,20 +481,20 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.view.scroll_to(frac, notify=False) else: self.set_page_number(frac) - + def close_progress_indicator(self): self.pi.stop() for o in ('tool_bar', 'tool_bar2', 'view', 'horizontal_scrollbar', 'vertical_scrollbar'): getattr(self, o).setEnabled(True) self.unsetCursor() self.view.setFocus(Qt.PopupFocusReason) - + def open_progress_indicator(self, msg=''): self.pi.start(msg) for o in ('tool_bar', 'tool_bar2', 'view', 'horizontal_scrollbar', 'vertical_scrollbar'): getattr(self, o).setEnabled(False) self.setCursor(Qt.BusyCursor) - + def set_bookmarks(self, bookmarks): self.bookmarks_menu.clear() self.bookmarks_menu.addAction(_("Manage Bookmarks"), self.manage_bookmarks) @@ -507,19 +506,19 @@ class EbookViewer(MainWindow, Ui_EbookViewer): else: self.bookmarks_menu.addAction(bm[0], partial(self.goto_bookmark, bm)) return current_page - + def manage_bookmarks(self): bmm = BookmarkManager(self, self.iterator.bookmarks) if bmm.exec_() != BookmarkManager.Accepted: return - + bookmarks = bmm.get_bookmarks() - + if bookmarks != self.iterator.bookmarks: self.iterator.set_bookmarks(bookmarks) self.iterator.save_bookmarks() self.set_bookmarks(bookmarks) - + def save_current_position(self): try: pos = self.view.bookmark() @@ -527,7 +526,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.iterator.add_bookmark(('calibre_current_page_bookmark', bookmark)) except: traceback.print_exc() - + def load_ebook(self, pathtoebook): if self.iterator is not None: self.save_current_position() @@ -543,7 +542,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): if isinstance(worker.exception, DRMError): error_dialog(self, _('DRM Error'), _('

This book is protected by DRM')%'http://wiki.mobileread.com/wiki/DRM').exec_() else: - ConversionErrorDialog(self, _('Could not open ebook'), + ConversionErrorDialog(self, _('Could not open ebook'), _('%s

%s

')%(worker.exception, worker.traceback.replace('\n', '
')), show=True) self.close_progress_indicator() else: @@ -571,37 +570,37 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.goto_bookmark(previous) else: self.next_document() - + def set_vscrollbar_value(self, pagenum): self.vertical_scrollbar.blockSignals(True) self.vertical_scrollbar.setValue(int(pagenum*100)) self.vertical_scrollbar.blockSignals(False) - + def set_page_number(self, frac): if getattr(self, 'current_page', None) is not None: page = self.current_page.start_page + frac*float(self.current_page.pages-1) self.pos.set_value(page) self.set_vscrollbar_value(page) - + def scrolled(self, frac): self.set_page_number(frac) - + def next_document(self): if self.current_index < len(self.iterator.spine) - 1: self.load_path(self.iterator.spine[self.current_index+1]) - + def previous_document(self): if self.current_index > 0: self.load_path(self.iterator.spine[self.current_index-1], pos=1.0) - + def __enter__(self): return self - + def __exit__(self, *args): if self.iterator is not None: self.save_current_position() self.iterator.__exit__(*args) - + def config(defaults=None): desc = _('Options to control the ebook viewer') @@ -609,8 +608,8 @@ def config(defaults=None): c = Config('viewer', desc) else: c = StringConfig(defaults, desc) - - c.add_opt('raise_window', ['--raise-window'], default=False, + + c.add_opt('raise_window', ['--raise-window'], default=False, help=_('If specified, viewer window will try to come to the ' 'front when started.')) return c @@ -620,7 +619,7 @@ def option_parser(): return c.option_parser(usage=_('''\ %prog [options] file -View an ebook. +View an ebook. ''')) @@ -639,7 +638,7 @@ def main(args=sys.argv): if opts.raise_window: main.raise_() with main: - return app.exec_() + return app.exec_() return 0 if __name__ == '__main__': diff --git a/src/calibre/web/feeds/recipes/__init__.py b/src/calibre/web/feeds/recipes/__init__.py index d407378ce5..33763f83ce 100644 --- a/src/calibre/web/feeds/recipes/__init__.py +++ b/src/calibre/web/feeds/recipes/__init__.py @@ -37,7 +37,7 @@ recipe_modules = ['recipe_' + r for r in ( 'new_york_review_of_books_no_sub', 'politico', 'adventuregamers', 'mondedurable', 'instapaper', 'dnevnik_cro', 'vecernji_list', 'nacional_cro', '24sata', 'dnevni_avaz', 'glas_srpske', '24sata_rs', - 'krstarica', 'krstarica_en', 'tanjug', + 'krstarica', 'krstarica_en', 'tanjug', 'laprensa_ni', )] import re, imp, inspect, time, os diff --git a/src/calibre/web/feeds/recipes/recipe_laprensa_ni.py b/src/calibre/web/feeds/recipes/recipe_laprensa_ni.py new file mode 100644 index 0000000000..7a137ff07e --- /dev/null +++ b/src/calibre/web/feeds/recipes/recipe_laprensa_ni.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python + +__license__ = 'GPL v3' +__copyright__ = '2009, Darko Miletic ' +''' +laprensa.com.ni +''' + +import locale +import time +from calibre.web.feeds.news import BasicNewsRecipe + +class LaPrensa_ni(BasicNewsRecipe): + title = 'La Prensa - Nicaragua' + __author__ = 'Darko Miletic' + description = 'LA PRENSA - EL Diario de los Nicaraguenses' + publisher = 'La Prensa' + category = 'Nicaragua, nicaragua, la prensa, La Prensa, prensa, Prensa, diario, Diario, periodico, noticias, internacional, economia, dinero, opinion, ultimas noticias, deportes, politica, managua, Managua, ultima hora, daily, newspaper, news, breaking news, urgente, tecnologia, tiempo, weather, buscador, magazine, Magazine, nosotras, Nosotras, journalism, clasificados, avisos, classified, ads, media, publicidad, arroba, arroba de oro' + oldest_article = 1 + max_articles_per_feed = 100 + no_stylesheets = True + use_embedded_content = False + encoding = 'cp1252' + remove_javascript = True + language = _('Spanish') + + #Locale setting to get appropriate date/month values in Spanish + try: + #Windows seting for locale + locale.setlocale(locale.LC_TIME,'Spanish_Nicaragua') + except locale.Error: + #Linux setting for locale -- choose one appropriate for your distribution + try: + locale.setlocale(locale.LC_TIME,'es_NI') + except locale.Error: + try: + locale.setlocale(locale.LC_TIME,'es_ES') + except: + pass + + + current_index = time.strftime("http://www.laprensa.com.ni/archivo/%Y/%B/%d/noticias/") + + html2lrf_options = [ + '--comment', description + , '--category', category + , '--publisher', publisher + , '--ignore-tables' + ] + + html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"\nlinearize_tables=True' + + feeds = [(u'Portada', current_index + 'portada/')] + + def print_version(self, url): + return url.replace('.shtml','_print.shtml') + + def preprocess_html(self, soup): + del soup.body['onload'] + mtag = '' + soup.head.insert(0,mtag) + atag = soup.find('span',attrs={'class':'mas_noticias'}) + if atag: + atag.extract() + btag = soup.find('a',attrs={'href':'/archivo'}) + if btag: + btag.extract() + for item in soup.findAll(style=True): + del item['style'] + return soup + + def parse_index(self): + totalfeeds = [] + lfeeds = self.get_feeds() + for feedobj in lfeeds: + feedtitle, feedurl = feedobj + self.report_progress(0, _('Fetching feed')+' %s...'%(feedtitle if feedtitle else feedurl)) + articles = [] + soup = self.index_to_soup(feedurl) + for item in soup.findAll('a', attrs={'class':['titular','titulonotamed']}): + description = '' + url = feedurl + item['href'] + title = self.tag_to_string(item) + date = time.strftime(self.timefmt) + articles.append({ + 'title' :title + ,'date' :date + ,'url' :url + ,'description':description + }) + totalfeeds.append((feedtitle, articles)) + return totalfeeds + + def cleanup(self): + #Going back to the default locale + locale.setlocale(locale.LC_TIME,'') diff --git a/src/calibre/www/apps/feedjack/views.py b/src/calibre/www/apps/feedjack/views.py index c1f31eb908..27b5dc0783 100644 --- a/src/calibre/www/apps/feedjack/views.py +++ b/src/calibre/www/apps/feedjack/views.py @@ -26,7 +26,8 @@ def initview(request): 5. The feeds for the site (ids) """ - site_id, cachekey = fjlib.getcurrentsite(request.META['HTTP_HOST'], \ + site_id, cachekey = fjlib.getcurrentsite(request.META.get('HTTP_HOST', + 'planet.calibre-ebook.com'), \ request.META.get('REQUEST_URI', request.META.get('PATH_INFO', '/')), \ request.META['QUERY_STRING']) response = fjcache.cache_get(site_id, cachekey) diff --git a/src/calibre/www/publish.sh b/src/calibre/www/publish.sh index c78f0a1d89..8882a8b7ea 100755 --- a/src/calibre/www/publish.sh +++ b/src/calibre/www/publish.sh @@ -1,4 +1,4 @@ #!/bin/sh -ssh divok "cd /usr/local/calibre && bzr pull" +ssh divok "cd /usr/local/calibre && bzr up" ssh divok /etc/init.d/apache2 graceful diff --git a/src/calibre/www/templates/feedjack/default/post_list.html b/src/calibre/www/templates/feedjack/default/post_list.html index 25ecb152b0..8aaa427a33 100644 --- a/src/calibre/www/templates/feedjack/default/post_list.html +++ b/src/calibre/www/templates/feedjack/default/post_list.html @@ -52,7 +52,7 @@
- {{ item.feed.title|safe }} + {{ item.feed.name|safe }}
diff --git a/upload.py b/upload.py index 814d124523..b2fc81c8b6 100644 --- a/upload.py +++ b/upload.py @@ -667,9 +667,16 @@ class stage3(OptionlessCommand): def misc(cls): check_call('ssh divok rm -f %s/calibre-\*.tar.gz'%DOWNLOADS, shell=True) check_call('scp dist/calibre-*.tar.gz divok:%s/'%DOWNLOADS, shell=True) + check_call('gpg --armor --detach-sign dist/calibre-*.tar.gz', + shell=True) + check_call('scp dist/calibre-*.tar.gz.asc divok:%s/signatures/'%DOWNLOADS, + shell=True) check_call('''rm -rf dist/* build/*''', shell=True) check_call('ssh divok bzr update /var/www/calibre.kovidgoyal.net/calibre/', shell=True) + check_call('ssh divok bzr update /usr/local/calibre', + shell=True) + def run(self): OptionlessCommand.run(self)