Adding works (more or less)

This commit is contained in:
Kovid Goyal 2009-05-15 00:02:32 -07:00
parent 92a1d8c4e7
commit 042841b912
10 changed files with 97 additions and 64 deletions

View File

@ -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)]))

View File

@ -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):

View File

@ -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])

View File

@ -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,

View File

@ -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

View File

@ -1,19 +1,19 @@
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
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?',
'<p>The following tags are used by one or more books. Are you certain you want to delete them?<br>'+ct)
if d.exec_() == QMessageBox.Yes:
if question_dialog(self, _('Are your sure?'),
'<p>'+_('The following tags are used by one or more books. '
'Are you certain you want to delete them?')+'<br>'+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('')

View File

@ -3,7 +3,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
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

View File

@ -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 <a href="http://calibre.kovidgoyal.net/wiki/'
'Changelog">new features</a>. 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))

View File

@ -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()

View File

@ -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: