mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Sync to trunk.
This commit is contained in:
commit
b6bb7237a8
@ -30,3 +30,4 @@ nbproject/
|
|||||||
.project
|
.project
|
||||||
.pydevproject
|
.pydevproject
|
||||||
.settings/
|
.settings/
|
||||||
|
*.DS_Store
|
||||||
|
@ -21,14 +21,19 @@ class Fronda(BasicNewsRecipe):
|
|||||||
|
|
||||||
feeds = [(u'Infformacje', u'http://fronda.pl/news/feed')]
|
feeds = [(u'Infformacje', u'http://fronda.pl/news/feed')]
|
||||||
|
|
||||||
keep_only_tags = [dict(name='h1', attrs={'class':'big'}),
|
keep_only_tags = [dict(name='h2', attrs={'class':'news_title'}),
|
||||||
dict(name='ul', attrs={'class':'about clear'}),
|
dict(name='div', attrs={'class':'naglowek_tresc'}),
|
||||||
dict(name='div', attrs={'class':'content'})]
|
dict(name='div', attrs={'id':'czytaj'}) ]
|
||||||
|
|
||||||
|
remove_tags = [dict(name='a', attrs={'class':'print'})]
|
||||||
|
|
||||||
preprocess_regexps = [
|
preprocess_regexps = [
|
||||||
(re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in
|
(re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in
|
||||||
[ (r'<a href="#" class="print">Drukuj</a>', lambda match: ''),
|
[ (r'<p><a href="http://fronda.pl/sklepy">.*</a></p>', lambda match: ''),
|
||||||
(r'<p><a href="http://fronda.pl/sklepy">.*</a></p>', lambda match: ''),
|
|
||||||
(r'<p><a href="http://fronda.pl/pasaz">.*</a></p>', lambda match: ''),
|
(r'<p><a href="http://fronda.pl/pasaz">.*</a></p>', lambda match: ''),
|
||||||
(r'<h3><strong>W.* lektury.*</a></p></div>', lambda match: '</div>'),
|
(r'<h3><strong>W.* lektury.*</a></p></div>', lambda match: '</div>'),
|
||||||
(r'<h3>Zobacz t.*?</div>', lambda match: '</div>') ]
|
(r'<h3>Zobacz t.*?</div>', lambda match: '</div>'),
|
||||||
|
(r'<p[^>]*> </p>', lambda match: ''),
|
||||||
|
(r'<p><span style=".*?"><br /></span></p> ', lambda match: ''),
|
||||||
|
(r'<a style=\'float:right;margin-top:3px;\' href="http://www.facebook.com/share.php?.*?</a>', lambda match: '')]
|
||||||
]
|
]
|
||||||
|
BIN
recipes/icons/rzeczpospolita.png
Normal file
BIN
recipes/icons/rzeczpospolita.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
recipes/icons/ziuaveche.png
Normal file
BIN
recipes/icons/ziuaveche.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 554 B |
36
recipes/korea_herald.recipe
Normal file
36
recipes/korea_herald.recipe
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2011, Seongkyoun Yoo <Seongkyoun.yoo at gmail.com>'
|
||||||
|
'''
|
||||||
|
Profile to download KoreaHerald
|
||||||
|
'''
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class KoreaHerald(BasicNewsRecipe):
|
||||||
|
title = u'KoreaHerald'
|
||||||
|
language = 'en'
|
||||||
|
description = u'Korea Herald News articles'
|
||||||
|
__author__ = 'Seongkyoun Yoo'
|
||||||
|
oldest_article = 10
|
||||||
|
recursions = 3
|
||||||
|
max_articles_per_feed = 10
|
||||||
|
no_stylesheets = True
|
||||||
|
keep_only_tags = [
|
||||||
|
dict(id=['contentLeft', '_article'])
|
||||||
|
]
|
||||||
|
|
||||||
|
remove_tags = [
|
||||||
|
dict(name='iframe'),
|
||||||
|
dict(name='div', attrs={'class':['left','htit2', 'navigation','banner_txt','banner_img']}),
|
||||||
|
dict(name='ul', attrs={'class':['link_icon', 'flow_icon','detailTextAD110113']}),
|
||||||
|
]
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
('All News','http://www.koreaherald.com/rss/020000000000.xml'),
|
||||||
|
('National','http://www.koreaherald.com/rss/020100000000.xml'),
|
||||||
|
('Business','http://www.koreaherald.com/rss/020200000000.xml'),
|
||||||
|
('Life&Style','http://www.koreaherald.com/rss/020300000000.xml'),
|
||||||
|
('Entertainment','http://www.koreaherald.com/rss/020400000000.xml'),
|
||||||
|
('Sports','http://www.koreaherald.com/rss/020500000000.xml'),
|
||||||
|
('Opinion','http://www.koreaherald.com/rss/020600000000.xml'),
|
||||||
|
('English Cafe','http://www.koreaherald.com/rss/021000000000.xml'),
|
||||||
|
]
|
@ -2,7 +2,7 @@ from calibre.web.feeds.news import BasicNewsRecipe
|
|||||||
|
|
||||||
class RzeczpospolitaRecipe(BasicNewsRecipe):
|
class RzeczpospolitaRecipe(BasicNewsRecipe):
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__author__ = 'kwetal'
|
__author__ = u'kwetal and Tomasz Dlugosz'
|
||||||
language = 'pl'
|
language = 'pl'
|
||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
@ -38,6 +38,8 @@ class RzeczpospolitaRecipe(BasicNewsRecipe):
|
|||||||
remove_tags.append(dict(name = 'div', attrs = {'class' : 'clr'}))
|
remove_tags.append(dict(name = 'div', attrs = {'class' : 'clr'}))
|
||||||
remove_tags.append(dict(name = 'div', attrs = {'id' : 'share_bottom'}))
|
remove_tags.append(dict(name = 'div', attrs = {'id' : 'share_bottom'}))
|
||||||
remove_tags.append(dict(name = 'div', attrs = {'id' : 'copyright_law'}))
|
remove_tags.append(dict(name = 'div', attrs = {'id' : 'copyright_law'}))
|
||||||
|
remove_tags.append(dict(name = 'div', attrs = {'class' : 'more'}))
|
||||||
|
remove_tags.append(dict(name = 'div', attrs = {'class' : 'editorPicks'}))
|
||||||
|
|
||||||
extra_css = '''
|
extra_css = '''
|
||||||
body {font-family: verdana, arial, helvetica, geneva, sans-serif ;}
|
body {font-family: verdana, arial, helvetica, geneva, sans-serif ;}
|
||||||
@ -48,6 +50,13 @@ class RzeczpospolitaRecipe(BasicNewsRecipe):
|
|||||||
.fot{font-size: x-small; color: #666666;}
|
.fot{font-size: x-small; color: #666666;}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
def skip_ad_pages(self, soup):
|
||||||
|
if ('advertisement' in soup.find('title').string.lower()):
|
||||||
|
href = soup.find('a').get('href')
|
||||||
|
return self.index_to_soup(href, raw=True)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
def print_version(self, url):
|
def print_version(self, url):
|
||||||
start, sep, rest = url.rpartition('/')
|
start, sep, rest = url.rpartition('/')
|
||||||
forget, sep, index = rest.rpartition(',')
|
forget, sep, index = rest.rpartition(',')
|
||||||
|
@ -1,17 +1,12 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
|
||||||
__copyright__ = '2009, Gerhard Aigner <gerhard.aigner at gmail.com>'
|
|
||||||
|
|
||||||
|
|
||||||
import re
|
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
class TelepolisNews(BasicNewsRecipe):
|
class TelepolisNews(BasicNewsRecipe):
|
||||||
title = u'Telepolis (News+Artikel)'
|
title = u'Telepolis (News+Artikel)'
|
||||||
__author__ = 'Gerhard Aigner'
|
__author__ = 'syntaxis'
|
||||||
publisher = 'Heise Zeitschriften Verlag GmbH & Co KG'
|
publisher = 'Heise Zeitschriften Verlag GmbH & Co KG'
|
||||||
description = 'News from telepolis'
|
description = 'News from Telepolis'
|
||||||
category = 'news'
|
category = 'news'
|
||||||
oldest_article = 7
|
oldest_article = 7
|
||||||
max_articles_per_feed = 100
|
max_articles_per_feed = 100
|
||||||
@ -20,14 +15,19 @@ class TelepolisNews(BasicNewsRecipe):
|
|||||||
encoding = "utf-8"
|
encoding = "utf-8"
|
||||||
language = 'de'
|
language = 'de'
|
||||||
|
|
||||||
use_embedded_content =False
|
|
||||||
remove_empty_feeds = True
|
remove_empty_feeds = True
|
||||||
|
|
||||||
preprocess_regexps = [(re.compile(r'<a[^>]*>', re.DOTALL|re.IGNORECASE), lambda match: ''),
|
|
||||||
(re.compile(r'</a>', re.DOTALL|re.IGNORECASE), lambda match: ''),]
|
|
||||||
|
|
||||||
keep_only_tags = [dict(name = 'td',attrs={'class':'bloghead'}),dict(name = 'td',attrs={'class':'blogfliess'})]
|
|
||||||
remove_tags = [dict(name='img'), dict(name='td',attrs={'class':'blogbottom'}), dict(name='td',attrs={'class':'forum'})]
|
keep_only_tags = [dict(name = 'div',attrs={'class':'head'}),dict(name = 'div',attrs={'class':'leftbox'}),dict(name='td',attrs={'class':'strict'})]
|
||||||
|
remove_tags = [ dict(name='td',attrs={'class':'blogbottom'}),
|
||||||
|
dict(name='div',attrs={'class':'forum'}), dict(name='div',attrs={'class':'social'}),dict(name='div',attrs={'class':'blog-letter p-news'}),
|
||||||
|
dict(name='div',attrs={'class':'blog-sub'}),dict(name='div',attrs={'class':'version-div'}),dict(name='div',attrs={'id':'breadcrumb'})
|
||||||
|
,dict(attrs={'class':'tp-url'}),dict(attrs={'class':'blog-name entry_'}) ]
|
||||||
|
|
||||||
|
remove_tags_after = [dict(name='span', attrs={'class':['breadcrumb']})]
|
||||||
|
|
||||||
|
|
||||||
feeds = [(u'News', u'http://www.heise.de/tp/news-atom.xml')]
|
feeds = [(u'News', u'http://www.heise.de/tp/news-atom.xml')]
|
||||||
|
|
||||||
@ -39,15 +39,8 @@ class TelepolisNews(BasicNewsRecipe):
|
|||||||
|
|
||||||
html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"'
|
html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"'
|
||||||
|
|
||||||
def get_article_url(self, article):
|
|
||||||
'''if the linked article is of kind artikel don't take it'''
|
|
||||||
if (article.link.count('artikel') > 1) :
|
|
||||||
return None
|
|
||||||
return article.link
|
|
||||||
|
|
||||||
def preprocess_html(self, soup):
|
def preprocess_html(self, soup):
|
||||||
mtag = '<meta http-equiv="Content-Type" content="text/html; charset=' + self.encoding + '">'
|
mtag = '<meta http-equiv="Content-Type" content="text/html; charset=' + self.encoding + '">'
|
||||||
soup.head.insert(0,mtag)
|
soup.head.insert(0,mtag)
|
||||||
return soup
|
return soup
|
||||||
|
|
||||||
|
|
||||||
|
53
recipes/ziuaveche.recipe
Normal file
53
recipes/ziuaveche.recipe
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = u'2011, Silviu Cotoar\u0103'
|
||||||
|
'''
|
||||||
|
ziuaveche.ro
|
||||||
|
'''
|
||||||
|
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class ZiuaVeche(BasicNewsRecipe):
|
||||||
|
title = u'Ziua Veche'
|
||||||
|
__author__ = u'Silviu Cotoar\u0103'
|
||||||
|
description = 'Cotidian online'
|
||||||
|
publisher = 'Ziua Veche'
|
||||||
|
oldest_article = 5
|
||||||
|
language = 'ro'
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
no_stylesheets = True
|
||||||
|
use_embedded_content = False
|
||||||
|
category = 'Ziare,Cotidiane,Stiri'
|
||||||
|
encoding = 'utf-8'
|
||||||
|
cover_url = 'http://www.ziuaveche.ro/wp-content/themes/tema/images/zv-logo-alb-old.png'
|
||||||
|
|
||||||
|
conversion_options = {
|
||||||
|
'comments' : description
|
||||||
|
,'tags' : category
|
||||||
|
,'language' : language
|
||||||
|
,'publisher' : publisher
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
keep_only_tags = [
|
||||||
|
dict(name='div', attrs={'id':'singlePost'})
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
remove_tags = [
|
||||||
|
dict(name='div', attrs={'id':'LikePluginPagelet'})
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
remove_tags_after = [
|
||||||
|
dict(name='div', attrs={'id':'LikePluginPagelet'})
|
||||||
|
]
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
(u'Feeds', u'http://www.ziuaveche.ro/feed/rss')
|
||||||
|
]
|
||||||
|
|
||||||
|
def preprocess_html(self, soup):
|
||||||
|
return self.adeify_images(soup)
|
@ -449,7 +449,7 @@ class CatalogPlugin(Plugin): # {{{
|
|||||||
['author_sort','authors','comments','cover','formats',
|
['author_sort','authors','comments','cover','formats',
|
||||||
'id','isbn','ondevice','pubdate','publisher','rating',
|
'id','isbn','ondevice','pubdate','publisher','rating',
|
||||||
'series_index','series','size','tags','timestamp',
|
'series_index','series','size','tags','timestamp',
|
||||||
'title','uuid'])
|
'title_sort','title','uuid'])
|
||||||
all_custom_fields = set(db.custom_field_keys())
|
all_custom_fields = set(db.custom_field_keys())
|
||||||
all_fields = all_std_fields.union(all_custom_fields)
|
all_fields = all_std_fields.union(all_custom_fields)
|
||||||
|
|
||||||
|
@ -203,9 +203,11 @@ class ITUNES(DriverBase):
|
|||||||
# 0x1294 iPhone 3GS
|
# 0x1294 iPhone 3GS
|
||||||
# 0x1297 iPhone 4
|
# 0x1297 iPhone 4
|
||||||
# 0x129a iPad
|
# 0x129a iPad
|
||||||
# 0x12a2 iPad2
|
# 0x129f iPad2 (WiFi)
|
||||||
|
# 0x12a2 iPad2 (GSM)
|
||||||
|
# 0x12a3 iPad2 (CDMA)
|
||||||
VENDOR_ID = [0x05ac]
|
VENDOR_ID = [0x05ac]
|
||||||
PRODUCT_ID = [0x1292,0x1293,0x1294,0x1297,0x1299,0x129a,0x12a2]
|
PRODUCT_ID = [0x1292,0x1293,0x1294,0x1297,0x1299,0x129a,0x129f,0x12a2,0x12a3]
|
||||||
BCD = [0x01]
|
BCD = [0x01]
|
||||||
|
|
||||||
# Plugboard ID
|
# Plugboard ID
|
||||||
|
@ -68,9 +68,9 @@ class USER_DEFINED(USBMS):
|
|||||||
'is prepended to any send_to_device template') + '</p>',
|
'is prepended to any send_to_device template') + '</p>',
|
||||||
]
|
]
|
||||||
EXTRA_CUSTOMIZATION_DEFAULT = [
|
EXTRA_CUSTOMIZATION_DEFAULT = [
|
||||||
'0x0000',
|
'0xffff',
|
||||||
'0x0000',
|
'0xffff',
|
||||||
'0x0000',
|
'0xffff',
|
||||||
None,
|
None,
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
|
@ -68,7 +68,8 @@ def check_command_line_options(parser, args, log):
|
|||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
|
|
||||||
output = args[2]
|
output = args[2]
|
||||||
if output.startswith('.') and output != '.':
|
if output.startswith('.') and (output != '.' and not
|
||||||
|
output.startswith('..')):
|
||||||
output = os.path.splitext(os.path.basename(input))[0]+output
|
output = os.path.splitext(os.path.basename(input))[0]+output
|
||||||
output = os.path.abspath(output)
|
output = os.path.abspath(output)
|
||||||
|
|
||||||
|
@ -338,7 +338,7 @@ class Amazon(Source):
|
|||||||
q['field-author'] = ' '.join(author_tokens)
|
q['field-author'] = ' '.join(author_tokens)
|
||||||
|
|
||||||
if not ('field-keywords' in q or 'field-isbn' in q or
|
if not ('field-keywords' in q or 'field-isbn' in q or
|
||||||
('field-title' in q and 'field-author' in q)):
|
('field-title' in q)):
|
||||||
# Insufficient metadata to make an identify query
|
# Insufficient metadata to make an identify query
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -212,6 +212,9 @@ class Source(Plugin):
|
|||||||
def is_customizable(self):
|
def is_customizable(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def customization_help(self):
|
||||||
|
return 'This plugin can only be customized using the GUI'
|
||||||
|
|
||||||
def config_widget(self):
|
def config_widget(self):
|
||||||
from calibre.gui2.metadata.config import ConfigWidget
|
from calibre.gui2.metadata.config import ConfigWidget
|
||||||
return ConfigWidget(self)
|
return ConfigWidget(self)
|
||||||
@ -288,10 +291,10 @@ class Source(Plugin):
|
|||||||
parts = parts[1:] + parts[:1]
|
parts = parts[1:] + parts[:1]
|
||||||
for tok in parts:
|
for tok in parts:
|
||||||
tok = remove_pat.sub('', tok).strip()
|
tok = remove_pat.sub('', tok).strip()
|
||||||
if len(tok) > 2 and tok.lower() not in ('von', ):
|
if len(tok) > 2 and tok.lower() not in ('von', 'van',
|
||||||
|
_('Unknown').lower()):
|
||||||
yield tok
|
yield tok
|
||||||
|
|
||||||
|
|
||||||
def get_title_tokens(self, title, strip_joiners=True, strip_subtitle=False):
|
def get_title_tokens(self, title, strip_joiners=True, strip_subtitle=False):
|
||||||
'''
|
'''
|
||||||
Take a title and return a list of tokens useful for an AND search query.
|
Take a title and return a list of tokens useful for an AND search query.
|
||||||
|
@ -20,6 +20,9 @@ class GenerateCatalogAction(InterfaceAction):
|
|||||||
action_spec = (_('Create a catalog of the books in your calibre library'), 'catalog.png', 'Catalog builder', None)
|
action_spec = (_('Create a catalog of the books in your calibre library'), 'catalog.png', 'Catalog builder', None)
|
||||||
dont_add_to = frozenset(['menubar-device', 'toolbar-device', 'context-menu-device'])
|
dont_add_to = frozenset(['menubar-device', 'toolbar-device', 'context-menu-device'])
|
||||||
|
|
||||||
|
def genesis(self):
|
||||||
|
self.qaction.triggered.connect(self.generate_catalog)
|
||||||
|
|
||||||
def generate_catalog(self):
|
def generate_catalog(self):
|
||||||
rows = self.gui.library_view.selectionModel().selectedRows()
|
rows = self.gui.library_view.selectionModel().selectedRows()
|
||||||
if not rows or len(rows) < 2:
|
if not rows or len(rows) < 2:
|
||||||
|
@ -439,6 +439,7 @@ def populate_metadata_page(layout, db, book_id, bulk=False, two_column=False, pa
|
|||||||
w = widget_factory(dt, col)
|
w = widget_factory(dt, col)
|
||||||
ans.append(w)
|
ans.append(w)
|
||||||
for c in range(0, len(w.widgets), 2):
|
for c in range(0, len(w.widgets), 2):
|
||||||
|
w.widgets[c].setWordWrap(True)
|
||||||
w.widgets[c].setBuddy(w.widgets[c+1])
|
w.widgets[c].setBuddy(w.widgets[c+1])
|
||||||
layout.addWidget(w.widgets[c], row, column)
|
layout.addWidget(w.widgets[c], row, column)
|
||||||
layout.addWidget(w.widgets[c+1], row, column+1)
|
layout.addWidget(w.widgets[c+1], row, column+1)
|
||||||
|
@ -19,17 +19,23 @@ class MessageBox(QDialog, Ui_Dialog): # {{{
|
|||||||
INFO = 2
|
INFO = 2
|
||||||
QUESTION = 3
|
QUESTION = 3
|
||||||
|
|
||||||
def __init__(self, type_, title, msg, det_msg='', show_copy_button=True,
|
def __init__(self, type_, title, msg,
|
||||||
parent=None):
|
det_msg='',
|
||||||
|
q_icon=None,
|
||||||
|
show_copy_button=True,
|
||||||
|
parent=None):
|
||||||
QDialog.__init__(self, parent)
|
QDialog.__init__(self, parent)
|
||||||
icon = {
|
if q_icon is None:
|
||||||
self.ERROR : 'error',
|
icon = {
|
||||||
self.WARNING: 'warning',
|
self.ERROR : 'error',
|
||||||
self.INFO: 'information',
|
self.WARNING: 'warning',
|
||||||
self.QUESTION: 'question',
|
self.INFO: 'information',
|
||||||
}[type_]
|
self.QUESTION: 'question',
|
||||||
icon = 'dialog_%s.png'%icon
|
}[type_]
|
||||||
self.icon = QIcon(I(icon))
|
icon = 'dialog_%s.png'%icon
|
||||||
|
self.icon = QIcon(I(icon))
|
||||||
|
else:
|
||||||
|
self.icon = q_icon
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
|
||||||
self.setWindowTitle(title)
|
self.setWindowTitle(title)
|
||||||
@ -44,7 +50,6 @@ class MessageBox(QDialog, Ui_Dialog): # {{{
|
|||||||
self.bb.ActionRole)
|
self.bb.ActionRole)
|
||||||
self.ctc_button.clicked.connect(self.copy_to_clipboard)
|
self.ctc_button.clicked.connect(self.copy_to_clipboard)
|
||||||
|
|
||||||
|
|
||||||
self.show_det_msg = _('Show &details')
|
self.show_det_msg = _('Show &details')
|
||||||
self.hide_det_msg = _('Hide &details')
|
self.hide_det_msg = _('Hide &details')
|
||||||
self.det_msg_toggle = self.bb.addButton(self.show_det_msg, self.bb.ActionRole)
|
self.det_msg_toggle = self.bb.addButton(self.show_det_msg, self.bb.ActionRole)
|
||||||
|
@ -10,7 +10,7 @@ __docformat__ = 'restructuredtext en'
|
|||||||
import textwrap, re, os
|
import textwrap, re, os
|
||||||
|
|
||||||
from PyQt4.Qt import (Qt, QDateEdit, QDate, pyqtSignal, QMessageBox,
|
from PyQt4.Qt import (Qt, QDateEdit, QDate, pyqtSignal, QMessageBox,
|
||||||
QIcon, QToolButton, QWidget, QLabel, QGridLayout,
|
QIcon, QToolButton, QWidget, QLabel, QGridLayout, QApplication,
|
||||||
QDoubleSpinBox, QListWidgetItem, QSize, QPixmap,
|
QDoubleSpinBox, QListWidgetItem, QSize, QPixmap,
|
||||||
QPushButton, QSpinBox, QLineEdit, QSizePolicy)
|
QPushButton, QSpinBox, QLineEdit, QSizePolicy)
|
||||||
|
|
||||||
@ -1037,6 +1037,13 @@ class IdentifiersEdit(QLineEdit): # {{{
|
|||||||
self.setToolTip(tt+extra)
|
self.setToolTip(tt+extra)
|
||||||
self.setStyleSheet('QLineEdit { background-color: %s }'%col)
|
self.setStyleSheet('QLineEdit { background-color: %s }'%col)
|
||||||
|
|
||||||
|
def paste_isbn(self):
|
||||||
|
text = unicode(QApplication.clipboard().text()).strip()
|
||||||
|
if text:
|
||||||
|
vals = self.current_val
|
||||||
|
vals['isbn'] = text
|
||||||
|
self.current_val = vals
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
class PublisherEdit(MultiCompleteComboBox): # {{{
|
class PublisherEdit(MultiCompleteComboBox): # {{{
|
||||||
@ -1119,7 +1126,7 @@ class DateEdit(QDateEdit): # {{{
|
|||||||
@dynamic_property
|
@dynamic_property
|
||||||
def current_val(self):
|
def current_val(self):
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return qt_to_dt(self.date())
|
return qt_to_dt(self.date(), as_utc=False)
|
||||||
def fset(self, val):
|
def fset(self, val):
|
||||||
if val is None:
|
if val is None:
|
||||||
val = UNDEFINED_DATE
|
val = UNDEFINED_DATE
|
||||||
|
@ -31,6 +31,7 @@ class MetadataSingleDialogBase(ResizableDialog):
|
|||||||
view_format = pyqtSignal(object, object)
|
view_format = pyqtSignal(object, object)
|
||||||
cc_two_column = tweaks['metadata_single_use_2_cols_for_custom_fields']
|
cc_two_column = tweaks['metadata_single_use_2_cols_for_custom_fields']
|
||||||
one_line_comments_toolbar = False
|
one_line_comments_toolbar = False
|
||||||
|
use_toolbutton_for_config_metadata = True
|
||||||
|
|
||||||
def __init__(self, db, parent=None):
|
def __init__(self, db, parent=None):
|
||||||
self.db = db
|
self.db = db
|
||||||
@ -69,7 +70,11 @@ class MetadataSingleDialogBase(ResizableDialog):
|
|||||||
self.setLayout(self.l)
|
self.setLayout(self.l)
|
||||||
self.l.setMargin(0)
|
self.l.setMargin(0)
|
||||||
self.l.addWidget(self.scroll_area)
|
self.l.addWidget(self.scroll_area)
|
||||||
self.l.addWidget(self.button_box)
|
ll = self.button_box_layout = QHBoxLayout()
|
||||||
|
self.l.addLayout(ll)
|
||||||
|
ll.addSpacing(10)
|
||||||
|
ll.addWidget(self.button_box)
|
||||||
|
ll.addSpacing(10)
|
||||||
|
|
||||||
self.setWindowIcon(QIcon(I('edit_input.png')))
|
self.setWindowIcon(QIcon(I('edit_input.png')))
|
||||||
self.setWindowTitle(_('Edit Metadata'))
|
self.setWindowTitle(_('Edit Metadata'))
|
||||||
@ -125,6 +130,13 @@ class MetadataSingleDialogBase(ResizableDialog):
|
|||||||
'Swap the author and title'))
|
'Swap the author and title'))
|
||||||
self.swap_title_author_button.clicked.connect(self.swap_title_author)
|
self.swap_title_author_button.clicked.connect(self.swap_title_author)
|
||||||
|
|
||||||
|
self.manage_authors_button = QToolButton(self)
|
||||||
|
self.manage_authors_button.setIcon(QIcon(I('user_profile.png')))
|
||||||
|
self.manage_authors_button.setToolTip('<p>' + _(
|
||||||
|
'Manage authors. Use to rename authors and correct '
|
||||||
|
'individual author\'s sort values') + '</p>')
|
||||||
|
self.manage_authors_button.clicked.connect(self.authors.manage_authors)
|
||||||
|
|
||||||
self.series = SeriesEdit(self)
|
self.series = SeriesEdit(self)
|
||||||
self.remove_unused_series_button = QToolButton(self)
|
self.remove_unused_series_button = QToolButton(self)
|
||||||
self.remove_unused_series_button.setToolTip(
|
self.remove_unused_series_button.setToolTip(
|
||||||
@ -161,6 +173,12 @@ class MetadataSingleDialogBase(ResizableDialog):
|
|||||||
self.clear_identifiers_button = QToolButton(self)
|
self.clear_identifiers_button = QToolButton(self)
|
||||||
self.clear_identifiers_button.setIcon(QIcon(I('trash.png')))
|
self.clear_identifiers_button.setIcon(QIcon(I('trash.png')))
|
||||||
self.clear_identifiers_button.clicked.connect(self.identifiers.clear)
|
self.clear_identifiers_button.clicked.connect(self.identifiers.clear)
|
||||||
|
self.paste_isbn_button = QToolButton(self)
|
||||||
|
self.paste_isbn_button.setToolTip('<p>' +
|
||||||
|
_('Paste the contents of the clipboard into the '
|
||||||
|
'identifiers box prefixed with isbn:') + '</p>')
|
||||||
|
self.paste_isbn_button.setIcon(QIcon(I('edit-paste.png')))
|
||||||
|
self.paste_isbn_button.clicked.connect(self.identifiers.paste_isbn)
|
||||||
|
|
||||||
self.publisher = PublisherEdit(self)
|
self.publisher = PublisherEdit(self)
|
||||||
self.basic_metadata_widgets.append(self.publisher)
|
self.basic_metadata_widgets.append(self.publisher)
|
||||||
@ -176,7 +194,12 @@ class MetadataSingleDialogBase(ResizableDialog):
|
|||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
self.fetch_metadata_button.setFont(font)
|
self.fetch_metadata_button.setFont(font)
|
||||||
|
|
||||||
self.config_metadata_button = QToolButton(self)
|
if self.use_toolbutton_for_config_metadata:
|
||||||
|
self.config_metadata_button = QToolButton(self)
|
||||||
|
self.config_metadata_button.setIcon(QIcon(I('config.png')))
|
||||||
|
else:
|
||||||
|
self.config_metadata_button = QPushButton(self)
|
||||||
|
self.config_metadata_button.setText(_('Configure download metadata'))
|
||||||
self.config_metadata_button.setIcon(QIcon(I('config.png')))
|
self.config_metadata_button.setIcon(QIcon(I('config.png')))
|
||||||
self.config_metadata_button.clicked.connect(self.configure_metadata)
|
self.config_metadata_button.clicked.connect(self.configure_metadata)
|
||||||
self.config_metadata_button.setToolTip(
|
self.config_metadata_button.setToolTip(
|
||||||
@ -499,7 +522,8 @@ class MetadataSingleDialog(MetadataSingleDialogBase): # {{{
|
|||||||
sto(one, two)
|
sto(one, two)
|
||||||
sto(two, three)
|
sto(two, three)
|
||||||
|
|
||||||
tl.addWidget(self.swap_title_author_button, 0, 0, 2, 1)
|
tl.addWidget(self.swap_title_author_button, 0, 0, 1, 1)
|
||||||
|
tl.addWidget(self.manage_authors_button, 1, 0, 1, 1)
|
||||||
|
|
||||||
create_row(0, self.title, self.deduce_title_sort_button, self.title_sort)
|
create_row(0, self.title, self.deduce_title_sort_button, self.title_sort)
|
||||||
sto(self.title_sort, self.authors)
|
sto(self.title_sort, self.authors)
|
||||||
@ -508,6 +532,7 @@ class MetadataSingleDialog(MetadataSingleDialogBase): # {{{
|
|||||||
create_row(2, self.series, self.remove_unused_series_button,
|
create_row(2, self.series, self.remove_unused_series_button,
|
||||||
self.series_index, icon='trash.png')
|
self.series_index, icon='trash.png')
|
||||||
sto(self.series_index, self.swap_title_author_button)
|
sto(self.series_index, self.swap_title_author_button)
|
||||||
|
sto(self.swap_title_author_button, self.manage_authors_button)
|
||||||
|
|
||||||
tl.addWidget(self.formats_manager, 0, 6, 3, 1)
|
tl.addWidget(self.formats_manager, 0, 6, 3, 1)
|
||||||
|
|
||||||
@ -518,7 +543,7 @@ class MetadataSingleDialog(MetadataSingleDialogBase): # {{{
|
|||||||
self.tabs[0].gb = gb = QGroupBox(_('Change cover'), self)
|
self.tabs[0].gb = gb = QGroupBox(_('Change cover'), self)
|
||||||
gb.l = l = QGridLayout()
|
gb.l = l = QGridLayout()
|
||||||
gb.setLayout(l)
|
gb.setLayout(l)
|
||||||
sto(self.swap_title_author_button, self.cover.buttons[0])
|
sto(self.manage_authors_button, self.cover.buttons[0])
|
||||||
for i, b in enumerate(self.cover.buttons[:3]):
|
for i, b in enumerate(self.cover.buttons[:3]):
|
||||||
l.addWidget(b, 0, i, 1, 1)
|
l.addWidget(b, 0, i, 1, 1)
|
||||||
sto(b, self.cover.buttons[i+1])
|
sto(b, self.cover.buttons[i+1])
|
||||||
@ -532,10 +557,16 @@ class MetadataSingleDialog(MetadataSingleDialogBase): # {{{
|
|||||||
w.setLayout(w.l)
|
w.setLayout(w.l)
|
||||||
l.setMargin(0)
|
l.setMargin(0)
|
||||||
self.splitter.addWidget(w)
|
self.splitter.addWidget(w)
|
||||||
def create_row2(row, widget, button=None):
|
def create_row2(row, widget, button=None, front_button=None):
|
||||||
row += 1
|
row += 1
|
||||||
ql = BuddyLabel(widget)
|
ql = BuddyLabel(widget)
|
||||||
l.addWidget(ql, row, 0, 1, 1)
|
if front_button:
|
||||||
|
ltl = QHBoxLayout()
|
||||||
|
ltl.addWidget(front_button)
|
||||||
|
ltl.addWidget(ql)
|
||||||
|
l.addLayout(ltl, row, 0, 1, 1)
|
||||||
|
else:
|
||||||
|
l.addWidget(ql, row, 0, 1, 1)
|
||||||
l.addWidget(widget, row, 1, 1, 2 if button is None else 1)
|
l.addWidget(widget, row, 1, 1, 2 if button is None else 1)
|
||||||
if button is not None:
|
if button is not None:
|
||||||
l.addWidget(button, row, 2, 1, 1)
|
l.addWidget(button, row, 2, 1, 1)
|
||||||
@ -550,8 +581,10 @@ class MetadataSingleDialog(MetadataSingleDialogBase): # {{{
|
|||||||
create_row2(1, self.rating)
|
create_row2(1, self.rating)
|
||||||
sto(self.rating, self.tags)
|
sto(self.rating, self.tags)
|
||||||
create_row2(2, self.tags, self.tags_editor_button)
|
create_row2(2, self.tags, self.tags_editor_button)
|
||||||
sto(self.tags_editor_button, self.identifiers)
|
sto(self.tags_editor_button, self.paste_isbn_button)
|
||||||
create_row2(3, self.identifiers, self.clear_identifiers_button)
|
sto(self.paste_isbn_button, self.identifiers)
|
||||||
|
create_row2(3, self.identifiers, self.clear_identifiers_button,
|
||||||
|
front_button=self.paste_isbn_button)
|
||||||
sto(self.clear_identifiers_button, self.timestamp)
|
sto(self.clear_identifiers_button, self.timestamp)
|
||||||
create_row2(4, self.timestamp, self.timestamp.clear_button)
|
create_row2(4, self.timestamp, self.timestamp.clear_button)
|
||||||
sto(self.timestamp.clear_button, self.pubdate)
|
sto(self.timestamp.clear_button, self.pubdate)
|
||||||
@ -589,6 +622,7 @@ class MetadataSingleDialogAlt1(MetadataSingleDialogBase): # {{{
|
|||||||
|
|
||||||
cc_two_column = False
|
cc_two_column = False
|
||||||
one_line_comments_toolbar = True
|
one_line_comments_toolbar = True
|
||||||
|
use_toolbutton_for_config_metadata = False
|
||||||
|
|
||||||
on_drag_enter = pyqtSignal()
|
on_drag_enter = pyqtSignal()
|
||||||
|
|
||||||
@ -624,13 +658,11 @@ class MetadataSingleDialogAlt1(MetadataSingleDialogBase): # {{{
|
|||||||
self.tabs[0].l.addWidget(gb, 0, 0, 1, 1)
|
self.tabs[0].l.addWidget(gb, 0, 0, 1, 1)
|
||||||
gb.setLayout(tl)
|
gb.setLayout(tl)
|
||||||
|
|
||||||
self.button_box.addButton(self.fetch_metadata_button,
|
self.button_box_layout.insertWidget(1, self.fetch_metadata_button)
|
||||||
QDialogButtonBox.ActionRole)
|
self.button_box_layout.insertWidget(2, self.config_metadata_button)
|
||||||
self.config_metadata_button.setToolButtonStyle(Qt.ToolButtonTextOnly)
|
sto(self.button_box, self.fetch_metadata_button)
|
||||||
self.config_metadata_button.setText(_('Configure metadata downloading'))
|
sto(self.fetch_metadata_button, self.config_metadata_button)
|
||||||
self.button_box.addButton(self.config_metadata_button,
|
sto(self.config_metadata_button, self.title)
|
||||||
QDialogButtonBox.ActionRole)
|
|
||||||
sto(self.button_box, self.title)
|
|
||||||
|
|
||||||
def create_row(row, widget, tab_to, button=None, icon=None, span=1):
|
def create_row(row, widget, tab_to, button=None, icon=None, span=1):
|
||||||
ql = BuddyLabel(widget)
|
ql = BuddyLabel(widget)
|
||||||
@ -648,6 +680,8 @@ class MetadataSingleDialogAlt1(MetadataSingleDialogBase): # {{{
|
|||||||
sto(widget, tab_to)
|
sto(widget, tab_to)
|
||||||
|
|
||||||
tl.addWidget(self.swap_title_author_button, 0, 0, 2, 1)
|
tl.addWidget(self.swap_title_author_button, 0, 0, 2, 1)
|
||||||
|
tl.addWidget(self.manage_authors_button, 2, 0, 1, 1)
|
||||||
|
tl.addWidget(self.paste_isbn_button, 11, 0, 1, 1)
|
||||||
|
|
||||||
create_row(0, self.title, self.title_sort,
|
create_row(0, self.title, self.title_sort,
|
||||||
button=self.deduce_title_sort_button, span=2,
|
button=self.deduce_title_sort_button, span=2,
|
||||||
@ -669,6 +703,9 @@ class MetadataSingleDialogAlt1(MetadataSingleDialogBase): # {{{
|
|||||||
button=self.timestamp.clear_button, icon='trash.png')
|
button=self.timestamp.clear_button, icon='trash.png')
|
||||||
create_row(11, self.identifiers, self.comments,
|
create_row(11, self.identifiers, self.comments,
|
||||||
button=self.clear_identifiers_button, icon='trash.png')
|
button=self.clear_identifiers_button, icon='trash.png')
|
||||||
|
sto(self.clear_identifiers_button, self.swap_title_author_button)
|
||||||
|
sto(self.swap_title_author_button, self.manage_authors_button)
|
||||||
|
sto(self.manage_authors_button, self.paste_isbn_button)
|
||||||
tl.addItem(QSpacerItem(1, 1, QSizePolicy.Fixed, QSizePolicy.Expanding),
|
tl.addItem(QSpacerItem(1, 1, QSizePolicy.Fixed, QSizePolicy.Expanding),
|
||||||
12, 1, 1 ,1)
|
12, 1, 1 ,1)
|
||||||
|
|
||||||
@ -708,7 +745,6 @@ class MetadataSingleDialogAlt1(MetadataSingleDialogBase): # {{{
|
|||||||
gb = QGroupBox(_('Change cover'), tab1)
|
gb = QGroupBox(_('Change cover'), tab1)
|
||||||
l = QGridLayout()
|
l = QGridLayout()
|
||||||
gb.setLayout(l)
|
gb.setLayout(l)
|
||||||
sto(self.swap_title_author_button, self.cover.buttons[0])
|
|
||||||
for i, b in enumerate(self.cover.buttons[:3]):
|
for i, b in enumerate(self.cover.buttons[:3]):
|
||||||
l.addWidget(b, 0, i, 1, 1)
|
l.addWidget(b, 0, i, 1, 1)
|
||||||
sto(b, self.cover.buttons[i+1])
|
sto(b, self.cover.buttons[i+1])
|
||||||
@ -738,6 +774,7 @@ class MetadataSingleDialogAlt2(MetadataSingleDialogBase): # {{{
|
|||||||
|
|
||||||
cc_two_column = False
|
cc_two_column = False
|
||||||
one_line_comments_toolbar = True
|
one_line_comments_toolbar = True
|
||||||
|
use_toolbutton_for_config_metadata = False
|
||||||
|
|
||||||
def do_layout(self):
|
def do_layout(self):
|
||||||
self.central_widget.clear()
|
self.central_widget.clear()
|
||||||
@ -756,13 +793,11 @@ class MetadataSingleDialogAlt2(MetadataSingleDialogBase): # {{{
|
|||||||
l.addWidget(gb, 0, 0, 1, 1)
|
l.addWidget(gb, 0, 0, 1, 1)
|
||||||
gb.setLayout(tl)
|
gb.setLayout(tl)
|
||||||
|
|
||||||
self.button_box.addButton(self.fetch_metadata_button,
|
self.button_box_layout.insertWidget(1, self.fetch_metadata_button)
|
||||||
QDialogButtonBox.ActionRole)
|
self.button_box_layout.insertWidget(2, self.config_metadata_button)
|
||||||
self.config_metadata_button.setToolButtonStyle(Qt.ToolButtonTextOnly)
|
sto(self.button_box, self.fetch_metadata_button)
|
||||||
self.config_metadata_button.setText(_('Configure metadata downloading'))
|
sto(self.fetch_metadata_button, self.config_metadata_button)
|
||||||
self.button_box.addButton(self.config_metadata_button,
|
sto(self.config_metadata_button, self.title)
|
||||||
QDialogButtonBox.ActionRole)
|
|
||||||
sto(self.button_box, self.title)
|
|
||||||
|
|
||||||
def create_row(row, widget, tab_to, button=None, icon=None, span=1):
|
def create_row(row, widget, tab_to, button=None, icon=None, span=1):
|
||||||
ql = BuddyLabel(widget)
|
ql = BuddyLabel(widget)
|
||||||
@ -780,6 +815,8 @@ class MetadataSingleDialogAlt2(MetadataSingleDialogBase): # {{{
|
|||||||
sto(widget, tab_to)
|
sto(widget, tab_to)
|
||||||
|
|
||||||
tl.addWidget(self.swap_title_author_button, 0, 0, 2, 1)
|
tl.addWidget(self.swap_title_author_button, 0, 0, 2, 1)
|
||||||
|
tl.addWidget(self.manage_authors_button, 2, 0, 2, 1)
|
||||||
|
tl.addWidget(self.paste_isbn_button, 11, 0, 1, 1)
|
||||||
|
|
||||||
create_row(0, self.title, self.title_sort,
|
create_row(0, self.title, self.title_sort,
|
||||||
button=self.deduce_title_sort_button, span=2,
|
button=self.deduce_title_sort_button, span=2,
|
||||||
@ -801,6 +838,9 @@ class MetadataSingleDialogAlt2(MetadataSingleDialogBase): # {{{
|
|||||||
button=self.timestamp.clear_button, icon='trash.png')
|
button=self.timestamp.clear_button, icon='trash.png')
|
||||||
create_row(11, self.identifiers, self.comments,
|
create_row(11, self.identifiers, self.comments,
|
||||||
button=self.clear_identifiers_button, icon='trash.png')
|
button=self.clear_identifiers_button, icon='trash.png')
|
||||||
|
sto(self.clear_identifiers_button, self.swap_title_author_button)
|
||||||
|
sto(self.swap_title_author_button, self.manage_authors_button)
|
||||||
|
sto(self.manage_authors_button, self.paste_isbn_button)
|
||||||
tl.addItem(QSpacerItem(1, 1, QSizePolicy.Fixed, QSizePolicy.Expanding),
|
tl.addItem(QSpacerItem(1, 1, QSizePolicy.Fixed, QSizePolicy.Expanding),
|
||||||
12, 1, 1 ,1)
|
12, 1, 1 ,1)
|
||||||
|
|
||||||
@ -820,7 +860,7 @@ class MetadataSingleDialogAlt2(MetadataSingleDialogBase): # {{{
|
|||||||
l.addWidget(gb, 0, 1, 1, 1)
|
l.addWidget(gb, 0, 1, 1, 1)
|
||||||
sp = QSizePolicy()
|
sp = QSizePolicy()
|
||||||
sp.setVerticalStretch(10)
|
sp.setVerticalStretch(10)
|
||||||
sp.setHorizontalPolicy(QSizePolicy.Fixed)
|
sp.setHorizontalPolicy(QSizePolicy.Minimum)
|
||||||
sp.setVerticalPolicy(QSizePolicy.Expanding)
|
sp.setVerticalPolicy(QSizePolicy.Expanding)
|
||||||
gb.setSizePolicy(sp)
|
gb.setSizePolicy(sp)
|
||||||
self.set_custom_metadata_tab_order()
|
self.set_custom_metadata_tab_order()
|
||||||
@ -842,7 +882,7 @@ class MetadataSingleDialogAlt2(MetadataSingleDialogBase): # {{{
|
|||||||
lb = QGridLayout()
|
lb = QGridLayout()
|
||||||
gb.setLayout(lb)
|
gb.setLayout(lb)
|
||||||
lb.addWidget(self.cover, 0, 0, 1, 3, alignment=Qt.AlignCenter)
|
lb.addWidget(self.cover, 0, 0, 1, 3, alignment=Qt.AlignCenter)
|
||||||
sto(self.clear_identifiers_button, self.cover.buttons[0])
|
sto(self.manage_authors_button, self.cover.buttons[0])
|
||||||
for i, b in enumerate(self.cover.buttons[:3]):
|
for i, b in enumerate(self.cover.buttons[:3]):
|
||||||
lb.addWidget(b, 1, i, 1, 1)
|
lb.addWidget(b, 1, i, 1, 1)
|
||||||
sto(b, self.cover.buttons[i+1])
|
sto(b, self.cover.buttons[i+1])
|
||||||
|
@ -27,7 +27,7 @@ from calibre.utils.logging import default_log as log
|
|||||||
from calibre.utils.magick.draw import thumbnail
|
from calibre.utils.magick.draw import thumbnail
|
||||||
from calibre.utils.zipfile import ZipFile, ZipInfo
|
from calibre.utils.zipfile import ZipFile, ZipInfo
|
||||||
|
|
||||||
FIELDS = ['all', 'title', 'author_sort', 'authors', 'comments',
|
FIELDS = ['all', 'title', 'title_sort', 'author_sort', 'authors', 'comments',
|
||||||
'cover', 'formats','id', 'isbn', 'ondevice', 'pubdate', 'publisher',
|
'cover', 'formats','id', 'isbn', 'ondevice', 'pubdate', 'publisher',
|
||||||
'rating', 'series_index', 'series', 'size', 'tags', 'timestamp', 'uuid']
|
'rating', 'series_index', 'series', 'size', 'tags', 'timestamp', 'uuid']
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ class CSV_XML(CatalogPlugin): # {{{
|
|||||||
dest = 'sort_by',
|
dest = 'sort_by',
|
||||||
action = None,
|
action = None,
|
||||||
help = _('Output field to sort on.\n'
|
help = _('Output field to sort on.\n'
|
||||||
'Available fields: author_sort, id, rating, size, timestamp, title.\n'
|
'Available fields: author_sort, id, rating, size, timestamp, title_sort\n'
|
||||||
"Default: '%default'\n"
|
"Default: '%default'\n"
|
||||||
"Applies to: CSV, XML output formats"))]
|
"Applies to: CSV, XML output formats"))]
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ class CSV_XML(CatalogPlugin): # {{{
|
|||||||
|
|
||||||
if opts.verbose:
|
if opts.verbose:
|
||||||
opts_dict = vars(opts)
|
opts_dict = vars(opts)
|
||||||
log("%s(): Generating %s" % (self.name,self.fmt))
|
log("%s(): Generating %s" % (self.name,self.fmt.upper()))
|
||||||
if opts.connected_device['is_device_connected']:
|
if opts.connected_device['is_device_connected']:
|
||||||
log(" connected_device: %s" % opts.connected_device['name'])
|
log(" connected_device: %s" % opts.connected_device['name'])
|
||||||
if opts_dict['search_text']:
|
if opts_dict['search_text']:
|
||||||
@ -126,8 +126,11 @@ class CSV_XML(CatalogPlugin): # {{{
|
|||||||
for field in fields:
|
for field in fields:
|
||||||
if field.startswith('#'):
|
if field.startswith('#'):
|
||||||
item = db.get_field(entry['id'],field,index_is_id=True)
|
item = db.get_field(entry['id'],field,index_is_id=True)
|
||||||
|
elif field == 'title_sort':
|
||||||
|
item = entry['sort']
|
||||||
else:
|
else:
|
||||||
item = entry[field]
|
item = entry[field]
|
||||||
|
|
||||||
if item is None:
|
if item is None:
|
||||||
outstr.append('""')
|
outstr.append('""')
|
||||||
continue
|
continue
|
||||||
@ -167,7 +170,7 @@ class CSV_XML(CatalogPlugin): # {{{
|
|||||||
item = getattr(E, field.replace('#','_'))(val)
|
item = getattr(E, field.replace('#','_'))(val)
|
||||||
record.append(item)
|
record.append(item)
|
||||||
|
|
||||||
for field in ('id', 'uuid', 'title', 'publisher', 'rating', 'size',
|
for field in ('id', 'uuid', 'publisher', 'rating', 'size',
|
||||||
'isbn','ondevice'):
|
'isbn','ondevice'):
|
||||||
if field in fields:
|
if field in fields:
|
||||||
val = r[field]
|
val = r[field]
|
||||||
@ -178,6 +181,10 @@ class CSV_XML(CatalogPlugin): # {{{
|
|||||||
item = getattr(E, field)(val)
|
item = getattr(E, field)(val)
|
||||||
record.append(item)
|
record.append(item)
|
||||||
|
|
||||||
|
if 'title' in fields:
|
||||||
|
title = E.title(r['title'], sort=r['sort'])
|
||||||
|
record.append(title)
|
||||||
|
|
||||||
if 'authors' in fields:
|
if 'authors' in fields:
|
||||||
aus = E.authors(sort=r['author_sort'])
|
aus = E.authors(sort=r['author_sort'])
|
||||||
for au in r['authors']:
|
for au in r['authors']:
|
||||||
|
@ -3056,7 +3056,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
'''
|
'''
|
||||||
if prefix is None:
|
if prefix is None:
|
||||||
prefix = self.library_path
|
prefix = self.library_path
|
||||||
FIELDS = set(['title', 'authors', 'author_sort', 'publisher', 'rating',
|
FIELDS = set(['title', 'sort', 'authors', 'author_sort', 'publisher', 'rating',
|
||||||
'timestamp', 'size', 'tags', 'comments', 'series', 'series_index',
|
'timestamp', 'size', 'tags', 'comments', 'series', 'series_index',
|
||||||
'uuid', 'pubdate', 'last_modified', 'identifiers'])
|
'uuid', 'pubdate', 'last_modified', 'identifiers'])
|
||||||
for x in self.custom_column_num_map:
|
for x in self.custom_column_num_map:
|
||||||
|
@ -10,6 +10,7 @@ License: http://www.opensource.org/licenses/mit-license.php
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from calibre.utils.icu import capitalize
|
from calibre.utils.icu import capitalize
|
||||||
|
from calibre.utils.config import prefs
|
||||||
|
|
||||||
__all__ = ['titlecase']
|
__all__ = ['titlecase']
|
||||||
__version__ = '0.5'
|
__version__ = '0.5'
|
||||||
@ -67,11 +68,12 @@ def titlecase(text):
|
|||||||
line.append(icu_lower(word))
|
line.append(icu_lower(word))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
match = MAC_MC.match(word)
|
if prefs['language'].lower().startswith('en'):
|
||||||
if match and not match.group(2)[:3] in ('hin', 'ht'):
|
match = MAC_MC.match(word)
|
||||||
line.append("%s%s" % (capitalize(match.group(1)),
|
if match and not match.group(2)[:3] in ('hin', 'ht'):
|
||||||
capitalize(match.group(2))))
|
line.append("%s%s" % (capitalize(match.group(1)),
|
||||||
continue
|
capitalize(match.group(2))))
|
||||||
|
continue
|
||||||
|
|
||||||
hyphenated = []
|
hyphenated = []
|
||||||
for item in word.split('-'):
|
for item in word.split('-'):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user