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

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import os
  5. import shutil
  6. import time
  7. from Queue import Queue, Empty
  8. from threading import Thread
  9. from PyQt4.Qt import QThread, SIGNAL, QObject, QTimer, Qt, QProgressDialog
  10. from calibre.gui2.dialogs.progress import ProgressDialog
  11. from calibre.gui2 import question_dialog, error_dialog, info_dialog
  12. from calibre.ebooks.metadata.opf2 import OPF
  13. from calibre.ebooks.metadata import MetaInformation
  14. from calibre.constants import preferred_encoding, filesystem_encoding
  15. from calibre.utils.config import prefs
  16.  
  17. class DuplicatesAdder(QThread):
  18.     
  19.     def __init__(self, parent, db, duplicates, db_adder):
  20.         QThread.__init__(self, parent)
  21.         self.db = db
  22.         self.db_adder = db_adder
  23.         self.duplicates = duplicates
  24.  
  25.     
  26.     def run(self):
  27.         count = 1
  28.         for mi, cover, formats in self.duplicates:
  29.             formats = _[1]
  30.             id = self.db.create_book_entry(mi, cover = cover, add_duplicates = True)
  31.             self.db_adder.add_formats(id, formats)
  32.             self.db_adder.number_of_books_added += 1
  33.             self.emit(SIGNAL('added(PyQt_PyObject)'), count)
  34.             count += 1
  35.         
  36.         self.emit(SIGNAL('adding_done()'))
  37.  
  38.  
  39.  
  40. class RecursiveFind(QThread):
  41.     
  42.     def __init__(self, parent, db, root, single):
  43.         QThread.__init__(self, parent)
  44.         self.db = db
  45.         self.path = root
  46.         self.single_book_per_directory = single
  47.         self.canceled = False
  48.  
  49.     
  50.     def walk(self, root):
  51.         self.books = []
  52.         for dirpath in os.walk(root):
  53.             if self.canceled:
  54.                 return None
  55.             self.emit(SIGNAL('update(PyQt_PyObject)'), _('Searching in') + ' ' + dirpath[0])
  56.             self.books += list(self.db.find_books_in_directory(dirpath[0], self.single_book_per_directory))
  57.         
  58.  
  59.     
  60.     def run(self):
  61.         root = os.path.abspath(self.path)
  62.         
  63.         try:
  64.             self.walk(root)
  65.         except:
  66.             
  67.             try:
  68.                 if isinstance(root, unicode):
  69.                     root = root.encode(filesystem_encoding)
  70.                 
  71.                 self.walk(root)
  72.             except Exception:
  73.                 err = None
  74.                 import traceback
  75.                 traceback.print_exc()
  76.                 
  77.                 try:
  78.                     msg = unicode(err)
  79.                 except:
  80.                     msg = repr(err)
  81.  
  82.                 self.emit(SIGNAL('found(PyQt_PyObject)'), msg)
  83.                 return None
  84.             
  85.  
  86.  
  87.         self.books = _[1]
  88.  
  89.  
  90.  
  91. class DBAdder(Thread):
  92.     
  93.     def __init__(self, db, ids, nmap):
  94.         self.db = db
  95.         self.ids = dict(**ids)
  96.         self.nmap = dict(**nmap)
  97.         self.end = False
  98.         self.critical = { }
  99.         self.number_of_books_added = 0
  100.         self.duplicates = []
  101.         self.names = []
  102.         self.paths = []
  103.         self.infos = []
  104.         Thread.__init__(self)
  105.         self.daemon = True
  106.         self.input_queue = Queue()
  107.         self.output_queue = Queue()
  108.         self.merged_books = set([])
  109.  
  110.     
  111.     def run(self):
  112.         while not self.end:
  113.             
  114.             try:
  115.                 (id, opf, cover) = self.input_queue.get(True, 0.2)
  116.             except Empty:
  117.                 continue
  118.  
  119.             name = self.nmap.pop(id)
  120.             title = None
  121.             
  122.             try:
  123.                 title = self.add(id, opf, cover, name)
  124.             except:
  125.                 import traceback
  126.                 self.critical[name] = traceback.format_exc()
  127.                 title = name
  128.  
  129.             self.output_queue.put(title)
  130.  
  131.     
  132.     def process_formats(self, opf, formats):
  133.         imp = opf[:-4] + '.import'
  134.         if not os.access(imp, os.R_OK):
  135.             return formats
  136.         fmt_map = { }
  137.         for line in open(imp, 'rb').readlines():
  138.             if ':' not in line:
  139.                 continue
  140.             
  141.             (f, _, p) = line.partition(':')
  142.             fmt_map[f] = p.rstrip()
  143.         
  144.         fmts = []
  145.         for fmt in formats:
  146.             e = os.path.splitext(fmt)[1].replace('.', '').lower()
  147.             fmts.append(fmt_map.get(e, fmt))
  148.             if not os.access(fmts[-1], os.R_OK):
  149.                 fmts[-1] = fmt
  150.                 continue
  151.         
  152.         return fmts
  153.  
  154.     
  155.     def add(self, id, opf, cover, name):
  156.         formats = self.ids.pop(id)
  157.         if opf.endswith('.error'):
  158.             mi = MetaInformation('', [
  159.                 _('Unknown')])
  160.             self.critical[name] = open(opf, 'rb').read().decode('utf-8', 'replace')
  161.         else:
  162.             
  163.             try:
  164.                 mi = OPF(opf).to_book_metadata()
  165.             except:
  166.                 import traceback
  167.                 mi = MetaInformation('', [
  168.                     _('Unknown')])
  169.                 self.critical[name] = traceback.format_exc()
  170.  
  171.         formats = self.process_formats(opf, formats)
  172.         if not mi.title:
  173.             mi.title = os.path.splitext(name)[0]
  174.         
  175.         mi.title = None if isinstance(mi.title, unicode) else mi.title.decode(preferred_encoding, 'replace')
  176.         if mi.application_id == '__calibre_dummy__':
  177.             mi.application_id = None
  178.         
  179.         return mi.title
  180.  
  181.     
  182.     def add_formats(self, id, formats, replace = True):
  183.         for path in formats:
  184.             fmt = os.path.splitext(path)[-1].replace('.', '').upper()
  185.             
  186.             try:
  187.                 f = _[1]
  188.                 self.db.add_format(id, fmt, f, index_is_id = True, notify = False, replace = replace)
  189.             finally:
  190.                 pass
  191.  
  192.         
  193.  
  194.  
  195.  
  196. class Adder(QObject):
  197.     ADD_TIMEOUT = 600
  198.     
  199.     def __init__(self, parent, db, callback, spare_server = None):
  200.         QObject.__init__(self, parent)
  201.         self.pd = ProgressDialog(_('Adding...'), parent = parent)
  202.         self.spare_server = spare_server
  203.         self.db = db
  204.         self.pd.setModal(True)
  205.         self.pd.show()
  206.         self._parent = parent
  207.         self.rfind = None
  208.         self.worker = None
  209.         self.timer = None
  210.         self.callback = callback
  211.         self.callback_called = False
  212.         self.connect(self.pd, SIGNAL('canceled()'), self.canceled)
  213.  
  214.     
  215.     def add_recursive(self, root, single = True):
  216.         self.path = root
  217.         self.pd.set_msg(_('Searching in all sub-directories...'))
  218.         self.pd.set_min(0)
  219.         self.pd.set_max(0)
  220.         self.pd.value = 0
  221.         self.rfind = RecursiveFind(self, self.db, root, single)
  222.         self.connect(self.rfind, SIGNAL('update(PyQt_PyObject)'), self.pd.set_msg, Qt.QueuedConnection)
  223.         self.connect(self.rfind, SIGNAL('found(PyQt_PyObject)'), self.add, Qt.QueuedConnection)
  224.         self.rfind.start()
  225.  
  226.     
  227.     def add(self, books):
  228.         if isinstance(books, basestring):
  229.             error_dialog(self.pd, _('Path error'), _('The specified directory could not be processed.'), det_msg = books, show = True)
  230.             return self.canceled()
  231.         if not books:
  232.             info_dialog(self.pd, _('No books'), _('No books found'), show = True)
  233.             return self.canceled()
  234.         books = [ _[1] if isinstance(b, basestring) else b for b in books ]
  235.         self.rfind = None
  236.         read_metadata = read_metadata
  237.         import calibre.ebooks.metadata.worker
  238.         self.rq = Queue()
  239.         tasks = []
  240.         self.ids = { }
  241.         self.nmap = { }
  242.         self.duplicates = []
  243.         for i, b in enumerate(books):
  244.             tasks.append((i, b))
  245.             self.ids[i] = b
  246.             self.nmap[i] = os.path.basename(b[0])
  247.         
  248.         self.worker = read_metadata(tasks, self.rq, spare_server = self.spare_server)
  249.         self.pd.set_min(0)
  250.         self.pd.set_max(len(self.ids))
  251.         self.pd.value = 0
  252.         self.db_adder = DBAdder(self.db, self.ids, self.nmap)
  253.         self.db_adder.start()
  254.         self.last_added_at = time.time()
  255.         self.entry_count = len(self.ids)
  256.         self.continue_updating = True
  257.         QTimer.singleShot(200, self.update)
  258.  
  259.     
  260.     def canceled(self):
  261.         self.continue_updating = False
  262.         if self.rfind is not None:
  263.             self.rfind.canceled = True
  264.         
  265.         if self.worker is not None:
  266.             self.worker.canceled = True
  267.         
  268.         if hasattr(self, 'db_adder'):
  269.             self.db_adder.end = True
  270.         
  271.         self.pd.hide()
  272.         if not self.callback_called:
  273.             self.callback(self.paths, self.names, self.infos)
  274.             self.callback_called = True
  275.         
  276.  
  277.     
  278.     def duplicates_processed(self):
  279.         self.db_adder.end = True
  280.         if not self.callback_called:
  281.             self.callback(self.paths, self.names, self.infos)
  282.             self.callback_called = True
  283.         
  284.         if hasattr(self, '__p_d'):
  285.             self._Adder__p_d.hide()
  286.         
  287.  
  288.     
  289.     def update(self):
  290.         if self.entry_count <= 0:
  291.             self.continue_updating = False
  292.             self.pd.hide()
  293.             self.process_duplicates()
  294.             return None
  295.         
  296.         try:
  297.             (id, opf, cover) = self.rq.get_nowait()
  298.             self.db_adder.input_queue.put((id, opf, cover))
  299.             self.last_added_at = time.time()
  300.         except Empty:
  301.             self.entry_count <= 0
  302.             self.entry_count <= 0
  303.         except:
  304.             self.entry_count <= 0
  305.  
  306.         
  307.         try:
  308.             title = self.db_adder.output_queue.get_nowait()
  309.             self.pd.value += 1
  310.             self.pd.set_msg(_('Added') + ' ' + title)
  311.             self.last_added_at = time.time()
  312.             self.entry_count -= 1
  313.         except Empty:
  314.             self.entry_count <= 0
  315.             self.entry_count <= 0
  316.         except:
  317.             self.entry_count <= 0
  318.  
  319.         if self.continue_updating:
  320.             QTimer.singleShot(200, self.update)
  321.         
  322.  
  323.     
  324.     def process_duplicates(self):
  325.         duplicates = self.db_adder.duplicates
  326.         if not duplicates:
  327.             return self.duplicates_processed()
  328.         self.pd.hide()
  329.         files = [ x[0].title for x in duplicates ]
  330.         if question_dialog(self._parent, _('Duplicates found!'), _('Books with the same title as the following already exist in the database. Add them anyway?'), '\n'.join(files)):
  331.             pd = QProgressDialog(_('Adding duplicates...'), '', 0, len(duplicates), self._parent)
  332.             pd.setCancelButton(None)
  333.             pd.setValue(0)
  334.             pd.show()
  335.             self._Adder__p_d = pd
  336.             self._Adder__d_a = DuplicatesAdder(self._parent, self.db, duplicates, self.db_adder)
  337.             self.connect(self._Adder__d_a, SIGNAL('added(PyQt_PyObject)'), pd.setValue)
  338.             self.connect(self._Adder__d_a, SIGNAL('adding_done()'), self.duplicates_processed)
  339.             self._Adder__d_a.start()
  340.         else:
  341.             return self.duplicates_processed()
  342.         return []
  343.  
  344.     
  345.     def cleanup(self):
  346.         if hasattr(self, 'pd'):
  347.             self.pd.hide()
  348.         
  349.         if hasattr(self, 'worker') and hasattr(self.worker, 'tdir') and self.worker.tdir is not None:
  350.             if os.path.exists(self.worker.tdir):
  351.                 
  352.                 try:
  353.                     shutil.rmtree(self.worker.tdir)
  354.  
  355.             
  356.         
  357.  
  358.     
  359.     def number_of_books_added(self):
  360.         return getattr(getattr(self, 'db_adder', None), 'number_of_books_added', 0)
  361.  
  362.     number_of_books_added = property(number_of_books_added)
  363.     
  364.     def merged_books(self):
  365.         return getattr(getattr(self, 'db_adder', None), 'merged_books', set([]))
  366.  
  367.     merged_books = property(merged_books)
  368.     
  369.     def critical(self):
  370.         return getattr(getattr(self, 'db_adder', None), 'critical', { })
  371.  
  372.     critical = property(critical)
  373.     
  374.     def paths(self):
  375.         return getattr(getattr(self, 'db_adder', None), 'paths', [])
  376.  
  377.     paths = property(paths)
  378.     
  379.     def names(self):
  380.         return getattr(getattr(self, 'db_adder', None), 'names', [])
  381.  
  382.     names = property(names)
  383.     
  384.     def infos(self):
  385.         return getattr(getattr(self, 'db_adder', None), 'infos', [])
  386.  
  387.     infos = property(infos)
  388.  
  389.  
  390. class Saver(QObject):
  391.     
  392.     def __init__(self, parent, db, callback, rows, path, opts, spare_server = None):
  393.         QObject.__init__(self, parent)
  394.         self.pd = ProgressDialog(_('Saving...'), parent = parent)
  395.         self.spare_server = spare_server
  396.         self.db = db
  397.         self.opts = opts
  398.         self.pd.setModal(True)
  399.         self.pd.show()
  400.         self.pd.set_min(0)
  401.         self._parent = parent
  402.         self.callback = callback
  403.         self.callback_called = False
  404.         self.rq = Queue()
  405.         self.ids = _[1]
  406.         self.pd.set_max(len(self.ids))
  407.         self.pd.value = 0
  408.         self.failures = set([])
  409.         SaveWorker = SaveWorker
  410.         import calibre.ebooks.metadata.worker
  411.         self.worker = SaveWorker(self.rq, db, self.ids, path, self.opts, spare_server = self.spare_server)
  412.         self.pd.canceled_signal.connect(self.canceled)
  413.         self.timer = QTimer(self)
  414.         self.connect(self.timer, SIGNAL('timeout()'), self.update)
  415.         self.timer.start(200)
  416.  
  417.     
  418.     def canceled(self):
  419.         if self.timer is not None:
  420.             self.timer.stop()
  421.         
  422.         if self.worker is not None:
  423.             self.worker.canceled = True
  424.         
  425.         self.pd.hide()
  426.         if not self.callback_called:
  427.             self.callback(self.worker.path, self.failures, self.worker.error)
  428.             self.callback_called = True
  429.         
  430.  
  431.     
  432.     def update(self):
  433.         if not (self.ids) or not self.worker.is_alive():
  434.             self.timer.stop()
  435.             self.pd.hide()
  436.             if not self.callback_called:
  437.                 self.callback(self.worker.path, self.failures, self.worker.error)
  438.                 self.callback_called = True
  439.             
  440.             return None
  441.         
  442.         try:
  443.             (id, title, ok, tb) = self.rq.get_nowait()
  444.         except Empty:
  445.             not self.worker.is_alive()
  446.             not self.worker.is_alive()
  447.             return None
  448.  
  449.         self.pd.value += 1
  450.         self.ids.remove(id)
  451.         self.pd.set_msg(_('Saved') + ' ' + title)
  452.         if not ok:
  453.             self.failures.add((title, tb))
  454.         
  455.  
  456.  
  457.