home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 January / maximum-cd-2011-01.iso / DiscContents / calibre-0.7.26.msi / file_1182 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-10-31  |  13.4 KB  |  303 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. __license__ = 'GPL v3'
  5. __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
  6. __docformat__ = 'restructuredtext en'
  7. import os
  8. import collections
  9. from PyQt4.Qt import QLabel, QPixmap, QSize, QWidget, Qt, pyqtSignal, QVBoxLayout, QScrollArea, QPropertyAnimation, QEasingCurve, QSizePolicy, QPainter, QRect, pyqtProperty
  10. from calibre import fit_image, prepare_string_for_xml
  11. from calibre.gui2.widgets import IMAGE_EXTENSIONS
  12. from calibre.ebooks import BOOK_EXTENSIONS
  13. from calibre.constants import preferred_encoding
  14. from calibre.library.comments import comments_to_html
  15. from calibre.gui2 import config, open_local_file
  16. WEIGHTS = collections.defaultdict((lambda : 100))
  17. WEIGHTS[_('Path')] = 5
  18. WEIGHTS[_('Formats')] = 1
  19. WEIGHTS[_('Collections')] = 2
  20. WEIGHTS[_('Series')] = 3
  21. WEIGHTS[_('Tags')] = 4
  22.  
  23. def render_rows(data):
  24.     keys = data.keys()
  25.     keys.sort(cmp = (lambda x, y: cmp(x.lower(), y.lower())))
  26.     keys.sort(cmp = (lambda x, y: cmp(WEIGHTS[x], WEIGHTS[y])))
  27.     rows = []
  28.     for key in keys:
  29.         txt = data[key]
  30.         if key in ('id', _('Comments')) and not hasattr(txt, 'strip') and not txt.strip() or txt == 'None':
  31.             continue
  32.         
  33.         if isinstance(key, str):
  34.             key = key.decode(preferred_encoding, 'replace')
  35.         
  36.         if isinstance(txt, str):
  37.             txt = txt.decode(preferred_encoding, 'replace')
  38.         
  39.         if '</font>' not in txt:
  40.             txt = prepare_string_for_xml(txt)
  41.         
  42.         if 'id' in data:
  43.             if key == _('Path'):
  44.                 txt = u'<a href="path:%s" title="%s">%s</a>' % (data['id'], txt, _('Click to open'))
  45.             
  46.             if key == _('Formats') and txt and txt != _('None'):
  47.                 fmts = [ x.strip() for x in txt.split(',') ]
  48.                 fmts = [ u'<a href="format:%s:%s">%s</a>' % (data['id'], x, x) for x in fmts ]
  49.                 txt = ', '.join(fmts)
  50.             
  51.         elif key == _('Path'):
  52.             txt = u'<a href="devpath:%s">%s</a>' % (txt, _('Click to open'))
  53.         
  54.         rows.append((key, txt))
  55.     
  56.     return rows
  57.  
  58.  
  59. class CoverView(QWidget):
  60.     
  61.     def __init__(self, vertical, parent = None):
  62.         QWidget.__init__(self, parent)
  63.         self.setMaximumSize(QSize(120, 120))
  64.         None(None(self.setMinimumSize, QSize if vertical else 20 if vertical else 20))
  65.         self._current_pixmap_size = self.maximumSize()
  66.         self.vertical = vertical
  67.         self.animation = QPropertyAnimation(self, 'current_pixmap_size', self)
  68.         self.animation.setEasingCurve(QEasingCurve(QEasingCurve.OutExpo))
  69.         self.animation.setDuration(1000)
  70.         self.animation.setStartValue(QSize(0, 0))
  71.         self.animation.valueChanged.connect(self.value_changed)
  72.         None(self.setSizePolicy if vertical else QSizePolicy.Minimum, QSizePolicy.Expanding)
  73.         self.default_pixmap = QPixmap(I('book.png'))
  74.         self.pixmap = self.default_pixmap
  75.         self.pwidth = None
  76.         self.pheight = None
  77.         self.data = { }
  78.         self.do_layout()
  79.  
  80.     
  81.     def value_changed(self, val):
  82.         self.update()
  83.  
  84.     
  85.     def setCurrentPixmapSize(self, val):
  86.         self._current_pixmap_size = val
  87.  
  88.     
  89.     def do_layout(self):
  90.         if self.rect().width() == 0 or self.rect().height() == 0:
  91.             return None
  92.         pixmap = self.pixmap
  93.         pwidth = pixmap.width()
  94.         pheight = pixmap.height()
  95.         
  96.         try:
  97.             (self.pwidth, self.pheight) = fit_image(pwidth, pheight, self.rect().width(), self.rect().height())[1:]
  98.         except:
  99.             self.rect().height() == 0
  100.             self.pwidth = self.rect().width() - 1
  101.             self.pheight = self.rect().height() - 1
  102.  
  103.         self.current_pixmap_size = QSize(self.pwidth, self.pheight)
  104.         self.animation.setEndValue(self.current_pixmap_size)
  105.  
  106.     
  107.     def relayout(self, parent_size):
  108.         if self.vertical:
  109.             self.setMaximumSize(parent_size.width(), min(int(parent_size.height() / 2), int((4 / 3) * parent_size.width()) + 1))
  110.         else:
  111.             self.setMaximumSize(1 + int((3 / 4) * parent_size.height()), parent_size.height())
  112.         self.resize(self.maximumSize())
  113.         self.animation.stop()
  114.         self.do_layout()
  115.  
  116.     
  117.     def sizeHint(self):
  118.         return self.maximumSize()
  119.  
  120.     
  121.     def show_data(self, data):
  122.         self.animation.stop()
  123.         same_item = data.get('id', True) == self.data.get('id', False)
  124.         self.data = {
  125.             'id': data.get('id', None) }
  126.         if data.has_key('cover'):
  127.             self.pixmap = QPixmap.fromImage(data.pop('cover'))
  128.             if self.pixmap.isNull() and self.pixmap.width() < 5 or self.pixmap.height() < 5:
  129.                 self.pixmap = self.default_pixmap
  130.             
  131.         else:
  132.             self.pixmap = self.default_pixmap
  133.         self.do_layout()
  134.         self.update()
  135.         if not same_item and not config['disable_animations']:
  136.             self.animation.start()
  137.         
  138.  
  139.     
  140.     def paintEvent(self, event):
  141.         canvas_size = self.rect()
  142.         width = self.current_pixmap_size.width()
  143.         extrax = canvas_size.width() - width
  144.         if extrax < 0:
  145.             extrax = 0
  146.         
  147.         x = int(extrax / 2)
  148.         height = self.current_pixmap_size.height()
  149.         extray = canvas_size.height() - height
  150.         if extray < 0:
  151.             extray = 0
  152.         
  153.         y = int(extray / 2)
  154.         target = QRect(x, y, width, height)
  155.         p = QPainter(self)
  156.         p.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
  157.         p.drawPixmap(target, self.pixmap.scaled(target.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))
  158.         p.end()
  159.  
  160.     current_pixmap_size = pyqtProperty('QSize', fget = (lambda self: self._current_pixmap_size), fset = setCurrentPixmapSize)
  161.  
  162.  
  163. class Label(QLabel):
  164.     mr = pyqtSignal(object)
  165.     link_clicked = pyqtSignal(object)
  166.     
  167.     def __init__(self):
  168.         QLabel.__init__(self)
  169.         self.setTextFormat(Qt.RichText)
  170.         self.setText('')
  171.         self.setWordWrap(True)
  172.         self.setAlignment(Qt.AlignTop)
  173.         self.linkActivated.connect(self.link_activated)
  174.         self._link_clicked = False
  175.         self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
  176.  
  177.     
  178.     def link_activated(self, link):
  179.         self._link_clicked = True
  180.         link = unicode(link)
  181.         self.link_clicked.emit(link)
  182.  
  183.     
  184.     def mouseReleaseEvent(self, ev):
  185.         QLabel.mouseReleaseEvent(self, ev)
  186.         if not self._link_clicked:
  187.             self.mr.emit(ev)
  188.         
  189.         self._link_clicked = False
  190.  
  191.  
  192.  
  193. class BookInfo(QScrollArea):
  194.     
  195.     def __init__(self, vertical, parent = None):
  196.         QScrollArea.__init__(self, parent)
  197.         self.vertical = vertical
  198.         self.setWidgetResizable(True)
  199.         self.label = Label()
  200.         self.setWidget(self.label)
  201.         self.link_clicked = self.label.link_clicked
  202.         self.mr = self.label.mr
  203.         self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
  204.  
  205.     
  206.     def show_data(self, data):
  207.         self.label.setText('')
  208.         rows = render_rows(data)
  209.         rows = []([ u'<tr><td valign="top"><b>%s:</b></td><td valign="top">%s</td></tr>' % (k, t) for k, t in rows ])
  210.         comments = ''
  211.  
  212.  
  213.  
  214. class BookDetails(QWidget):
  215.     resized = pyqtSignal(object)
  216.     show_book_info = pyqtSignal()
  217.     open_containing_folder = pyqtSignal(int)
  218.     view_specific_format = pyqtSignal(int, object)
  219.     DROPABBLE_EXTENSIONS = IMAGE_EXTENSIONS + BOOK_EXTENSIONS
  220.     files_dropped = pyqtSignal(object, object)
  221.     
  222.     def paths_from_event(cls, event):
  223.         if event.mimeData().hasFormat('text/uri-list'):
  224.             urls = [ unicode(u.toLocalFile()) for u in event.mimeData().urls() ]
  225.             urls = _[2]
  226.             return _[3]
  227.  
  228.     paths_from_event = classmethod(paths_from_event)
  229.     
  230.     def dragEnterEvent(self, event):
  231.         if int(event.possibleActions() & Qt.CopyAction) + int(event.possibleActions() & Qt.MoveAction) == 0:
  232.             return None
  233.         paths = self.paths_from_event(event)
  234.         if paths:
  235.             event.acceptProposedAction()
  236.         
  237.  
  238.     
  239.     def dropEvent(self, event):
  240.         paths = self.paths_from_event(event)
  241.         event.setDropAction(Qt.CopyAction)
  242.         self.files_dropped.emit(event, paths)
  243.  
  244.     
  245.     def dragMoveEvent(self, event):
  246.         event.acceptProposedAction()
  247.  
  248.     
  249.     def __init__(self, vertical, parent = None):
  250.         QWidget.__init__(self, parent)
  251.         self.setAcceptDrops(True)
  252.         self._layout = QVBoxLayout()
  253.         if not vertical:
  254.             self._layout.setDirection(self._layout.LeftToRight)
  255.         
  256.         self.setLayout(self._layout)
  257.         self.cover_view = CoverView(vertical, self)
  258.         self.cover_view.relayout(self.size())
  259.         self.resized.connect(self.cover_view.relayout, type = Qt.QueuedConnection)
  260.         self._layout.addWidget(self.cover_view)
  261.         self.book_info = BookInfo(vertical, self)
  262.         self._layout.addWidget(self.book_info)
  263.         self.book_info.link_clicked.connect(self._link_clicked)
  264.         self.book_info.mr.connect(self.mouseReleaseEvent)
  265.         if vertical:
  266.             self.setMinimumSize(QSize(190, 200))
  267.         else:
  268.             self.setMinimumSize(120, 120)
  269.         self.setCursor(Qt.PointingHandCursor)
  270.  
  271.     
  272.     def _link_clicked(self, link):
  273.         (typ, _, val) = link.partition(':')
  274.         if typ == 'path':
  275.             self.open_containing_folder.emit(int(val))
  276.         elif typ == 'format':
  277.             (id_, fmt) = val.split(':')
  278.             self.view_specific_format.emit(int(id_), fmt)
  279.         elif typ == 'devpath':
  280.             open_local_file(val)
  281.         
  282.  
  283.     
  284.     def mouseReleaseEvent(self, ev):
  285.         ev.accept()
  286.         self.show_book_info.emit()
  287.  
  288.     
  289.     def resizeEvent(self, ev):
  290.         self.resized.emit(self.size())
  291.  
  292.     
  293.     def show_data(self, data):
  294.         self.cover_view.show_data(data)
  295.         self.book_info.show_data(data)
  296.         self.setToolTip('<p>' + _('Click to open Book Details window') + '<br><br>' + _('Path') + ': ' + data.get(_('Path'), ''))
  297.  
  298.     
  299.     def reset_info(self):
  300.         self.show_data({ })
  301.  
  302.  
  303.