mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge from trunk
This commit is contained in:
commit
4325a82e82
@ -422,6 +422,33 @@ class MetadataField(object):
|
|||||||
elem = obj.create_metadata_element(self.name, is_dc=self.is_dc)
|
elem = obj.create_metadata_element(self.name, is_dc=self.is_dc)
|
||||||
obj.set_text(elem, self.renderer(val))
|
obj.set_text(elem, self.renderer(val))
|
||||||
|
|
||||||
|
class TitleSortField(MetadataField):
|
||||||
|
|
||||||
|
def __get__(self, obj, type=None):
|
||||||
|
c = self.__real_get__(obj, type)
|
||||||
|
if c is None:
|
||||||
|
matches = obj.title_path(obj.metadata)
|
||||||
|
if matches:
|
||||||
|
for match in matches:
|
||||||
|
ans = match.get('{%s}file-as'%obj.NAMESPACES['opf'], None)
|
||||||
|
if not ans:
|
||||||
|
ans = match.get('file-as', None)
|
||||||
|
if ans:
|
||||||
|
c = ans
|
||||||
|
if not c:
|
||||||
|
c = self.none_is
|
||||||
|
else:
|
||||||
|
c = c.strip()
|
||||||
|
return c
|
||||||
|
|
||||||
|
def __set__(self, obj, val):
|
||||||
|
MetadataField.__set__(self, obj, val)
|
||||||
|
matches = obj.title_path(obj.metadata)
|
||||||
|
if matches:
|
||||||
|
for match in matches:
|
||||||
|
for attr in list(match.attrib):
|
||||||
|
if attr.endswith('file-as'):
|
||||||
|
del match.attrib[attr]
|
||||||
|
|
||||||
def serialize_user_metadata(metadata_elem, all_user_metadata, tail='\n'+(' '*8)):
|
def serialize_user_metadata(metadata_elem, all_user_metadata, tail='\n'+(' '*8)):
|
||||||
from calibre.utils.config import to_json
|
from calibre.utils.config import to_json
|
||||||
@ -490,6 +517,7 @@ class OPF(object): # {{{
|
|||||||
rights = MetadataField('rights')
|
rights = MetadataField('rights')
|
||||||
series = MetadataField('series', is_dc=False)
|
series = MetadataField('series', is_dc=False)
|
||||||
series_index = MetadataField('series_index', is_dc=False, formatter=float, none_is=1)
|
series_index = MetadataField('series_index', is_dc=False, formatter=float, none_is=1)
|
||||||
|
title_sort = TitleSortField('title_sort', is_dc=False)
|
||||||
rating = MetadataField('rating', is_dc=False, formatter=int)
|
rating = MetadataField('rating', is_dc=False, formatter=int)
|
||||||
pubdate = MetadataField('date', formatter=parse_date,
|
pubdate = MetadataField('date', formatter=parse_date,
|
||||||
renderer=isoformat)
|
renderer=isoformat)
|
||||||
@ -776,47 +804,6 @@ class OPF(object): # {{{
|
|||||||
|
|
||||||
return property(fget=fget, fset=fset)
|
return property(fget=fget, fset=fset)
|
||||||
|
|
||||||
@dynamic_property
|
|
||||||
def title_sort(self):
|
|
||||||
|
|
||||||
def fget(self):
|
|
||||||
#first try the title_sort meta tag
|
|
||||||
matches = self.root.xpath('//*[name() = "meta" and starts-with(@name,'
|
|
||||||
'"calibre:title_sort") and @content]')
|
|
||||||
if matches:
|
|
||||||
for elem in matches:
|
|
||||||
return self.get_text(elem)
|
|
||||||
# fallback to file-as
|
|
||||||
matches = self.title_path(self.metadata)
|
|
||||||
if matches:
|
|
||||||
for match in matches:
|
|
||||||
ans = match.get('{%s}file-as'%self.NAMESPACES['opf'], None)
|
|
||||||
if not ans:
|
|
||||||
ans = match.get('file-as', None)
|
|
||||||
if ans:
|
|
||||||
return ans
|
|
||||||
return None
|
|
||||||
|
|
||||||
def fset(self, val):
|
|
||||||
matches = self.root.xpath('//*[name() = "meta" and starts-with(@name,'
|
|
||||||
'"calibre:title_sort") and @content]')
|
|
||||||
if matches:
|
|
||||||
for elem in matches:
|
|
||||||
elem.getparent().remove(elem)
|
|
||||||
matches = self.title_path(self.metadata)
|
|
||||||
if matches:
|
|
||||||
for elem in matches:
|
|
||||||
parent = elem.getparent()
|
|
||||||
attrib = {}
|
|
||||||
attrib['name'] = 'calibre:title_sort'
|
|
||||||
attrib['content'] = val
|
|
||||||
e = elem.makeelement('meta', attrib=attrib)
|
|
||||||
e.tail = '\n'+(' '*8)
|
|
||||||
parent.append(elem)
|
|
||||||
|
|
||||||
return property(fget=fget, fset=fset)
|
|
||||||
|
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def tags(self):
|
def tags(self):
|
||||||
|
|
||||||
@ -1146,8 +1133,6 @@ class OPFCreator(Metadata):
|
|||||||
metadata = M.metadata()
|
metadata = M.metadata()
|
||||||
a = metadata.append
|
a = metadata.append
|
||||||
role = {}
|
role = {}
|
||||||
if self.title_sort:
|
|
||||||
role = {'file-as':self.title_sort}
|
|
||||||
a(DC_ELEM('title', self.title if self.title else _('Unknown'),
|
a(DC_ELEM('title', self.title if self.title else _('Unknown'),
|
||||||
opf_attrs=role))
|
opf_attrs=role))
|
||||||
for i, author in enumerate(self.authors):
|
for i, author in enumerate(self.authors):
|
||||||
@ -1182,6 +1167,8 @@ class OPFCreator(Metadata):
|
|||||||
a(CAL_ELEM('calibre:series', self.series))
|
a(CAL_ELEM('calibre:series', self.series))
|
||||||
if self.series_index is not None:
|
if self.series_index is not None:
|
||||||
a(CAL_ELEM('calibre:series_index', self.format_series_index()))
|
a(CAL_ELEM('calibre:series_index', self.format_series_index()))
|
||||||
|
if self.title_sort:
|
||||||
|
a(CAL_ELEM('calibre:title_sort', self.title_sort))
|
||||||
if self.rating is not None:
|
if self.rating is not None:
|
||||||
a(CAL_ELEM('calibre:rating', str(self.rating)))
|
a(CAL_ELEM('calibre:rating', str(self.rating)))
|
||||||
if self.timestamp is not None:
|
if self.timestamp is not None:
|
||||||
@ -1337,7 +1324,6 @@ def test_m2o():
|
|||||||
mi.author_sort = 'author sort'
|
mi.author_sort = 'author sort'
|
||||||
mi.pubdate = nowf()
|
mi.pubdate = nowf()
|
||||||
mi.language = 'en'
|
mi.language = 'en'
|
||||||
mi.category = 'test'
|
|
||||||
mi.comments = 'what a fun book\n\n'
|
mi.comments = 'what a fun book\n\n'
|
||||||
mi.publisher = 'publisher'
|
mi.publisher = 'publisher'
|
||||||
mi.isbn = 'boooo'
|
mi.isbn = 'boooo'
|
||||||
@ -1352,11 +1338,11 @@ def test_m2o():
|
|||||||
opf = metadata_to_opf(mi)
|
opf = metadata_to_opf(mi)
|
||||||
print opf
|
print opf
|
||||||
newmi = MetaInformation(OPF(StringIO(opf)))
|
newmi = MetaInformation(OPF(StringIO(opf)))
|
||||||
for attr in ('author_sort', 'title_sort', 'comments', 'category',
|
for attr in ('author_sort', 'title_sort', 'comments',
|
||||||
'publisher', 'series', 'series_index', 'rating',
|
'publisher', 'series', 'series_index', 'rating',
|
||||||
'isbn', 'tags', 'cover_data', 'application_id',
|
'isbn', 'tags', 'cover_data', 'application_id',
|
||||||
'language', 'cover',
|
'language', 'cover',
|
||||||
'book_producer', 'timestamp', 'lccn', 'lcc', 'ddc',
|
'book_producer', 'timestamp',
|
||||||
'pubdate', 'rights', 'publication_type'):
|
'pubdate', 'rights', 'publication_type'):
|
||||||
o, n = getattr(mi, attr), getattr(newmi, attr)
|
o, n = getattr(mi, attr), getattr(newmi, attr)
|
||||||
if o != n and o.strip() != n.strip():
|
if o != n and o.strip() != n.strip():
|
||||||
@ -1458,4 +1444,6 @@ def test_user_metadata():
|
|||||||
print opf.render()
|
print opf.render()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
test_user_metadata()
|
#test_user_metadata()
|
||||||
|
#test_m2o()
|
||||||
|
test()
|
||||||
|
@ -48,10 +48,10 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0" colspan="3">
|
<item row="6" column="0" colspan="3">
|
||||||
<widget class="XPathEdit" name="opt_page_breaks_before" native="true"/>
|
<widget class="XPathEdit" name="opt_page_breaks_before" native="true"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0" colspan="3">
|
<item row="7" column="0" colspan="3">
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
@ -77,6 +77,16 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="4" column="0" colspan="3">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>The header and footer removal options have been replaced by the Search & Replace options. Click the Search & Replace category in the bar to the left to use these options. Leave the replace field blank and enter your header/footer removal regexps into the search field.</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user