Merge from trunk

This commit is contained in:
Charles Haley 2011-05-10 15:18:53 +01:00
commit 05e9dc65d1
17 changed files with 156 additions and 78 deletions

View File

@ -21,14 +21,19 @@ class Fronda(BasicNewsRecipe):
feeds = [(u'Infformacje', u'http://fronda.pl/news/feed')]
keep_only_tags = [dict(name='h1', attrs={'class':'big'}),
dict(name='ul', attrs={'class':'about clear'}),
dict(name='div', attrs={'class':'content'})]
keep_only_tags = [dict(name='h2', attrs={'class':'news_title'}),
dict(name='div', attrs={'class':'naglowek_tresc'}),
dict(name='div', attrs={'id':'czytaj'}) ]
remove_tags = [dict(name='a', attrs={'class':'print'})]
preprocess_regexps = [
(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'<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[^>]*>&nbsp;</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: '')]
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
recipes/icons/ziuaveche.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B

View File

@ -2,7 +2,7 @@ from calibre.web.feeds.news import BasicNewsRecipe
class RzeczpospolitaRecipe(BasicNewsRecipe):
__license__ = 'GPL v3'
__author__ = 'kwetal'
__author__ = u'kwetal and Tomasz Dlugosz'
language = 'pl'
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 = {'id' : 'share_bottom'}))
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 = '''
body {font-family: verdana, arial, helvetica, geneva, sans-serif ;}
@ -48,6 +50,13 @@ class RzeczpospolitaRecipe(BasicNewsRecipe):
.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):
start, sep, rest = url.rpartition('/')
forget, sep, index = rest.rpartition(',')

View File

@ -1,17 +1,12 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3'
__copyright__ = '2009, Gerhard Aigner <gerhard.aigner at gmail.com>'
import re
from calibre.web.feeds.news import BasicNewsRecipe
class TelepolisNews(BasicNewsRecipe):
title = u'Telepolis (News+Artikel)'
__author__ = 'Gerhard Aigner'
__author__ = 'syntaxis'
publisher = 'Heise Zeitschriften Verlag GmbH & Co KG'
description = 'News from telepolis'
description = 'News from Telepolis'
category = 'news'
oldest_article = 7
max_articles_per_feed = 100
@ -20,14 +15,19 @@ class TelepolisNews(BasicNewsRecipe):
encoding = "utf-8"
language = 'de'
use_embedded_content =False
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')]
@ -39,15 +39,8 @@ class TelepolisNews(BasicNewsRecipe):
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):
mtag = '<meta http-equiv="Content-Type" content="text/html; charset=' + self.encoding + '">'
soup.head.insert(0,mtag)
return soup

53
recipes/ziuaveche.recipe Normal file
View 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)

View File

@ -203,9 +203,11 @@ class ITUNES(DriverBase):
# 0x1294 iPhone 3GS
# 0x1297 iPhone 4
# 0x129a iPad
# 0x12a2 iPad2
# 0x129f iPad2 (WiFi)
# 0x12a2 iPad2 (GSM)
# 0x12a3 iPad2 (CDMA)
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]
# Plugboard ID

View File

@ -68,7 +68,8 @@ def check_command_line_options(parser, args, log):
raise SystemExit(1)
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.abspath(output)

View File

@ -7,7 +7,6 @@ __copyright__ = '2011, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
import os
import posixpath
from calibre import guess_type, walk
from calibre.customize.conversion import InputFormatPlugin
@ -74,22 +73,23 @@ class HTMLZInput(InputFormatPlugin):
meta_info_to_oeb_metadata(mi, oeb.metadata, log)
# Get the cover path from the OPF.
cover_href = None
cover_path = None
opf = None
for x in walk('.'):
if os.path.splitext(x)[1].lower() in ('.opf'):
opf = x
break
if opf:
opf = OPF(opf)
cover_href = posixpath.relpath(opf.cover, os.path.dirname(stream.name))
opf = OPF(opf, basedir=os.getcwd())
cover_path = opf.raster_cover
# Set the cover.
if cover_href:
if cover_path:
cdata = None
with open(cover_href, 'rb') as cf:
with open(os.path.join(os.getcwd(), cover_path), 'rb') as cf:
cdata = cf.read()
id, href = oeb.manifest.generate('cover', cover_href)
oeb.manifest.add(id, href, guess_type(cover_href)[0], data=cdata)
cover_name = os.path.basename(cover_path)
id, href = oeb.manifest.generate('cover', cover_name)
oeb.manifest.add(id, href, guess_type(cover_name)[0], data=cdata)
oeb.guide.add('cover', 'Cover', href)
return oeb

View File

@ -8,12 +8,11 @@ Read meta information from extZ (TXTZ, HTMLZ...) files.
'''
import os
import posixpath
from cStringIO import StringIO
from calibre.ebooks.metadata import MetaInformation
from calibre.ebooks.metadata.opf2 import OPF, metadata_to_opf
from calibre.ebooks.metadata.opf2 import OPF
from calibre.ptempfile import PersistentTemporaryFile
from calibre.utils.zipfile import ZipFile, safe_replace
@ -31,9 +30,9 @@ def get_metadata(stream, extract_cover=True):
opf = OPF(opf_stream)
mi = opf.to_book_metadata()
if extract_cover:
cover_href = posixpath.relpath(opf.cover, os.path.dirname(stream.name))
cover_href = opf.raster_cover
if cover_href:
mi.cover_data = ('jpg', zf.read(cover_href))
mi.cover_data = (os.path.splitext(cover_href)[1], zf.read(cover_href))
except:
return mi
return mi
@ -59,18 +58,15 @@ def set_metadata(stream, mi):
except:
pass
if new_cdata:
cover = opf.cover
if not cover:
cover = 'cover.jpg'
cpath = posixpath.join(posixpath.dirname(opf_path), cover)
cpath = opf.raster_cover
if not cpath:
cpath = 'cover.jpg'
new_cover = _write_new_cover(new_cdata, cpath)
replacements[cpath] = open(new_cover.name, 'rb')
mi.cover = cover
mi.cover = cpath
# Update the metadata.
old_mi = opf.to_book_metadata()
old_mi.smart_update(mi)
opf.smart_update(metadata_to_opf(old_mi), replace_metadata=True)
opf.smart_update(mi, replace_metadata=True)
newopf = StringIO(opf.render())
safe_replace(stream, opf_path, newopf, extra_replacements=replacements, add_missing=True)

View File

@ -338,7 +338,7 @@ class Amazon(Source):
q['field-author'] = ' '.join(author_tokens)
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
return None

View File

@ -212,6 +212,9 @@ class Source(Plugin):
def is_customizable(self):
return True
def customization_help(self):
return 'This plugin can only be customized using the GUI'
def config_widget(self):
from calibre.gui2.metadata.config import ConfigWidget
return ConfigWidget(self)
@ -288,10 +291,10 @@ class Source(Plugin):
parts = parts[1:] + parts[:1]
for tok in parts:
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
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.

View File

@ -20,6 +20,9 @@ class GenerateCatalogAction(InterfaceAction):
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'])
def genesis(self):
self.qaction.triggered.connect(self.generate_catalog)
def generate_catalog(self):
rows = self.gui.library_view.selectionModel().selectedRows()
if not rows or len(rows) < 2:

View File

@ -19,9 +19,13 @@ class MessageBox(QDialog, Ui_Dialog): # {{{
INFO = 2
QUESTION = 3
def __init__(self, type_, title, msg, det_msg='', show_copy_button=True,
def __init__(self, type_, title, msg,
det_msg='',
q_icon=None,
show_copy_button=True,
parent=None):
QDialog.__init__(self, parent)
if q_icon is None:
icon = {
self.ERROR : 'error',
self.WARNING: 'warning',
@ -30,6 +34,8 @@ class MessageBox(QDialog, Ui_Dialog): # {{{
}[type_]
icon = 'dialog_%s.png'%icon
self.icon = QIcon(I(icon))
else:
self.icon = q_icon
self.setupUi(self)
self.setWindowTitle(title)
@ -44,7 +50,6 @@ class MessageBox(QDialog, Ui_Dialog): # {{{
self.bb.ActionRole)
self.ctc_button.clicked.connect(self.copy_to_clipboard)
self.show_det_msg = _('Show &details')
self.hide_det_msg = _('Hide &details')
self.det_msg_toggle = self.bb.addButton(self.show_det_msg, self.bb.ActionRole)

View File

@ -1126,7 +1126,7 @@ class DateEdit(QDateEdit): # {{{
@dynamic_property
def current_val(self):
def fget(self):
return qt_to_dt(self.date())
return qt_to_dt(self.date(), as_utc=False)
def fset(self, val):
if val is None:
val = UNDEFINED_DATE

View File

@ -31,6 +31,7 @@ class MetadataSingleDialogBase(ResizableDialog):
view_format = pyqtSignal(object, object)
cc_two_column = tweaks['metadata_single_use_2_cols_for_custom_fields']
one_line_comments_toolbar = False
use_toolbutton_for_config_metadata = True
def __init__(self, db, parent=None):
self.db = db
@ -71,7 +72,9 @@ class MetadataSingleDialogBase(ResizableDialog):
self.l.addWidget(self.scroll_area)
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.setWindowTitle(_('Edit Metadata'))
@ -191,8 +194,13 @@ class MetadataSingleDialogBase(ResizableDialog):
font.setBold(True)
self.fetch_metadata_button.setFont(font)
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.clicked.connect(self.configure_metadata)
self.config_metadata_button.setToolTip(
_('Change how calibre downloads metadata'))
@ -614,6 +622,7 @@ class MetadataSingleDialogAlt1(MetadataSingleDialogBase): # {{{
cc_two_column = False
one_line_comments_toolbar = True
use_toolbutton_for_config_metadata = False
on_drag_enter = pyqtSignal()
@ -649,10 +658,8 @@ class MetadataSingleDialogAlt1(MetadataSingleDialogBase): # {{{
self.tabs[0].l.addWidget(gb, 0, 0, 1, 1)
gb.setLayout(tl)
self.button_box_layout.insertWidget(0, self.fetch_metadata_button)
self.config_metadata_button.setToolButtonStyle(Qt.ToolButtonTextOnly)
self.config_metadata_button.setText(_('Configure metadata downloading'))
self.button_box_layout.insertWidget(1, self.config_metadata_button)
self.button_box_layout.insertWidget(1, self.fetch_metadata_button)
self.button_box_layout.insertWidget(2, self.config_metadata_button)
sto(self.button_box, self.fetch_metadata_button)
sto(self.fetch_metadata_button, self.config_metadata_button)
sto(self.config_metadata_button, self.title)
@ -767,6 +774,7 @@ class MetadataSingleDialogAlt2(MetadataSingleDialogBase): # {{{
cc_two_column = False
one_line_comments_toolbar = True
use_toolbutton_for_config_metadata = False
def do_layout(self):
self.central_widget.clear()
@ -785,10 +793,8 @@ class MetadataSingleDialogAlt2(MetadataSingleDialogBase): # {{{
l.addWidget(gb, 0, 0, 1, 1)
gb.setLayout(tl)
self.button_box_layout.insertWidget(0, self.fetch_metadata_button)
self.config_metadata_button.setToolButtonStyle(Qt.ToolButtonTextOnly)
self.config_metadata_button.setText(_('Configure metadata downloading'))
self.button_box_layout.insertWidget(1, self.config_metadata_button)
self.button_box_layout.insertWidget(1, self.fetch_metadata_button)
self.button_box_layout.insertWidget(2, self.config_metadata_button)
sto(self.button_box, self.fetch_metadata_button)
sto(self.fetch_metadata_button, self.config_metadata_button)
sto(self.config_metadata_button, self.title)

View File

@ -10,6 +10,7 @@ License: http://www.opensource.org/licenses/mit-license.php
import re
from calibre.utils.icu import capitalize
from calibre.utils.config import prefs
__all__ = ['titlecase']
__version__ = '0.5'
@ -67,6 +68,7 @@ def titlecase(text):
line.append(icu_lower(word))
continue
if prefs['language'].lower().startswith('en'):
match = MAC_MC.match(word)
if match and not match.group(2)[:3] in ('hin', 'ht'):
line.append("%s%s" % (capitalize(match.group(1)),