home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_1300 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  22.8 KB  |  639 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. __license__ = 'GPL v3'
  5. __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
  6. import collections
  7. import itertools
  8. import glob
  9. from PyQt4.QtCore import Qt, QByteArray, SIGNAL
  10. from PyQt4.QtGui import QGraphicsRectItem, QGraphicsScene, QPen, QBrush, QColor, QFontDatabase, QGraphicsItem, QGraphicsLineItem
  11. from calibre.gui2.lrf_renderer.text import TextBlock, FontLoader, COLOR, PixmapItem
  12. from calibre.ebooks.lrf.objects import RuledLine as _RuledLine
  13. from calibre.ebooks.lrf.objects import Canvas as __Canvas
  14.  
  15. class Color(QColor):
  16.     
  17.     def __init__(self, color):
  18.         QColor.__init__(self, color.r, color.g, color.b, 255 - color.a)
  19.  
  20.  
  21.  
  22. class Pen(QPen):
  23.     
  24.     def __init__(self, color, width):
  25.         None(QPen.__init__, self, QBrush(Color(color)), width if width > 0 else Qt.NoPen)
  26.  
  27.  
  28.  
  29. class ContentObject(object):
  30.     has_content = True
  31.     
  32.     def reset(self):
  33.         self.has_content = True
  34.  
  35.  
  36.  
  37. class RuledLine(QGraphicsLineItem, ContentObject):
  38.     map = {
  39.         'solid': Qt.SolidLine,
  40.         'dashed': Qt.DashLine,
  41.         'dotted': Qt.DotLine,
  42.         'double': Qt.DashDotLine }
  43.     
  44.     def __init__(self, rl):
  45.         QGraphicsLineItem.__init__(self, 0, 0, rl.linelength, 0)
  46.         ContentObject.__init__(self)
  47.         self.setPen(QPen(COLOR(rl.linecolor, None), rl.linewidth))
  48.  
  49.  
  50.  
  51. class ImageBlock(PixmapItem, ContentObject):
  52.     
  53.     def __init__(self, obj):
  54.         ContentObject.__init__(self)
  55.         (x0, y0, x1, y1) = (obj.attrs['x0'], obj.attrs['y0'], obj.attrs['x1'], obj.attrs['y1'])
  56.         xsize = obj.attrs['xsize']
  57.         ysize = obj.attrs['ysize']
  58.         refstream = obj.refstream
  59.         data = refstream.stream
  60.         encoding = refstream.encoding
  61.         PixmapItem.__init__(self, data, encoding, x0, y0, x1, y1, xsize, ysize)
  62.         self.block_id = obj.id
  63.  
  64.  
  65.  
  66. def object_factory(container, obj, respect_max_y = False):
  67.     if hasattr(obj, 'name'):
  68.         if obj.name.endswith('TextBlock'):
  69.             return TextBlock(obj, container.font_loader, respect_max_y, container.text_width, container.logger, container.opts, container.ruby_tags, container.link_activated)
  70.         if obj.name.endswith('ImageBlock'):
  71.             return ImageBlock(obj)
  72.     elif isinstance(obj, _RuledLine):
  73.         return RuledLine(obj)
  74.     obj.name.endswith('TextBlock')
  75.     if isinstance(obj, __Canvas):
  76.         return Canvas(container.font_loader, obj, container.logger, container.opts, container.ruby_tags, container.link_activated)
  77.  
  78.  
  79. class _Canvas(QGraphicsRectItem):
  80.     
  81.     def __init__(self, font_loader, logger, opts, width = 0, height = 0, parent = None, x = 0, y = 0):
  82.         QGraphicsRectItem.__init__(self, x, y, width, height, parent)
  83.         self.font_loader = font_loader
  84.         self.logger = logger
  85.         self.opts = opts
  86.         self.current_y = 0
  87.         self.max_y = height
  88.         self.max_x = width
  89.         self.is_full = False
  90.         pen = QPen()
  91.         pen.setStyle(Qt.NoPen)
  92.         self.setPen(pen)
  93.         if not hasattr(self, 'children'):
  94.             self.children = self.childItems
  95.         
  96.  
  97.     
  98.     def layout_block(self, block, x, y):
  99.         if isinstance(block, TextBlock):
  100.             self.layout_text_block(block, x, y)
  101.         elif isinstance(block, RuledLine):
  102.             self.layout_ruled_line(block, x, y)
  103.         elif isinstance(block, ImageBlock):
  104.             self.layout_image_block(block, x, y)
  105.         elif isinstance(block, Canvas):
  106.             self.layout_canvas(block, x, y)
  107.         
  108.  
  109.     
  110.     def layout_canvas(self, canvas, x, y):
  111.         if canvas.max_y + y > self.max_y and y > 0:
  112.             self.is_full = True
  113.             return None
  114.         canvas.setParentItem(self)
  115.         canvas.setPos(x, y)
  116.         canvas.has_content = False
  117.         canvas.put_objects()
  118.         self.current_y += canvas.max_y
  119.  
  120.     
  121.     def layout_text_block(self, block, x, y):
  122.         textwidth = block.bs.blockwidth - block.bs.sidemargin
  123.         if block.max_y == 0 or not (block.lines):
  124.             self.is_full = False
  125.             return None
  126.         line = block.peek()
  127.         y += block.bs.topskip
  128.         block_consumed = False
  129.         line.height = min(line.height, self.max_y - block.bs.topskip)
  130.         while y + line.height <= self.max_y:
  131.             block.commit()
  132.             if isinstance(line, QGraphicsItem):
  133.                 line.setParentItem(self)
  134.                 line.setPos(x + line.getx(textwidth), y)
  135.                 y += line.height + line.line_space
  136.             else:
  137.                 y += line.height
  138.             if not block.has_content:
  139.                 
  140.                 try:
  141.                     y += block.bs.footskip
  142.                 except AttributeError:
  143.                     pass
  144.  
  145.                 block_consumed = True
  146.                 break
  147.                 continue
  148.             line = block.peek()
  149.         self.current_y = y
  150.         self.is_full = not block_consumed
  151.  
  152.     
  153.     def layout_ruled_line(self, rl, x, y):
  154.         br = rl.boundingRect()
  155.         rl.setParentItem(self)
  156.         rl.setPos(x, y + 1)
  157.         self.current_y = y + br.height() + 1
  158.         self.is_full = y > self.max_y - 5
  159.         rl.has_content = False
  160.  
  161.     
  162.     def layout_image_block(self, ib, x, y):
  163.         mw = self.max_x - x
  164.         mh = self.max_y - y
  165.         if self.current_y + ib.height > self.max_y - y and self.current_y > 5:
  166.             self.is_full = True
  167.         elif ib.width > mw or ib.height > mh:
  168.             ib.resize(mw, mh)
  169.         
  170.         br = ib.boundingRect()
  171.         max_height = min(br.height(), self.max_y - y)
  172.         max_width = min(br.width(), self.max_x - x)
  173.         if br.height() > max_height or br.width() > max_width:
  174.             p = ib.pixmap()
  175.             ib.setPixmap(p.scaled(max_width, max_height, Qt.IgnoreAspectRatio, Qt.SmoothTransformation))
  176.             br = ib.boundingRect()
  177.         
  178.         ib.setParentItem(self)
  179.         ib.setPos(x, y)
  180.         self.current_y = y + br.height()
  181.         self.is_full = y > self.max_y - 5
  182.         ib.has_content = False
  183.         if ib.block_id == 54:
  184.             print 
  185.             print ib.block_id, ib.has_content, self.is_full
  186.             print self.current_y, self.max_y, y, br.height()
  187.             print 
  188.         
  189.  
  190.     
  191.     def search(self, phrase):
  192.         matches = []
  193.         for child in self.children():
  194.             if hasattr(child, 'search'):
  195.                 res = child.search(phrase)
  196.                 if res:
  197.                     if isinstance(res, list):
  198.                         matches += res
  199.                     else:
  200.                         matches.append(res)
  201.                 
  202.             res
  203.         
  204.         return matches
  205.  
  206.  
  207.  
  208. class Canvas(_Canvas, ContentObject):
  209.     
  210.     def __init__(self, font_loader, canvas, logger, opts, ruby_tags, link_activated, width = 0, height = 0):
  211.         if hasattr(canvas, 'canvaswidth'):
  212.             width = canvas.canvaswidth
  213.             height = canvas.canvasheight
  214.         
  215.         _Canvas.__init__(self, font_loader, logger, opts, width = width, height = height)
  216.         self.block_id = canvas.id
  217.         self.ruby_tags = ruby_tags
  218.         self.link_activated = link_activated
  219.         self.text_width = width
  220.         fg = canvas.framecolor
  221.         bg = canvas.bgcolor
  222.         if not (opts.visual_debug) and canvas.framemode != 'none':
  223.             self.setPen(Pen(fg, canvas.framewidth))
  224.         
  225.         self.setBrush(QBrush(Color(bg)))
  226.         self.items = []
  227.         for po in canvas:
  228.             obj = po.object
  229.             item = object_factory(self, obj, respect_max_y = True)
  230.             if item:
  231.                 self.items.append((item, po.x1, po.y1))
  232.                 continue
  233.         
  234.  
  235.     
  236.     def put_objects(self):
  237.         for block, x, y in self.items:
  238.             self.layout_block(block, x, y)
  239.         
  240.  
  241.     
  242.     def layout_block(self, block, x, y):
  243.         block.reset()
  244.         _Canvas.layout_block(self, block, x, y)
  245.  
  246.  
  247.  
  248. class Header(Canvas):
  249.     
  250.     def __init__(self, font_loader, header, page_style, logger, opts, ruby_tags, link_activated):
  251.         Canvas.__init__(self, font_loader, header, logger, opts, ruby_tags, link_activated, page_style.textwidth, page_style.headheight)
  252.         if opts.visual_debug:
  253.             self.setPen(QPen(Qt.blue, 1, Qt.DashLine))
  254.         
  255.  
  256.  
  257.  
  258. class Footer(Canvas):
  259.     
  260.     def __init__(self, font_loader, footer, page_style, logger, opts, ruby_tags, link_activated):
  261.         Canvas.__init__(self, font_loader, footer, logger, opts, ruby_tags, link_activated, page_style.textwidth, page_style.footheight)
  262.         if opts.visual_debug:
  263.             self.setPen(QPen(Qt.blue, 1, Qt.DashLine))
  264.         
  265.  
  266.  
  267.  
  268. class Screen(_Canvas):
  269.     
  270.     def __init__(self, font_loader, chapter, odd, logger, opts, ruby_tags, link_activated):
  271.         self.logger = logger
  272.         self.opts = opts
  273.         page_style = chapter.style
  274.         sidemargin = None if odd else page_style.evensidemargin
  275.         width = 2 * sidemargin + page_style.textwidth
  276.         self.content_x = 0 + sidemargin
  277.         self.text_width = page_style.textwidth
  278.         self.header_y = page_style.topmargin
  279.         self.text_y = self.header_y + page_style.headheight + page_style.headsep
  280.         self.text_height = page_style.textheight
  281.         self.footer_y = self.text_y + self.text_height + (page_style.footspace - page_style.footheight)
  282.         _Canvas.__init__(self, font_loader, logger, opts, width = width, height = self.footer_y + page_style.footheight)
  283.         if opts.visual_debug:
  284.             self.setPen(QPen(Qt.red, 1, Qt.SolidLine))
  285.         
  286.         header = None
  287.         footer = None
  288.         if page_style.headheight > 0:
  289.             
  290.             try:
  291.                 header = None if odd else chapter.evenheader
  292.             except AttributeError:
  293.                 pass
  294.             except:
  295.                 None<EXCEPTION MATCH>AttributeError
  296.             
  297.  
  298.         None<EXCEPTION MATCH>AttributeError
  299.         if page_style.footheight > 0:
  300.             
  301.             try:
  302.                 footer = None if odd else chapter.evenfooter
  303.             except AttributeError:
  304.                 pass
  305.             except:
  306.                 None<EXCEPTION MATCH>AttributeError
  307.             
  308.  
  309.         None<EXCEPTION MATCH>AttributeError
  310.         if header:
  311.             header = Header(font_loader, header, page_style, logger, opts, ruby_tags, link_activated)
  312.             self.layout_canvas(header, self.content_x, self.header_y)
  313.         
  314.         if footer:
  315.             footer = Footer(font_loader, footer, page_style, logger, opts, ruby_tags, link_activated)
  316.             self.layout_canvas(footer, self.content_x, self.header_y)
  317.         
  318.         self.page = None
  319.  
  320.     
  321.     def set_page(self, page):
  322.         if self.page is not None and self.page.scene():
  323.             self.scene().removeItem(self.page)
  324.         
  325.         self.page = page
  326.         self.page.setPos(self.content_x, self.text_y)
  327.         self.scene().addItem(self.page)
  328.  
  329.     
  330.     def remove(self):
  331.         if self.scene():
  332.             if self.page is not None and self.page.scene():
  333.                 self.scene().removeItem(self.page)
  334.             
  335.             self.scene().removeItem(self)
  336.         
  337.  
  338.  
  339.  
  340. class Page(_Canvas):
  341.     
  342.     def __init__(self, font_loader, logger, opts, width, height):
  343.         _Canvas.__init__(self, font_loader, logger, opts, width, height)
  344.         if opts.visual_debug:
  345.             self.setPen(QPen(Qt.cyan, 1, Qt.DashLine))
  346.         
  347.  
  348.     
  349.     def id(self):
  350.         for child in self.children():
  351.             if hasattr(child, 'block_id'):
  352.                 return child.block_id
  353.         
  354.  
  355.     
  356.     def add_block(self, block):
  357.         self.layout_block(block, 0, self.current_y)
  358.  
  359.  
  360.  
  361. class Chapter(object):
  362.     num_of_pages = property(fget = (lambda self: len(self.pages)))
  363.     
  364.     def __init__(self, oddscreen, evenscreen, pages, object_to_page_map):
  365.         (self.oddscreen, self.evenscreen, self.pages, self.object_to_page_map) = (oddscreen, evenscreen, pages, object_to_page_map)
  366.  
  367.     
  368.     def page_of_object(self, id):
  369.         return self.object_to_page_map[id]
  370.  
  371.     
  372.     def page(self, num):
  373.         return self.pages[num - 1]
  374.  
  375.     
  376.     def screen(self, odd):
  377.         if odd:
  378.             return self.oddscreen
  379.         return self.evenscreen
  380.  
  381.     
  382.     def search(self, phrase):
  383.         pages = []
  384.         for i in range(len(self.pages)):
  385.             matches = self.pages[i].search(phrase)
  386.             if matches:
  387.                 pages.append([
  388.                     i,
  389.                     matches])
  390.                 continue
  391.         
  392.         return pages
  393.  
  394.  
  395.  
  396. class History(collections.deque):
  397.     
  398.     def __init__(self):
  399.         collections.deque.__init__(self)
  400.         self.pos = 0
  401.  
  402.     
  403.     def back(self):
  404.         if self.pos - 1 < 0:
  405.             return None
  406.         self.pos -= 1
  407.         return self[self.pos]
  408.  
  409.     
  410.     def forward(self):
  411.         if self.pos + 1 >= len(self):
  412.             return None
  413.         self.pos += 1
  414.         return self[self.pos]
  415.  
  416.     
  417.     def add(self, item):
  418.         while len(self) > self.pos + 1:
  419.             self.pop()
  420.         self.append(item)
  421.         self.pos += 1
  422.  
  423.  
  424.  
  425. class Document(QGraphicsScene):
  426.     num_of_pages = property(fget = (lambda self: sum(self.chapter_layout)))
  427.     
  428.     def __init__(self, logger, opts):
  429.         QGraphicsScene.__init__(self)
  430.         self.logger = logger
  431.         self.opts = opts
  432.         self.pages = []
  433.         self.chapters = []
  434.         self.chapter_layout = None
  435.         self.current_screen = None
  436.         self.current_page = 0
  437.         self.link_map = { }
  438.         self.chapter_map = { }
  439.         self.history = History()
  440.         self.last_search = iter([])
  441.         if not opts.white_background:
  442.             self.setBackgroundBrush(QBrush(QColor(238, 238, 238)))
  443.         
  444.  
  445.     
  446.     def page_of(self, oid):
  447.         for chapter in self.chapters:
  448.             if oid in chapter.object_to_page_map:
  449.                 return chapter.object_to_page_map[oid]
  450.         
  451.  
  452.     
  453.     def get_page_num(self, chapterid, objid):
  454.         cnum = self.chapter_map[chapterid]
  455.         page = self.chapters[cnum].object_to_page_map[objid]
  456.         return sum(self.chapter_layout[:cnum]) + page
  457.  
  458.     
  459.     def add_to_history(self):
  460.         page = self.chapter_page(self.current_page)[1]
  461.         page_id = page.id()
  462.         if page_id is not None:
  463.             self.history.add(page_id)
  464.         
  465.  
  466.     
  467.     def link_activated(self, objid, on_creation = None):
  468.         if on_creation is None:
  469.             (cid, oid) = self.link_map[objid]
  470.             if oid is not None:
  471.                 self.add_to_history()
  472.                 page = self.get_page_num(cid, oid)
  473.                 self.show_page(page)
  474.             
  475.         else:
  476.             jb = self.objects[objid]
  477.             self.link_map[objid] = (jb.refpage, jb.refobj)
  478.  
  479.     
  480.     def back(self):
  481.         oid = self.history.back()
  482.         if oid is not None:
  483.             page = self.page_of(oid)
  484.             self.show_page(page)
  485.         
  486.  
  487.     
  488.     def forward(self):
  489.         oid = self.history.forward()
  490.         if oid is not None:
  491.             page = self.page_of(oid)
  492.             self.show_page(page)
  493.         
  494.  
  495.     
  496.     def load_fonts(self, lrf, load_substitutions = True):
  497.         font_map = { }
  498.         for font in lrf.font_map:
  499.             fdata = QByteArray(lrf.font_map[font].data)
  500.             id = QFontDatabase.addApplicationFontFromData(fdata)
  501.             if id != -1:
  502.                 font_map[font] = [ str(i) for i in QFontDatabase.applicationFontFamilies(id) ][0]
  503.                 continue
  504.             []
  505.         
  506.         if load_substitutions:
  507.             base = P('fonts/liberation/*.ttf')
  508.             for f in glob.glob(base):
  509.                 QFontDatabase.addApplicationFont(f)
  510.             
  511.         
  512.         self.font_loader = FontLoader(font_map, self.dpi)
  513.  
  514.     
  515.     def render_chapter(self, chapter, lrf):
  516.         oddscreen = Screen(self.font_loader, chapter, True, self.logger, self.opts, self.ruby_tags, self.link_activated)
  517.         evenscreen = Screen(self.font_loader, chapter, False, self.logger, self.opts, self.ruby_tags, self.link_activated)
  518.         pages = []
  519.         width = oddscreen.text_width
  520.         height = oddscreen.text_height
  521.         current_page = Page(self.font_loader, self.logger, self.opts, width, height)
  522.         object_to_page_map = { }
  523.         for object in chapter:
  524.             self.text_width = width
  525.             block = object_factory(self, object)
  526.             if block is None:
  527.                 continue
  528.             
  529.             object_to_page_map[object.id] = len(pages) + 1
  530.             while block.has_content:
  531.                 current_page.add_block(block)
  532.                 if current_page.is_full:
  533.                     pages.append(current_page)
  534.                     current_page = Page(self.font_loader, self.logger, self.opts, width, height)
  535.                     continue
  536.         
  537.         if current_page:
  538.             pages.append(current_page)
  539.         
  540.         self.chapters.append(Chapter(oddscreen, evenscreen, pages, object_to_page_map))
  541.         self.chapter_map[chapter.id] = len(self.chapters) - 1
  542.  
  543.     
  544.     def render(self, lrf, load_substitutions = True):
  545.         self.dpi = lrf.device_info.dpi / 10
  546.         self.ruby_tags = dict(**lrf.ruby_tags)
  547.         self.load_fonts(lrf, load_substitutions)
  548.         self.objects = lrf.objects
  549.         num_chaps = 0
  550.         for pt in lrf.page_trees:
  551.             for chapter in pt:
  552.                 num_chaps += 1
  553.             
  554.         
  555.         self.emit(SIGNAL('chapter_rendered(int)'), num_chaps)
  556.         for pt in lrf.page_trees:
  557.             for chapter in pt:
  558.                 self.render_chapter(chapter, lrf)
  559.                 self.emit(SIGNAL('chapter_rendered(int)'), -1)
  560.             
  561.         
  562.         self.chapter_layout = [ i.num_of_pages for i in self.chapters ]
  563.         self.objects = None
  564.  
  565.     
  566.     def chapter_page(self, num):
  567.         for chapter in self.chapters:
  568.             if num <= chapter.num_of_pages:
  569.                 break
  570.             
  571.             num -= chapter.num_of_pages
  572.         
  573.         return (chapter, chapter.page(num))
  574.  
  575.     
  576.     def show_page(self, num):
  577.         if num < 1 and num > self.num_of_pages or num == self.current_page:
  578.             return None
  579.         odd = num % 2 == 1
  580.         self.current_page = num
  581.         (chapter, page) = self.chapter_page(num)
  582.         screen = chapter.screen(odd)
  583.         if self.current_screen is not None and self.current_screen is not screen:
  584.             self.current_screen.remove()
  585.         
  586.         self.current_screen = screen
  587.         if self.current_screen.scene() is None:
  588.             self.addItem(self.current_screen)
  589.         
  590.         self.current_screen.set_page(page)
  591.         self.emit(SIGNAL('page_changed(PyQt_PyObject)'), self.current_page)
  592.  
  593.     
  594.     def next(self):
  595.         self.next_by(1)
  596.  
  597.     
  598.     def previous(self):
  599.         self.previous_by(1)
  600.  
  601.     
  602.     def next_by(self, num):
  603.         self.show_page(self.current_page + num)
  604.  
  605.     
  606.     def previous_by(self, num):
  607.         self.show_page(self.current_page - num)
  608.  
  609.     
  610.     def show_page_at_percent(self, p):
  611.         num = self.num_of_pages * (p / 100)
  612.         self.show_page(num)
  613.  
  614.     
  615.     def search(self, phrase):
  616.         if not phrase:
  617.             return None
  618.         matches = []
  619.         for i in range(len(self.chapters)):
  620.             cmatches = self.chapters[i].search(phrase)
  621.             for match in cmatches:
  622.                 match[0] += sum(self.chapter_layout[:i]) + 1
  623.             
  624.             matches += cmatches
  625.         
  626.         self.last_search = itertools.cycle(matches)
  627.         self.next_match()
  628.  
  629.     
  630.     def next_match(self):
  631.         page_num = self.last_search.next()[0]
  632.         if self.current_page == page_num:
  633.             self.update()
  634.         else:
  635.             self.add_to_history()
  636.             self.show_page(page_num)
  637.  
  638.  
  639.