KG updates

This commit is contained in:
GRiker 2010-06-17 12:50:45 -06:00
commit d675e36b19
16 changed files with 47 additions and 44 deletions

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 KiB

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

View File

@ -12,15 +12,14 @@ from calibre import fit_image
from calibre.constants import isosx, iswindows from calibre.constants import isosx, iswindows
from calibre.devices.errors import UserFeedback from calibre.devices.errors import UserFeedback
from calibre.devices.interface import DevicePlugin from calibre.devices.interface import DevicePlugin
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag from calibre.ebooks.BeautifulSoup import BeautifulSoup
from calibre.ebooks.metadata import MetaInformation from calibre.ebooks.metadata import MetaInformation
from calibre.ebooks.metadata.epub import set_metadata from calibre.ebooks.metadata.epub import set_metadata
from calibre.library.server.utils import strftime from calibre.library.server.utils import strftime
from calibre.ptempfile import PersistentTemporaryFile
from calibre.utils.config import Config, config_dir from calibre.utils.config import Config, config_dir
from calibre.utils.date import fromtimestamp, isoformat, now, parse_date, strptime from calibre.utils.date import isoformat, now, parse_date
from calibre.utils.logging import Log from calibre.utils.logging import Log
from calibre.utils.zipfile import safe_replace, ZipFile from calibre.utils.zipfile import ZipFile
from PIL import Image as PILImage from PIL import Image as PILImage
@ -34,7 +33,6 @@ if isosx:
if iswindows: if iswindows:
import pythoncom, win32com.client import pythoncom, win32com.client
from calibre.ebooks.BeautifulSoup import BeautifulSoup
class ITUNES(DevicePlugin): class ITUNES(DevicePlugin):
@ -1665,8 +1663,6 @@ class ITUNES(DevicePlugin):
''' '''
assumes pythoncom wrapper assumes pythoncom wrapper
''' '''
# if DEBUG:
# self.log.info(" ITUNES._get_device_books_playlist()")
if iswindows: if iswindows:
if 'iPod' in self.sources: if 'iPod' in self.sources:
pl = None pl = None
@ -1709,11 +1705,6 @@ class ITUNES(DevicePlugin):
if update_md: if update_md:
self._update_epub_metadata(fpath, metadata) self._update_epub_metadata(fpath, metadata)
# if DEBUG:
# self.log.info(" metadata before rewrite: '{0[0]}' '{0[1]}' '{0[2]}'".format(self._dump_epub_metadata(fpath)))
# self._update_epub_metadata(fpath, metadata)
# if DEBUG:
# self.log.info(" metadata after rewrite: '{0[0]}' '{0[1]}' '{0[2]}'".format(self._dump_epub_metadata(fpath)))
return fpath return fpath
def _get_library_books(self): def _get_library_books(self):
@ -2132,21 +2123,6 @@ class ITUNES(DevicePlugin):
# Refresh epub metadata # Refresh epub metadata
with open(fpath,'r+b') as zfo: with open(fpath,'r+b') as zfo:
'''
# Touch the timestamp to force a recache
if metadata.timestamp:
if DEBUG:
self.log.info(" old timestamp: %s" % metadata.timestamp)
old_ts = metadata.timestamp
metadata.timestamp = datetime.datetime(old_ts.year, old_ts.month, old_ts.day, old_ts.hour,
old_ts.minute, old_ts.second, old_ts.microsecond+1, old_ts.tzinfo)
if DEBUG:
self.log.info(" new timestamp: %s" % metadata.timestamp)
else:
metadata.timestamp = isoformat(now())
if DEBUG:
self.log.info(" add timestamp: %s" % metadata.timestamp)
'''
# Touch the OPF timestamp # Touch the OPF timestamp
zf_opf = ZipFile(fpath,'r') zf_opf = ZipFile(fpath,'r')
fnames = zf_opf.namelist() fnames = zf_opf.namelist()
@ -2186,7 +2162,7 @@ class ITUNES(DevicePlugin):
if iswindows and metadata.series: if iswindows and metadata.series:
metadata.tags = None metadata.tags = None
set_metadata(zfo,metadata) set_metadata(zfo, metadata, update_timestamp=True)
def _update_device(self, msg='', wait=True): def _update_device(self, msg='', wait=True):
''' '''

View File

@ -55,6 +55,7 @@ class PRS505(USBMS):
SUPPORTS_SUB_DIRS = True SUPPORTS_SUB_DIRS = True
MUST_READ_METADATA = True MUST_READ_METADATA = True
SUPPORTS_USE_AUTHOR_SORT = True
EBOOK_DIR_MAIN = 'database/media/books' EBOOK_DIR_MAIN = 'database/media/books'
EXTRA_CUSTOMIZATION_MESSAGE = _('Comma separated list of metadata fields ' EXTRA_CUSTOMIZATION_MESSAGE = _('Comma separated list of metadata fields '
@ -125,7 +126,7 @@ class PRS505(USBMS):
d = os.path.dirname(paths[source_id]) d = os.path.dirname(paths[source_id])
if not os.path.exists(d): if not os.path.exists(d):
os.makedirs(d) os.makedirs(d)
return XMLCache(paths, prefixes) return XMLCache(paths, prefixes, self.settings().use_author_sort)
def books(self, oncard=None, end_session=True): def books(self, oncard=None, end_session=True):
debug_print('PRS505: starting fetching books for card', oncard) debug_print('PRS505: starting fetching books for card', oncard)

View File

@ -60,12 +60,13 @@ def uuid():
class XMLCache(object): class XMLCache(object):
def __init__(self, paths, prefixes): def __init__(self, paths, prefixes, use_author_sort):
if DEBUG: if DEBUG:
debug_print('Building XMLCache...') debug_print('Building XMLCache...')
pprint(paths) pprint(paths)
self.paths = paths self.paths = paths
self.prefixes = prefixes self.prefixes = prefixes
self.use_author_sort = use_author_sort
# Parse XML files {{{ # Parse XML files {{{
parser = etree.XMLParser(recover=True) parser = etree.XMLParser(recover=True)
@ -434,7 +435,10 @@ class XMLCache(object):
if not ts: if not ts:
ts = title_sort(title) ts = title_sort(title)
record.set('titleSorter', ts) record.set('titleSorter', ts)
record.set('author', authors_to_string(book.authors)) if self.use_author_sort and book.author_sort is not None:
record.set('author', book.author_sort)
else:
record.set('author', authors_to_string(book.authors))
ext = os.path.splitext(path)[1] ext = os.path.splitext(path)[1]
if ext: if ext:
ext = ext[1:].lower() ext = ext[1:].lower()

View File

@ -80,6 +80,7 @@ class Device(DeviceConfig, DevicePlugin):
SUPPORTS_SUB_DIRS = False SUPPORTS_SUB_DIRS = False
MUST_READ_METADATA = False MUST_READ_METADATA = False
SUPPORTS_USE_AUTHOR_SORT = False
EBOOK_DIR_MAIN = '' EBOOK_DIR_MAIN = ''
EBOOK_DIR_CARD_A = '' EBOOK_DIR_CARD_A = ''

View File

@ -32,6 +32,8 @@ class DeviceConfig(object):
help=_('Place files in sub directories if the device supports them')) help=_('Place files in sub directories if the device supports them'))
c.add_opt('read_metadata', default=True, c.add_opt('read_metadata', default=True,
help=_('Read metadata from files on device')) help=_('Read metadata from files on device'))
c.add_opt('use_author_sort', default=False,
help=_('Use author sort instead of author'))
c.add_opt('save_template', default=cls._default_save_template(), c.add_opt('save_template', default=cls._default_save_template(),
help=_('Template to control how books are saved')) help=_('Template to control how books are saved'))
c.add_opt('extra_customization', c.add_opt('extra_customization',
@ -47,7 +49,8 @@ class DeviceConfig(object):
def config_widget(cls): def config_widget(cls):
from calibre.gui2.device_drivers.configwidget import ConfigWidget from calibre.gui2.device_drivers.configwidget import ConfigWidget
cw = ConfigWidget(cls.settings(), cls.FORMATS, cls.SUPPORTS_SUB_DIRS, cw = ConfigWidget(cls.settings(), cls.FORMATS, cls.SUPPORTS_SUB_DIRS,
cls.MUST_READ_METADATA, cls.EXTRA_CUSTOMIZATION_MESSAGE) cls.MUST_READ_METADATA, cls.SUPPORTS_USE_AUTHOR_SORT,
cls.EXTRA_CUSTOMIZATION_MESSAGE)
return cw return cw
@classmethod @classmethod
@ -58,6 +61,8 @@ class DeviceConfig(object):
proxy['use_subdirs'] = config_widget.use_subdirs() proxy['use_subdirs'] = config_widget.use_subdirs()
if not cls.MUST_READ_METADATA: if not cls.MUST_READ_METADATA:
proxy['read_metadata'] = config_widget.read_metadata() proxy['read_metadata'] = config_widget.read_metadata()
if cls.SUPPORTS_USE_AUTHOR_SORT:
proxy['use_author_sort'] = config_widget.use_author_sort()
if cls.EXTRA_CUSTOMIZATION_MESSAGE: if cls.EXTRA_CUSTOMIZATION_MESSAGE:
ec = unicode(config_widget.opt_extra_customization.text()).strip() ec = unicode(config_widget.opt_extra_customization.text()).strip()
if not ec: if not ec:

View File

@ -299,7 +299,7 @@ class USBMS(CLI, Device):
def replfunc(match): def replfunc(match):
if match.group(1) in ['title', 'series', 'series_index', 'isbn']: if match.group(1) in ['title', 'series', 'series_index', 'isbn']:
return '(?P<' + match.group(1) + '>.+?)' return '(?P<' + match.group(1) + '>.+?)'
elif match.group(1) == 'authors': elif match.group(1) in ['authors', 'author_sort']:
return '(?P<author>.+?)' return '(?P<author>.+?)'
else: else:
return '(.+?)' return '(.+?)'

View File

@ -182,7 +182,7 @@ def get_metadata(stream, extract_cover=True):
def get_quick_metadata(stream): def get_quick_metadata(stream):
return get_metadata(stream, False) return get_metadata(stream, False)
def set_metadata(stream, mi, apply_null=False): def set_metadata(stream, mi, apply_null=False, update_timestamp=False):
stream.seek(0) stream.seek(0)
reader = OCFZipReader(stream, root=os.getcwdu()) reader = OCFZipReader(stream, root=os.getcwdu())
mi = MetaInformation(mi) mi = MetaInformation(mi)
@ -196,6 +196,8 @@ def set_metadata(stream, mi, apply_null=False):
reader.opf.tags = [] reader.opf.tags = []
if not getattr(mi, 'isbn', None): if not getattr(mi, 'isbn', None):
reader.opf.isbn = None reader.opf.isbn = None
if update_timestamp and mi.timestamp is not None:
reader.opf.timestamp = mi.timestamp
newopf = StringIO(reader.opf.render()) newopf = StringIO(reader.opf.render())
safe_replace(stream, reader.container[OPF.MIMETYPE], newopf) safe_replace(stream, reader.container[OPF.MIMETYPE], newopf)

View File

@ -920,7 +920,7 @@ class OPF(object):
for attr in ('title', 'authors', 'author_sort', 'title_sort', for attr in ('title', 'authors', 'author_sort', 'title_sort',
'publisher', 'series', 'series_index', 'rating', 'publisher', 'series', 'series_index', 'rating',
'isbn', 'language', 'tags', 'category', 'comments', 'isbn', 'language', 'tags', 'category', 'comments',
'pubdate','timestamp'): 'pubdate'):
val = getattr(mi, attr, None) val = getattr(mi, attr, None)
if val is not None and val != [] and val != (None, None): if val is not None and val != [] and val != (None, None):
setattr(self, attr, val) setattr(self, attr, val)

View File

@ -11,7 +11,8 @@ from calibre.gui2.device_drivers.configwidget_ui import Ui_ConfigWidget
class ConfigWidget(QWidget, Ui_ConfigWidget): class ConfigWidget(QWidget, Ui_ConfigWidget):
def __init__(self, settings, all_formats, supports_subdirs, def __init__(self, settings, all_formats, supports_subdirs,
must_read_metadata, extra_customization_message): must_read_metadata, supports_use_author_sort,
extra_customization_message):
QWidget.__init__(self) QWidget.__init__(self)
Ui_ConfigWidget.__init__(self) Ui_ConfigWidget.__init__(self)
@ -38,6 +39,10 @@ class ConfigWidget(QWidget, Ui_ConfigWidget):
self.opt_read_metadata.setChecked(self.settings.read_metadata) self.opt_read_metadata.setChecked(self.settings.read_metadata)
else: else:
self.opt_read_metadata.hide() self.opt_read_metadata.hide()
if supports_use_author_sort:
self.opt_use_author_sort.setChecked(self.settings.use_author_sort)
else:
self.opt_use_author_sort.hide()
if extra_customization_message: if extra_customization_message:
self.extra_customization_label.setText(extra_customization_message) self.extra_customization_label.setText(extra_customization_message)
if settings.extra_customization: if settings.extra_customization:
@ -69,3 +74,6 @@ class ConfigWidget(QWidget, Ui_ConfigWidget):
def read_metadata(self): def read_metadata(self):
return self.opt_read_metadata.isChecked() return self.opt_read_metadata.isChecked()
def use_author_sort(self):
return self.opt_use_author_sort.isChecked()

View File

@ -90,7 +90,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0"> <item row="3" column="0">
<widget class="QCheckBox" name="opt_use_author_sort">
<property name="text">
<string>Use author sort for author</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="extra_customization_label"> <widget class="QLabel" name="extra_customization_label">
<property name="text"> <property name="text">
<string>Extra customization</string> <string>Extra customization</string>
@ -103,10 +110,10 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="0"> <item row="7" column="0">
<widget class="QLineEdit" name="opt_extra_customization"/> <widget class="QLineEdit" name="opt_extra_customization"/>
</item> </item>
<item row="3" column="0"> <item row="4" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>Save &amp;template:</string> <string>Save &amp;template:</string>
@ -116,7 +123,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="5" column="0">
<widget class="QLineEdit" name="opt_save_template"/> <widget class="QLineEdit" name="opt_save_template"/>
</item> </item>
</layout> </layout>

View File

@ -163,8 +163,7 @@ class ToolbarMixin(object): # {{{
self.convert_menu = cm self.convert_menu = cm
pm = QMenu() pm = QMenu()
ap = self.action_preferences pm.addAction(QIcon(I('config.svg')), _('Preferences'), self.do_config)
pm.addAction(ap)
pm.addAction(QIcon(I('wizard.svg')), _('Run welcome wizard'), pm.addAction(QIcon(I('wizard.svg')), _('Run welcome wizard'),
self.run_wizard) self.run_wizard)
self.action_preferences.setMenu(pm) self.action_preferences.setMenu(pm)

View File

@ -84,12 +84,12 @@ class DownloadMetadata(Thread):
if mi.isbn: if mi.isbn:
args['isbn'] = mi.isbn args['isbn'] = mi.isbn
else: else:
if not mi.title: if not mi.title or mi.title == _('Unknown'):
self.failures[id] = \ self.failures[id] = \
(str(id), _('Book has neither title nor ISBN')) (str(id), _('Book has neither title nor ISBN'))
continue continue
args['title'] = mi.title args['title'] = mi.title
if mi.authors: if mi.authors and mi.authors[0] != _('Unknown'):
args['author'] = mi.authors[0] args['author'] = mi.authors[0]
if self.key: if self.key:
args['isbndb_key'] = self.key args['isbndb_key'] = self.key