diff --git a/src/calibre/ebooks/metadata/meta.py b/src/calibre/ebooks/metadata/meta.py index a176c12c2b..1460a97eee 100644 --- a/src/calibre/ebooks/metadata/meta.py +++ b/src/calibre/ebooks/metadata/meta.py @@ -28,6 +28,14 @@ def path_to_ext(path): return os.path.splitext(path)[1][1:].lower() def metadata_from_formats(formats): + try: + return _metadata_from_formats(formats) + except: + mi = metadata_from_filename(formats[0]) + if not mi.authors: + mi.authors = [_('Unknown')] + +def _metadata_from_formats(formats): mi = MetaInformation(None, None) formats.sort(cmp=lambda x,y: cmp(METADATA_PRIORITIES[path_to_ext(x)], METADATA_PRIORITIES[path_to_ext(y)])) diff --git a/src/calibre/ebooks/metadata/opf2.py b/src/calibre/ebooks/metadata/opf2.py index 4b7648d81f..c735fbe940 100644 --- a/src/calibre/ebooks/metadata/opf2.py +++ b/src/calibre/ebooks/metadata/opf2.py @@ -387,6 +387,8 @@ class MetadataField(object): ans = self.formatter(ans) except: return None + if hasattr(ans, 'strip'): + ans = ans.strip() return ans def __get__(self, obj, type=None): diff --git a/src/calibre/ebooks/metadata/worker.py b/src/calibre/ebooks/metadata/worker.py index 1ae77a1fba..66a992df98 100644 --- a/src/calibre/ebooks/metadata/worker.py +++ b/src/calibre/ebooks/metadata/worker.py @@ -8,13 +8,18 @@ __docformat__ = 'restructuredtext en' from threading import Thread from Queue import Empty -import os, time +import os, time, sys from calibre.utils.ipc.job import ParallelJob from calibre.utils.ipc.server import Server from calibre.ptempfile import PersistentTemporaryDirectory from calibre import prints + +def debug(*args): + prints(*args) + sys.stdout.flush() + def read_metadata_(task, tdir, notification=lambda x,y:x): from calibre.ebooks.metadata.meta import metadata_from_formats from calibre.ebooks.metadata.opf2 import OPFCreator @@ -44,7 +49,7 @@ class Progress(object): def __call__(self, id): cover = os.path.join(self.tdir, str(id)) if not os.path.exists(cover): cover = None - self.result_queue.put((id, os.path.join(self.tdir, id+'.opf'), cover)) + self.result_queue.put((id, os.path.join(self.tdir, '%s.opf'%id), cover)) class ReadMetadata(Thread): @@ -57,7 +62,10 @@ class ReadMetadata(Thread): def run(self): - jobs, ids = set([]), set([id for id, p in self.tasks]) + jobs, ids = set([]), set([]) + for t in self.tasks: + for b in t: + ids.add(b[0]) progress = Progress(self.result_queue, self.tdir) server = Server() for i, task in enumerate(self.tasks): @@ -74,22 +82,26 @@ class ReadMetadata(Thread): while True: try: id = job.notifications.get_nowait()[-1] - progress(id) - ids.remove(id) + if id in ids: + progress(id) + ids.remove(id) except Empty: break job.update() if not job.is_finished: running = True + if not running: break + server.close() + time.sleep(1) + if self.canceled: - server.close() - time.sleep(1) return for id in ids: + print 11111111, id progress(id) for job in jobs: @@ -99,9 +111,8 @@ class ReadMetadata(Thread): os.remove(job.log_path) -def read_metadata(paths, result_queue): +def read_metadata(paths, result_queue, chunk=50): tasks = [] - chunk = 50 pos = 0 while pos < len(paths): tasks.append(paths[pos:pos+chunk]) diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 2afa65e690..2a5a02495a 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -122,7 +122,7 @@ def question_dialog(parent, title, msg, det_msg=''): parent) d.setDetailedText(det_msg) d.setIconPixmap(QPixmap(':/images/dialog_information.svg')) - return d + return d.exec_() == QMessageBox.Yes def info_dialog(parent, title, msg, det_msg='', show=False): d = QMessageBox(QMessageBox.Information, title, msg, QMessageBox.NoButton, diff --git a/src/calibre/gui2/add.py b/src/calibre/gui2/add.py index d467bde3e0..d0aeb3b300 100644 --- a/src/calibre/gui2/add.py +++ b/src/calibre/gui2/add.py @@ -2,12 +2,12 @@ UI for adding books to the database ''' import os -from threading import Queue, Empty +from Queue import Queue, Empty -from PyQt4.Qt import QThread, SIGNAL, QObject, QTimer +from PyQt4.Qt import QThread, SIGNAL, QObject, QTimer, Qt from calibre.gui2.dialogs.progress import ProgressDialog -from calibre.gui2 import warning_dialog +from calibre.gui2 import question_dialog from calibre.ebooks.metadata.opf2 import OPF from calibre.ebooks.metadata import MetaInformation from calibre.constants import preferred_encoding @@ -17,11 +17,13 @@ class RecursiveFind(QThread): def __init__(self, parent, db, root, single): QThread.__init__(self, parent) self.db = db - self.path = root, self.single_book_per_directory = single + self.path = root + self.single_book_per_directory = single self.canceled = False def run(self): root = os.path.abspath(self.path) + self.books = [] for dirpath in os.walk(root): if self.canceled: return @@ -47,6 +49,7 @@ class Adder(QObject): self.number_of_books_added = 0 self.rfind = self.worker = self.timer = None self.callback = callback + self.callback_called = False self.infos, self.paths, self.names = [], [], [] self.connect(self.pd, SIGNAL('canceled()'), self.canceled) @@ -58,9 +61,10 @@ class Adder(QObject): self.pd.value = 0 self.rfind = RecursiveFind(self, self.db, root, single) self.connect(self.rfind, SIGNAL('update(PyQt_PyObject)'), - self.pd.set_msg) + self.pd.set_msg, Qt.QueuedConnection) self.connect(self.rfind, SIGNAL('found(PyQt_PyObject)'), - self.add) + self.add, Qt.QueuedConnection) + self.rfind.start() def add(self, books): books = [[b] if isinstance(b, basestring) else b for b in books] @@ -71,10 +75,10 @@ class Adder(QObject): self.ids = {} self.nmap = {} self.duplicates = [] - for i, b in books: + for i, b in enumerate(books): tasks.append((i, b)) self.ids[i] = b - self.nmap = os.path.basename(b[0]) + self.nmap[i] = os.path.basename(b[0]) self.worker = read_metadata(tasks, self.rq) self.pd.set_min(0) self.pd.set_max(len(self.ids)) @@ -97,6 +101,10 @@ class Adder(QObject): if self.worker is not None: self.worker.canceled = True self.pd.hide() + if not self.callback_called: + self.callback(self.paths, self.names, self.infos) + self.callback_called = True + def update(self): @@ -104,7 +112,9 @@ class Adder(QObject): self.timer.stop() self.process_duplicates() self.pd.hide() - self.callback(self.paths, self.names, self.infos) + if not self.callback_called: + self.callback(self.paths, self.names, self.infos) + self.callback_called = True return try: @@ -139,15 +149,16 @@ class Adder(QObject): 'tags':mi.tags if mi.tags else []}) def process_duplicates(self): + if not self.duplicates: + return files = [x[0].title for x in self.duplicates] - d = warning_dialog(_('Duplicates found!'), + 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), parent=self._parent) - if d.exec_() == d.Accepted: + '\n'.join(files)): for mi, cover, formats in self.duplicates: id = self.db.create_book_entry(mi, cover=cover, - add_duplicates=False) + add_duplicates=True) self.add_formats(id, formats) self.number_of_books_added += 1 diff --git a/src/calibre/gui2/dialogs/tag_editor.py b/src/calibre/gui2/dialogs/tag_editor.py index b50649f761..5d17f3a693 100644 --- a/src/calibre/gui2/dialogs/tag_editor.py +++ b/src/calibre/gui2/dialogs/tag_editor.py @@ -1,19 +1,19 @@ __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal ' from PyQt4.QtCore import SIGNAL, Qt -from PyQt4.QtGui import QDialog, QMessageBox +from PyQt4.QtGui import QDialog from calibre.gui2.dialogs.tag_editor_ui import Ui_TagEditor from calibre.gui2 import qstring_to_unicode from calibre.gui2 import question_dialog, error_dialog class TagEditor(QDialog, Ui_TagEditor): - + def __init__(self, window, db, index=None): QDialog.__init__(self, window) Ui_TagEditor.__init__(self) self.setupUi(self) - + self.db = db self.index = index if self.index is not None: @@ -27,16 +27,16 @@ class TagEditor(QDialog, Ui_TagEditor): self.applied_tags.addItem(tag) else: tags = [] - + self.tags = tags - + all_tags = [tag for tag in self.db.all_tags()] all_tags = list(set(all_tags)) all_tags.sort() for tag in all_tags: if tag not in tags: self.available_tags.addItem(tag) - + self.connect(self.apply_button, SIGNAL('clicked()'), self.apply_tags) self.connect(self.unapply_button, SIGNAL('clicked()'), self.unapply_tags) self.connect(self.add_tag_button, SIGNAL('clicked()'), self.add_tag) @@ -44,8 +44,8 @@ class TagEditor(QDialog, Ui_TagEditor): self.connect(self.add_tag_input, SIGNAL('returnPressed()'), self.add_tag) self.connect(self.available_tags, SIGNAL('itemActivated(QListWidgetItem*)'), self.apply_tags) self.connect(self.applied_tags, SIGNAL('itemActivated(QListWidgetItem*)'), self.unapply_tags) - - + + def delete_tags(self, item=None): confirms, deletes = [], [] items = self.available_tags.selectedItems() if item is None else [item] @@ -56,47 +56,47 @@ class TagEditor(QDialog, Ui_TagEditor): if self.db.is_tag_used(qstring_to_unicode(item.text())): confirms.append(item) else: - deletes.append(item) + deletes.append(item) if confirms: ct = ', '.join([qstring_to_unicode(item.text()) for item in confirms]) - d = question_dialog(self, 'Are your sure?', - '

The following tags are used by one or more books. Are you certain you want to delete them?
'+ct) - if d.exec_() == QMessageBox.Yes: + if question_dialog(self, _('Are your sure?'), + '

'+_('The following tags are used by one or more books. ' + 'Are you certain you want to delete them?')+'
'+ct): deletes += confirms - + for item in deletes: self.db.delete_tag(qstring_to_unicode(item.text())) self.available_tags.takeItem(self.available_tags.row(item)) - - + + def apply_tags(self, item=None): - items = self.available_tags.selectedItems() if item is None else [item] + items = self.available_tags.selectedItems() if item is None else [item] for item in items: tag = qstring_to_unicode(item.text()) self.tags.append(tag) self.available_tags.takeItem(self.available_tags.row(item)) - + self.tags.sort() self.applied_tags.clear() for tag in self.tags: self.applied_tags.addItem(tag) - - - + + + def unapply_tags(self, item=None): - items = self.applied_tags.selectedItems() if item is None else [item] + items = self.applied_tags.selectedItems() if item is None else [item] for item in items: tag = qstring_to_unicode(item.text()) self.tags.remove(tag) self.available_tags.addItem(tag) - + self.tags.sort() self.applied_tags.clear() for tag in self.tags: self.applied_tags.addItem(tag) - + self.available_tags.sortItems() - + def add_tag(self): tags = qstring_to_unicode(self.add_tag_input.text()).split(',') for tag in tags: @@ -105,10 +105,10 @@ class TagEditor(QDialog, Ui_TagEditor): self.available_tags.takeItem(self.available_tags.row(item)) if tag not in self.tags: self.tags.append(tag) - + self.tags.sort() self.applied_tags.clear() for tag in self.tags: self.applied_tags.addItem(tag) - + self.add_tag_input.setText('') diff --git a/src/calibre/gui2/dialogs/user_profiles.py b/src/calibre/gui2/dialogs/user_profiles.py index c46b4ba392..6a4a3275a8 100644 --- a/src/calibre/gui2/dialogs/user_profiles.py +++ b/src/calibre/gui2/dialogs/user_profiles.py @@ -3,7 +3,7 @@ __copyright__ = '2008, Kovid Goyal ' import time, os from PyQt4.QtCore import SIGNAL, QUrl -from PyQt4.QtGui import QMessageBox, QDesktopServices +from PyQt4.QtGui import QDesktopServices from calibre.web.feeds.recipes import compile_recipe from calibre.web.feeds.news import AutomaticNewsRecipe @@ -175,9 +175,9 @@ class %(classname)s(%(base_class)s): try: self.available_profiles.add_item(title, (title, profile), replace=False) except ValueError: - d = question_dialog(self, _('Replace recipe?'), - _('A custom recipe named %s already exists. Do you want to replace it?')%title) - if d.exec_() == QMessageBox.Yes: + if question_dialog(self, _('Replace recipe?'), + _('A custom recipe named %s already exists. Do you want to ' + 'replace it?')%title): self.available_profiles.add_item(title, (title, profile), replace=True) else: return @@ -207,9 +207,9 @@ class %(classname)s(%(base_class)s): try: self.available_profiles.add_item(title, (title, r.text), replace=False) except ValueError: - d = question_dialog(self, _('Replace recipe?'), - _('A custom recipe named %s already exists. Do you want to replace it?')%title) - if d.exec_() == QMessageBox.Yes: + if question_dialog(self, _('Replace recipe?'), + _('A custom recipe named %s already exists. Do you ' + 'want to replace it?')%title): self.available_profiles.add_item(title, (title, r.text), replace=True) else: return @@ -231,9 +231,9 @@ class %(classname)s(%(base_class)s): try: self.available_profiles.add_item(title, (title, src), replace=False) except ValueError: - d = question_dialog(self, _('Replace recipe?'), - _('A custom recipe named %s already exists. Do you want to replace it?')%title) - if d.exec_() == QMessageBox.Yes: + if question_dialog(self, _('Replace recipe?'), + _('A custom recipe named %s already exists. Do you want to ' + 'replace it?')%title): self.available_profiles.add_item(title, (title, src), replace=True) else: return diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index 9724426460..940b2709b6 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -1576,12 +1576,11 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): self.vanity.update() if config.get('new_version_notification') and \ dynamic.get('update to version %s'%version, True): - d = question_dialog(self, _('Update available'), + if question_dialog(self, _('Update available'), _('%s has been updated to version %s. ' 'See the new features. Visit the download pa' - 'ge?')%(__appname__, version)) - if d.exec_() == QMessageBox.Yes: + 'ge?')%(__appname__, version)): url = 'http://calibre.kovidgoyal.net/download_'+\ ('windows' if iswindows else 'osx' if isosx else 'linux') QDesktopServices.openUrl(QUrl(url)) diff --git a/src/calibre/utils/ipc/server.py b/src/calibre/utils/ipc/server.py index 3dec90a644..0d7f307a9d 100644 --- a/src/calibre/utils/ipc/server.py +++ b/src/calibre/utils/ipc/server.py @@ -166,8 +166,8 @@ class Server(Thread): if len(self.pool) + len(self.workers) < self.pool_size: try: self.pool.append(self.launch_worker()) - except: - break + except Exception, err: + pass if len(self.pool) > 0 and len(self.waiting_jobs) > 0: job = self.waiting_jobs.pop() diff --git a/src/calibre/utils/ipc/worker.py b/src/calibre/utils/ipc/worker.py index 6ebecd15e3..82bfff0cbf 100644 --- a/src/calibre/utils/ipc/worker.py +++ b/src/calibre/utils/ipc/worker.py @@ -65,6 +65,8 @@ def main(): resultf = unhexlify(os.environ['CALIBRE_WORKER_RESULT']) with closing(Client(address, authkey=key)) as conn: name, args, kwargs = conn.recv() + #print (name, args, kwargs) + #sys.stdout.flush() func, notification = get_func(name) notifier = Progress(conn) if notification: