diff --git a/recipes/fronda.recipe b/recipes/fronda.recipe
index f57c7ecccb..452dca9068 100644
--- a/recipes/fronda.recipe
+++ b/recipes/fronda.recipe
@@ -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'Drukuj', lambda match: ''),
- (r'
.*
', lambda match: ''),
+ [ (r'.*
', lambda match: ''),
(r'.*
', lambda match: ''),
(r'W.* lektury.*', lambda match: ''),
- (r'Zobacz t.*?', lambda match: '') ]
+ (r'Zobacz t.*?', lambda match: ''),
+ (r'
]*>
', lambda match: ''),
+ (r'
', lambda match: ''),
+ (r']*>', re.DOTALL|re.IGNORECASE), lambda match: ''),
- (re.compile(r'', 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 = ''
soup.head.insert(0,mtag)
return soup
-
-
diff --git a/recipes/ziuaveche.recipe b/recipes/ziuaveche.recipe
new file mode 100644
index 0000000000..61df768e0a
--- /dev/null
+++ b/recipes/ziuaveche.recipe
@@ -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)
diff --git a/src/calibre/devices/apple/driver.py b/src/calibre/devices/apple/driver.py
index cd0bbe2ace..b7d5ac36d2 100644
--- a/src/calibre/devices/apple/driver.py
+++ b/src/calibre/devices/apple/driver.py
@@ -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
diff --git a/src/calibre/ebooks/conversion/cli.py b/src/calibre/ebooks/conversion/cli.py
index f1d5d5fe1b..b03887469d 100644
--- a/src/calibre/ebooks/conversion/cli.py
+++ b/src/calibre/ebooks/conversion/cli.py
@@ -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)
diff --git a/src/calibre/ebooks/htmlz/input.py b/src/calibre/ebooks/htmlz/input.py
index d083fcc4ab..743d8e53eb 100644
--- a/src/calibre/ebooks/htmlz/input.py
+++ b/src/calibre/ebooks/htmlz/input.py
@@ -7,7 +7,6 @@ __copyright__ = '2011, John Schember '
__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
diff --git a/src/calibre/ebooks/metadata/extz.py b/src/calibre/ebooks/metadata/extz.py
index 021450fca5..f3725027a9 100644
--- a/src/calibre/ebooks/metadata/extz.py
+++ b/src/calibre/ebooks/metadata/extz.py
@@ -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)
diff --git a/src/calibre/ebooks/metadata/sources/amazon.py b/src/calibre/ebooks/metadata/sources/amazon.py
index 8483698e28..31d815af63 100644
--- a/src/calibre/ebooks/metadata/sources/amazon.py
+++ b/src/calibre/ebooks/metadata/sources/amazon.py
@@ -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
diff --git a/src/calibre/ebooks/metadata/sources/base.py b/src/calibre/ebooks/metadata/sources/base.py
index 3eff9b11b3..c20cb1db83 100644
--- a/src/calibre/ebooks/metadata/sources/base.py
+++ b/src/calibre/ebooks/metadata/sources/base.py
@@ -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.
diff --git a/src/calibre/gui2/actions/catalog.py b/src/calibre/gui2/actions/catalog.py
index 093985d041..45544d8246 100644
--- a/src/calibre/gui2/actions/catalog.py
+++ b/src/calibre/gui2/actions/catalog.py
@@ -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:
diff --git a/src/calibre/gui2/dialogs/message_box.py b/src/calibre/gui2/dialogs/message_box.py
index f9354a0cfc..fdec19dc69 100644
--- a/src/calibre/gui2/dialogs/message_box.py
+++ b/src/calibre/gui2/dialogs/message_box.py
@@ -19,17 +19,23 @@ class MessageBox(QDialog, Ui_Dialog): # {{{
INFO = 2
QUESTION = 3
- def __init__(self, type_, title, msg, det_msg='', show_copy_button=True,
- parent=None):
+ def __init__(self, type_, title, msg,
+ det_msg='',
+ q_icon=None,
+ show_copy_button=True,
+ parent=None):
QDialog.__init__(self, parent)
- icon = {
- self.ERROR : 'error',
- self.WARNING: 'warning',
- self.INFO: 'information',
- self.QUESTION: 'question',
- }[type_]
- icon = 'dialog_%s.png'%icon
- self.icon = QIcon(I(icon))
+ if q_icon is None:
+ icon = {
+ self.ERROR : 'error',
+ self.WARNING: 'warning',
+ self.INFO: 'information',
+ self.QUESTION: 'question',
+ }[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)
diff --git a/src/calibre/gui2/metadata/basic_widgets.py b/src/calibre/gui2/metadata/basic_widgets.py
index 8858f9c986..d662256def 100644
--- a/src/calibre/gui2/metadata/basic_widgets.py
+++ b/src/calibre/gui2/metadata/basic_widgets.py
@@ -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
diff --git a/src/calibre/gui2/metadata/single.py b/src/calibre/gui2/metadata/single.py
index 84f0405fc6..5c4e241bba 100644
--- a/src/calibre/gui2/metadata/single.py
+++ b/src/calibre/gui2/metadata/single.py
@@ -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,7 +194,12 @@ class MetadataSingleDialogBase(ResizableDialog):
font.setBold(True)
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.clicked.connect(self.configure_metadata)
self.config_metadata_button.setToolTip(
@@ -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)
diff --git a/src/calibre/utils/titlecase.py b/src/calibre/utils/titlecase.py
index 1f153dd5fe..ff5b446268 100755
--- a/src/calibre/utils/titlecase.py
+++ b/src/calibre/utils/titlecase.py
@@ -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,11 +68,12 @@ def titlecase(text):
line.append(icu_lower(word))
continue
- match = MAC_MC.match(word)
- if match and not match.group(2)[:3] in ('hin', 'ht'):
- line.append("%s%s" % (capitalize(match.group(1)),
- capitalize(match.group(2))))
- 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)),
+ capitalize(match.group(2))))
+ continue
hyphenated = []
for item in word.split('-'):