home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 January / maximum-cd-2011-01.iso / DiscContents / calibre-0.7.26.msi / file_1157 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-10-31  |  9.0 KB  |  216 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 datetime
  9. from PyQt4.Qt import pyqtSignal, QModelIndex, QThread, Qt
  10. from calibre.gui2 import error_dialog, gprefs
  11. from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag, NavigableString
  12. from calibre import strftime
  13. from calibre.gui2.actions import InterfaceAction
  14.  
  15. class FetchAnnotationsAction(InterfaceAction):
  16.     name = 'Fetch Annotations'
  17.     action_spec = (_('Fetch annotations (experimental)'), None, None, None)
  18.     action_type = 'current'
  19.     
  20.     def genesis(self):
  21.         pass
  22.  
  23.     
  24.     def fetch_annotations(self, *args):
  25.         
  26.         def get_ids_from_selected_rows():
  27.             rows = self.gui.library_view.selectionModel().selectedRows()
  28.             if not rows or len(rows) < 2:
  29.                 rows = xrange(self.gui.library_view.model().rowCount(QModelIndex()))
  30.             
  31.             ids = map(self.gui.library_view.model().id, rows)
  32.             return ids
  33.  
  34.         
  35.         def get_formats(id):
  36.             formats = db.formats(id, index_is_id = True)
  37.             fmts = []
  38.             if formats:
  39.                 for format in formats.split(','):
  40.                     fmts.append(format.lower())
  41.                 
  42.             
  43.             return fmts
  44.  
  45.         
  46.         def generate_annotation_paths(ids, db, device):
  47.             path_map = { }
  48.             for id in ids:
  49.                 mi = db.get_metadata(id, index_is_id = True)
  50.                 a_path = device.create_upload_path(os.path.abspath('/<storage>'), mi, 'x.bookmark', create_dirs = False)
  51.                 path_map[id] = dict(path = a_path, fmts = get_formats(id))
  52.             
  53.             return path_map
  54.  
  55.         device = self.gui.device_manager.device
  56.         if self.gui.current_view() is not self.gui.library_view:
  57.             return error_dialog(self.gui, _('Use library only'), _('User annotations generated from main library only'), show = True)
  58.         db = self.gui.library_view.model().db
  59.         ids = get_ids_from_selected_rows()
  60.         if not ids:
  61.             return error_dialog(self.gui, _('No books selected'), _('No books selected to fetch annotations from'), show = True)
  62.         path_map = generate_annotation_paths(ids, db, device)
  63.         self.gui.device_manager.annotations(self.Dispatcher(self.annotations_fetched), path_map)
  64.  
  65.     
  66.     def annotations_fetched(self, job):
  67.         Device = Device
  68.         import calibre.devices.usbms.device
  69.         MetaInformation = MetaInformation
  70.         import calibre.ebooks.metadata
  71.         ProgressDialog = ProgressDialog
  72.         import calibre.gui2.dialogs.progress
  73.         do_add_format = do_add_format
  74.         import calibre.library.cli
  75.         
  76.         class Updater(None, None, None, None, 'Updater', (QThread,)):
  77.             update_progress = pyqtSignal(int)
  78.             update_done = pyqtSignal()
  79.             FINISHED_READING_PCT_THRESHOLD = 96
  80.             
  81.             def __init__(self, parent, db, annotation_map, done_callback):
  82.                 QThread.__init__(self, parent)
  83.                 self.db = db
  84.                 self.pd = ProgressDialog(_('Merging user annotations into database'), '', 0, len(job.result), parent = parent)
  85.                 self.am = annotation_map
  86.                 self.done_callback = done_callback
  87.                 self.pd.canceled_signal.connect(self.canceled)
  88.                 self.pd.setModal(True)
  89.                 self.pd.show()
  90.                 self.update_progress.connect(self.pd.set_value, type = Qt.QueuedConnection)
  91.                 self.update_done.connect(self.pd.hide, type = Qt.QueuedConnection)
  92.  
  93.             
  94.             def generate_annotation_html(self, bookmark):
  95.                 last_read_location = bookmark.last_read_location
  96.                 timestamp = datetime.datetime.utcfromtimestamp(bookmark.timestamp)
  97.                 percent_read = bookmark.percent_read
  98.                 ka_soup = BeautifulSoup()
  99.                 dtc = 0
  100.                 divTag = Tag(ka_soup, 'div')
  101.                 divTag['class'] = 'user_annotations'
  102.                 spanTag = Tag(ka_soup, 'span')
  103.                 spanTag['style'] = 'font-weight:bold'
  104.                 if bookmark.book_format == 'pdf':
  105.                     spanTag.insert(0, NavigableString(_('%s<br />Last Page Read: %d (%d%%)') % (strftime(u'%x', timestamp.timetuple()), last_read_location, percent_read)))
  106.                 else:
  107.                     spanTag.insert(0, NavigableString(_('%s<br />Last Page Read: Location %d (%d%%)') % (strftime(u'%x', timestamp.timetuple()), last_read_location, percent_read)))
  108.                 divTag.insert(dtc, spanTag)
  109.                 dtc += 1
  110.                 divTag.insert(dtc, Tag(ka_soup, 'br'))
  111.                 dtc += 1
  112.                 if bookmark.user_notes:
  113.                     user_notes = bookmark.user_notes
  114.                     annotations = []
  115.                     for location in sorted(user_notes):
  116.                         if user_notes[location]['text']:
  117.                             None(annotations.append % (_('<b>Location %d • %s</b><br />%s<br />'), user_notes[location]['displayed_location'], user_notes[location]['type'] if user_notes[location]['type'] == 'Note' else '<i>%s</i>' % user_notes[location]['text']))
  118.                             continue
  119.                         if bookmark.book_format == 'pdf':
  120.                             annotations.append(_('<b>Page %d • %s</b><br />') % (user_notes[location]['displayed_location'], user_notes[location]['type']))
  121.                             continue
  122.                         annotations.append(_('<b>Location %d • %s</b><br />') % (user_notes[location]['displayed_location'], user_notes[location]['type']))
  123.                     
  124.                     for annotation in annotations:
  125.                         divTag.insert(dtc, annotation)
  126.                         dtc += 1
  127.                     
  128.                 
  129.                 ka_soup.insert(0, divTag)
  130.                 return ka_soup
  131.  
  132.             
  133.             def mark_book_as_read(self, id):
  134.                 read_tag = gprefs.get('catalog_epub_mobi_read_tag')
  135.                 if read_tag:
  136.                     self.db.set_tags(id, [
  137.                         read_tag], append = True)
  138.                 
  139.  
  140.             
  141.             def canceled(self):
  142.                 self.pd.hide()
  143.  
  144.             
  145.             def run(self):
  146.                 ignore_tags = set([
  147.                     'Catalog',
  148.                     'Clippings'])
  149.                 for i, id in enumerate(self.am):
  150.                     bm = Device.UserAnnotation(self.am[id][0], self.am[id][1])
  151.                     if bm.type == 'kindle_bookmark':
  152.                         mi = self.db.get_metadata(id, index_is_id = True)
  153.                         user_notes_soup = self.generate_annotation_html(bm.value)
  154.                         if mi.comments:
  155.                             a_offset = mi.comments.find('<div class="user_annotations">')
  156.                             ad_offset = mi.comments.find('<hr class="annotations_divider" />')
  157.                             if a_offset >= 0:
  158.                                 mi.comments = mi.comments[:a_offset]
  159.                             
  160.                             if ad_offset >= 0:
  161.                                 mi.comments = mi.comments[:ad_offset]
  162.                             
  163.                             if set(mi.tags).intersection(ignore_tags):
  164.                                 continue
  165.                             
  166.                             if mi.comments:
  167.                                 hrTag = Tag(user_notes_soup, 'hr')
  168.                                 hrTag['class'] = 'annotations_divider'
  169.                                 user_notes_soup.insert(0, hrTag)
  170.                             
  171.                             mi.comments += user_notes_soup.prettify()
  172.                         else:
  173.                             mi.comments = unicode(user_notes_soup.prettify())
  174.                         self.db.set_comment(id, mi.comments)
  175.                         if bm.value.percent_read >= self.FINISHED_READING_PCT_THRESHOLD:
  176.                             if not set(mi.tags).intersection(ignore_tags):
  177.                                 self.mark_book_as_read(id)
  178.                             
  179.                         
  180.                         self.db.add_format_with_hooks(id, bm.value.bookmark_extension, bm.value.path, index_is_id = True)
  181.                         self.update_progress.emit(i)
  182.                         continue
  183.                     if bm.type == 'kindle_clippings':
  184.                         last_update = 'Last modified %s' % strftime(u'%x %X', bm.value['timestamp'].timetuple())
  185.                         mc_id = list(db.data.parse('title:"My Clippings"'))
  186.                         if mc_id:
  187.                             do_add_format(self.db, mc_id[0], 'TXT', bm.value['path'])
  188.                             mi = self.db.get_metadata(mc_id[0], index_is_id = True)
  189.                             mi.comments = last_update
  190.                             self.db.set_metadata(mc_id[0], mi)
  191.                         else:
  192.                             mi = MetaInformation('My Clippings', authors = [
  193.                                 'Kindle'])
  194.                             mi.tags = [
  195.                                 'Clippings']
  196.                             mi.comments = last_update
  197.                             self.db.add_books([
  198.                                 bm.value['path']], [
  199.                                 'txt'], [
  200.                                 mi])
  201.                     mc_id
  202.                 
  203.                 self.update_done.emit()
  204.                 self.done_callback(self.am.keys())
  205.  
  206.  
  207.         if not job.result:
  208.             return None
  209.         if self.gui.current_view() is not self.gui.library_view:
  210.             return error_dialog(self.gui, _('Use library only'), _('User annotations generated from main library only'), show = True)
  211.         db = self.gui.library_view.model().db
  212.         self._FetchAnnotationsAction__annotation_updater = Updater(self.gui, db, job.result, self.Dispatcher(self.gui.library_view.model().refresh_ids))
  213.         self._FetchAnnotationsAction__annotation_updater.start()
  214.  
  215.  
  216.