Pull from trunk

This commit is contained in:
Timothy Legge 2010-06-20 23:51:03 -03:00
commit d871e221e3
37 changed files with 21687 additions and 18271 deletions

View File

@ -4,6 +4,31 @@
# for important features/bug fixes. # for important features/bug fixes.
# Also, each release can have new and improved recipes. # Also, each release can have new and improved recipes.
- version: 0.7.4
date: 2010-06-19
bug fixes:
- title: "Fix regression in 0.7.3 that broke creating custom columns of rating or text types"
- title: "Fix cover browser breaking if you click on a book in the book list while cover browser is animated"
- title: "Fix a bug that could be triggered with the new book details pane if a book has a zero size cover"
tickets: [5889]
- title: "SONY driver: Fix bug preventing the editing of collections in the device view"
new recipes:
- title: Auto Prove
author: Gabriele Marini
- title: Forbes India, Maximum PC, Today Online
author: rty
improved recipes:
- WSJ
- Psychology Today
- version: 0.7.3 - version: 0.7.3
date: 2010-06-18 date: 2010-06-18

View File

@ -0,0 +1,90 @@
#!/usr/bin/env python
__license__ = 'GPL v3'
__author__ = 'GabrieleMarini, based on Darko Miletic'
__copyright__ = '2009, Darko Miletic <darko.miletic at gmail.com>, Gabriele Marini'
__version__ = 'v1.02 Marini Gabriele '
__date__ = '10, January 2010'
__description__ = 'Italian daily newspaper'
'''
http://www.corrieredellosport.it/
'''
from calibre.web.feeds.news import BasicNewsRecipe
class AutoPR(BasicNewsRecipe):
__author__ = 'Gabriele Marini'
description = 'Auto and Formula 1'
cover_url = 'http://www.auto.it/res/imgs/logo_Auto.png'
title = u'Auto Prove'
publisher = 'CONTE Editore'
category = 'Sport'
language = 'it'
timefmt = '[%a, %d %b, %Y]'
oldest_article = 60
max_articles_per_feed = 20
use_embedded_content = False
recursion = 100
remove_javascript = True
no_stylesheets = True
#html2lrf_options = [
# '--comment', description
# , '--category', category
# , '--publisher', publisher
# , '--ignore-tables'
# ]
#html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"\nlinearize_tables=True'
keep_only_tags = [
dict(name='h2', attrs={'class':['tit_Article y_Txt']}),
dict(name='h2', attrs={'class':['tit_Article']}),
dict(name='div', attrs={'class':['box_Img newsdet_new ']}),
dict(name='div', attrs={'class':['box_Img newsdet_as ']}),
dict(name='table', attrs={'class':['table_A']}),
dict(name='div', attrs={'class':['txt_Article txtBox_cms']}),
dict(name='testoscheda')]
def parse_index(self):
feeds = []
for title, url in [
("Prove su Strada" , "http://www.auto.it/rss/prove+6.xml")
]:
soup = self.index_to_soup(url)
soup = soup.find('channel')
print soup
for article in soup.findAllNext('item'):
title = self.tag_to_string(article.title)
date = self.tag_to_string(article.pubDate)
description = self.tag_to_string(article.description)
link = self.tag_to_string(article.guid)
# print article
articles = self.create_links_append(link, date, description)
if articles:
feeds.append((title, articles))
return feeds
def create_links_append(self, link, date, description):
current_articles = []
current_articles.append({'title': 'Generale', 'url': link,'description':description, 'date':date}),
current_articles.append({'title': 'Design', 'url': link.replace('scheda','design'),'description':'scheda', 'date':''}),
current_articles.append({'title': 'Interni', 'url': link.replace('scheda','interni'),'description':'Interni', 'date':''}),
current_articles.append({'title': 'Tecnica', 'url': link.replace('scheda','tecnica'),'description':'Tecnica', 'date':''}),
current_articles.append({'title': 'Su Strada', 'url': link.replace('scheda','su_strada'),'description':'Su Strada', 'date':''}),
current_articles.append({'title': 'Pagella', 'url': link.replace('scheda','pagella'),'description':'Pagella', 'date':''}),
current_articles.append({'title': 'Rilevamenti', 'url': link.replace('scheda','telemetria'),'description':'Rilevamenti', 'date':''})
return current_articles

View File

@ -0,0 +1,55 @@
from calibre.ptempfile import PersistentTemporaryFile
from calibre.web.feeds.news import BasicNewsRecipe
class AdvancedUserRecipe1276934715(BasicNewsRecipe):
title = u'Forbes India'
__author__ = 'rty'
description = 'India Edition Forbes'
publisher = 'Forbes India'
category = 'Business News, Economy, India'
oldest_article = 7
max_articles_per_feed = 100
remove_javascript = True
use_embedded_content = False
no_stylesheets = True
language = 'en_IN'
temp_files = []
articles_are_obfuscated = True
conversion_options = {'linearize_tables':True}
feeds = [
(u'Contents', u'http://business.in.com/rssfeed/rss_all.xml'),
]
extra_css = '''
.t-10-gy-l{font-style: italic; font-size: small}
.t-30-b-d{font-weight: bold; font-size: xx-large}
.t-16-gy-l{font-weight: bold; font-size: x-large; font-syle: italic}
.storycontent{font-size: 4px;font-family: Times New Roman;}
'''
remove_tags_before = dict(name='div', attrs={'class':'pdl10 pdr15'})
def get_obfuscated_article(self, url):
br = self.get_browser()
br.open(url)
response = br.follow_link(url_regex = r'/printcontent/[0-9]+', nr = 0)
html = response.read()
self.temp_files.append(PersistentTemporaryFile('_fa.html'))
self.temp_files[-1].write(html)
self.temp_files[-1].close()
return self.temp_files[-1].name
def get_cover_url(self):
index = 'http://business.in.com/magazine/'
soup = self.index_to_soup(index)
for image in soup.findAll('a',{ "class" : "lbOn a-9-b-d" }):
return image['href']
#return image['href'] + '.jpg'
return None
def preprocess_html(self, soup):
for item in soup.findAll(style=True):
del item['style']
for item in soup.findAll(width=True):
del item['width']
return soup

View File

@ -0,0 +1,43 @@
from calibre.ptempfile import PersistentTemporaryFile
from calibre.web.feeds.news import BasicNewsRecipe
class AdvancedUserRecipe1276930924(BasicNewsRecipe):
title = u'Maximum PC'
__author__ = 'rty'
description = 'Maximum PC'
publisher = 'http://www.maximumpc.com'
category = 'news, computer, technology'
language = 'en'
oldest_article = 30
max_articles_per_feed = 100
remove_javascript = True
use_embedded_content = False
no_stylesheets = True
language = 'en'
temp_files = []
articles_are_obfuscated = True
feeds = [(u'News', u'http://www.maximumpc.com/articles/4/feed'),
(u'Reviews', u'http://www.maximumpc.com/articles/40/feed'),
(u'Editors Blog', u'http://www.maximumpc.com/articles/6/feed'),
(u'How-to', u'http://www.maximumpc.com/articles/32/feed'),
(u'Features', u'http://www.maximumpc.com/articles/31/feed'),
(u'From the Magazine', u'http://www.maximumpc.com/articles/72/feed')
]
keep_only_tags = [
dict(name='div', attrs={'class':['print-title','article_body']}),
]
remove_tags = [
dict(name='div', attrs={'class':'comments-tags-actions'}),
]
remove_tags_before = dict(name='div', attrs={'class':'print-title'})
remove_tags_after = dict(name='div', attrs={'class':'meta-content'})
def get_obfuscated_article(self, url):
br = self.get_browser()
br.open(url)
response = br.follow_link(url_regex = r'/print/[0-9]+', nr = 0)
html = response.read()
self.temp_files.append(PersistentTemporaryFile('_fa.html'))
self.temp_files[-1].write(html)
self.temp_files[-1].close()
return self.temp_files[-1].name

View File

@ -1,39 +1,44 @@
from calibre.ptempfile import PersistentTemporaryFile
from calibre.web.feeds.news import BasicNewsRecipe from calibre.web.feeds.news import BasicNewsRecipe
from calibre.ebooks.BeautifulSoup import BeautifulSoup
class PsychologyToday(BasicNewsRecipe): class AdvancedUserRecipe1275708473(BasicNewsRecipe):
title = u'Psychology Today' title = u'Psychology Today'
_author__ = 'rty'
publisher = u'www.psychologytoday.com'
category = u'Psychology'
max_articles_per_feed = 100
remove_javascript = True
use_embedded_content = False
no_stylesheets = True
language = 'en' language = 'en'
__author__ = 'Krittika Goyal' temp_files = []
oldest_article = 1 #days articles_are_obfuscated = True
max_articles_per_feed = 25
#encoding = 'latin1'
remove_stylesheets = True
#remove_tags_before = dict(name='h1', attrs={'class':'heading'})
#remove_tags_after = dict(name='td', attrs={'class':'newptool1'})
remove_tags = [ remove_tags = [
dict(name='iframe'), dict(name='div', attrs={'class':['print-source_url','field-items','print-footer']}),
dict(name='div', attrs={'class':['pt-box-title', 'pt-box-content', 'blog-entry-footer', 'item-list', 'article-sub-meta']}), dict(name='span', attrs={'class':'print-footnote'}),
dict(name='div', attrs={'id':['block-td_search_160', 'block-cam_search_160']}),
#dict(name='ul', attrs={'class':'article-tools'}),
#dict(name='ul', attrs={'class':'articleTools'}),
] ]
remove_tags_before = dict(name='h1', attrs={'class':'print-title'})
remove_tags_after = dict(name='div', attrs={'class':['field-items','print-footer']})
feeds = [ feeds = [(u'Contents', u'http://www.psychologytoday.com/articles/index.rss')]
('PSY TODAY',
'http://www.psychologytoday.com/articles/index.rss'),
]
def preprocess_html(self, soup): def get_article_url(self, article):
story = soup.find(name='div', attrs={'id':'contentColumn'}) return article.get('link', None)
#td = heading.findParent(name='td')
#td.extract() def get_obfuscated_article(self, url):
soup = BeautifulSoup('<html><head><title>t</title></head><body></body></html>') br = self.get_browser()
body = soup.find(name='body') br.open(url)
body.insert(0, story) response = br.follow_link(url_regex = r'/print/[0-9]+', nr = 0)
for x in soup.findAll(name='p', text=lambda x:x and '--&gt;' in x): html = response.read()
p = x.findParent('p') self.temp_files.append(PersistentTemporaryFile('_fa.html'))
if p is not None: self.temp_files[-1].write(html)
p.extract() self.temp_files[-1].close()
return soup return self.temp_files[-1].name
def get_cover_url(self):
index = 'http://www.psychologytoday.com/magazine/'
soup = self.index_to_soup(index)
for image in soup.findAll('img',{ "class" : "imagefield imagefield-field_magazine_cover" }):
return image['src'] + '.jpg'
return None

View File

@ -0,0 +1,59 @@
from calibre.ptempfile import PersistentTemporaryFile
from calibre.web.feeds.news import BasicNewsRecipe
class AdvancedUserRecipe1276486274(BasicNewsRecipe):
title = u'Today Online - Singapore'
publisher = 'MediaCorp Press Ltd - Singapore'
__author__ = 'rty'
category = 'news, Singapore'
oldest_article = 7
max_articles_per_feed = 100
remove_javascript = True
use_embedded_content = False
no_stylesheets = True
language = 'en_SG'
temp_files = []
articles_are_obfuscated = True
masthead_url = 'http://www.todayonline.com/App_Themes/Default/images/icons/TodayOnlineLogo.gif'
conversion_options = {'linearize_tables':True}
extra_css = '''
.author{font-style: italic; font-size: small}
.date{font-style: italic; font-size: small}
.Headline{font-weight: bold; font-size: xx-large}
.headerStrap{font-weight: bold; font-size: x-large; font-syle: italic}
.bodyText{font-size: 4px;font-family: Times New Roman;}
'''
keep_only_tags = [
dict(name='div', attrs={'id':['fullPrintBodyHolder']})
]
remove_tags_after = [ dict(name='div', attrs={'class':'button'})]
remove_tags = [
dict(name='div', attrs={'class':['url','button']})
]
feeds = [
(u'Singapore', u'http://www.todayonline.com/RSS/Singapore'),
(u'Hot News', u'http://www.todayonline.com/RSS/Hotnews'),
(u'Today Online', u'http://www.todayonline.com/RSS/Todayonline'),
(u'Voices', u'http://www.todayonline.com/RSS/Voices'),
(u'Commentary', u'http://www.todayonline.com/RSS/Commentary'),
(u'World', u'http://www.todayonline.com/RSS/World'),
(u'Business', u'http://www.todayonline.com/RSS/Business'),
(u'Column', u'http://www.todayonline.com/RSS/Columns'),
]
def get_obfuscated_article(self, url):
br = self.get_browser()
br.open(url)
response = br.follow_link(url_regex = r'/Print/', nr = 0)
html = response.read()
self.temp_files.append(PersistentTemporaryFile('_fa.html'))
self.temp_files[-1].write(html)
self.temp_files[-1].close()
return self.temp_files[-1].name
def preprocess_html(self, soup):
for item in soup.findAll(style=True):
del item['style']
return soup

View File

@ -4,13 +4,14 @@ __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
from calibre.web.feeds.news import BasicNewsRecipe from calibre.web.feeds.news import BasicNewsRecipe
import copy
# http://online.wsj.com/page/us_in_todays_paper.html # http://online.wsj.com/page/us_in_todays_paper.html
class WallStreetJournal(BasicNewsRecipe): class WallStreetJournal(BasicNewsRecipe):
title = 'The Wall Street Journal (US)' title = 'The Wall Street Journal'
__author__ = 'Kovid Goyal and Sujata Raman' __author__ = 'Kovid Goyal, Sujata Raman, and Joshua Oster-Morris'
description = 'News and current affairs' description = 'News and current affairs'
needs_subscription = True needs_subscription = True
language = 'en' language = 'en'
@ -67,6 +68,16 @@ class WallStreetJournal(BasicNewsRecipe):
def wsj_get_index(self): def wsj_get_index(self):
return self.index_to_soup('http://online.wsj.com/itp') return self.index_to_soup('http://online.wsj.com/itp')
def wsj_add_feed(self,feeds,title,url):
self.log('Found section:', title)
if url.endswith('whatsnews'):
articles = self.wsj_find_wn_articles(url)
else:
articles = self.wsj_find_articles(url)
if articles:
feeds.append((title, articles))
return feeds
def parse_index(self): def parse_index(self):
soup = self.wsj_get_index() soup = self.wsj_get_index()
@ -82,25 +93,62 @@ class WallStreetJournal(BasicNewsRecipe):
div = soup.find('div', attrs={'class':'itpHeader'}) div = soup.find('div', attrs={'class':'itpHeader'})
div = div.find('ul', attrs={'class':'tab'}) div = div.find('ul', attrs={'class':'tab'})
for a in div.findAll('a', href=lambda x: x and '/itp/' in x): for a in div.findAll('a', href=lambda x: x and '/itp/' in x):
pageone = a['href'].endswith('pageone')
if pageone:
title = 'Front Section'
url = 'http://online.wsj.com' + a['href']
feeds = self.wsj_add_feed(feeds,title,url)
title = 'What''s News'
url = url.replace('pageone','whatsnews')
feeds = self.wsj_add_feed(feeds,title,url)
else:
title = self.tag_to_string(a) title = self.tag_to_string(a)
url = 'http://online.wsj.com' + a['href'] url = 'http://online.wsj.com' + a['href']
self.log('Found section:', title) feeds = self.wsj_add_feed(feeds,title,url)
articles = self.wsj_find_articles(url)
if articles:
feeds.append((title, articles))
return feeds return feeds
def wsj_find_wn_articles(self, url):
soup = self.index_to_soup(url)
articles = []
whats_news = soup.find('div', attrs={'class':lambda x: x and 'whatsNews-simple' in x})
if whats_news is not None:
for a in whats_news.findAll('a', href=lambda x: x and '/article/' in x):
container = a.findParent(['p'])
meta = a.find(attrs={'class':'meta_sectionName'})
if meta is not None:
meta.extract()
title = self.tag_to_string(a).strip()
url = a['href']
desc = ''
if container is not None:
desc = self.tag_to_string(container)
articles.append({'title':title, 'url':url,
'description':desc, 'date':''})
self.log('\tFound WN article:', title)
return articles
def wsj_find_articles(self, url): def wsj_find_articles(self, url):
soup = self.index_to_soup(url) soup = self.index_to_soup(url)
whats_news = soup.find('div', attrs={'class':lambda x: x and whats_news = soup.find('div', attrs={'class':lambda x: x and 'whatsNews-simple' in x})
'whatsNews-simple' in x})
if whats_news is not None: if whats_news is not None:
whats_news.extract() whats_news.extract()
articles = [] articles = []
flavorarea = soup.find('div', attrs={'class':lambda x: x and 'ahed' in x})
if flavorarea is not None:
flavorstory = flavorarea.find('a', href=lambda x: x and x.startswith('/article'))
if flavorstory is not None:
flavorstory['class'] = 'mjLinkItem'
metapage = soup.find('span', attrs={'class':lambda x: x and 'meta_sectionName' in x})
if metapage is not None:
flavorstory.append( copy.copy(metapage) ) #metapage should always be A1 because that should be first on the page
for a in soup.findAll('a', attrs={'class':'mjLinkItem'}, href=True): for a in soup.findAll('a', attrs={'class':'mjLinkItem'}, href=True):
container = a.findParent(['li', 'div']) container = a.findParent(['li', 'div'])
meta = a.find(attrs={'class':'meta_sectionName'}) meta = a.find(attrs={'class':'meta_sectionName'})
@ -118,26 +166,9 @@ class WallStreetJournal(BasicNewsRecipe):
self.log('\tFound article:', title) self.log('\tFound article:', title)
'''
# Find related articles
a.extract()
for a in container.findAll('a', href=lambda x: x and '/article/'
in x and 'articleTabs' not in x):
url = a['href']
if not url.startswith('http:'):
url = 'http://online.wsj.com'+url
title = self.tag_to_string(a).strip()
if not title or title.startswith('['): continue
if title:
articles.append({'title':self.tag_to_string(a),
'url':url, 'description':'', 'date':''})
self.log('\t\tFound related:', title)
'''
return articles return articles
def cleanup(self): def cleanup(self):
self.browser.open('http://online.wsj.com/logout?url=http://online.wsj.com') self.browser.open('http://online.wsj.com/logout?url=http://online.wsj.com')

View File

@ -2,7 +2,7 @@ __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
__appname__ = 'calibre' __appname__ = 'calibre'
__version__ = '0.7.3' __version__ = '0.7.4'
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>" __author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
import re import re

View File

@ -6,8 +6,7 @@ __docformat__ = 'restructuredtext en'
import cStringIO, ctypes, datetime, os, re, shutil, subprocess, sys, tempfile, time import cStringIO, ctypes, datetime, os, re, shutil, subprocess, sys, tempfile, time
from calibre.constants import __appname__, __version__, DEBUG
from calibre.constants import DEBUG
from calibre import fit_image 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
@ -79,7 +78,7 @@ class ITUNES(DevicePlugin):
supported_platforms = ['osx','windows'] supported_platforms = ['osx','windows']
author = 'GRiker' author = 'GRiker'
#: The version of this plugin as a 3-tuple (major, minor, revision) #: The version of this plugin as a 3-tuple (major, minor, revision)
version = (0,6,0) version = (0,7,0)
OPEN_FEEDBACK_MESSAGE = _( OPEN_FEEDBACK_MESSAGE = _(
'Apple device detected, launching iTunes, please wait ...') 'Apple device detected, launching iTunes, please wait ...')
@ -294,7 +293,7 @@ class ITUNES(DevicePlugin):
'author':[book.artist()], 'author':[book.artist()],
'lib_book':library_books[this_book.path] if this_book.path in library_books else None, 'lib_book':library_books[this_book.path] if this_book.path in library_books else None,
'dev_book':book, 'dev_book':book,
'uuid': book.album() 'uuid': book.composer()
} }
if self.report_progress is not None: if self.report_progress is not None:
@ -330,7 +329,7 @@ class ITUNES(DevicePlugin):
'title':book.Name, 'title':book.Name,
'author':book.Artist, 'author':book.Artist,
'lib_book':library_books[this_book.path] if this_book.path in library_books else None, 'lib_book':library_books[this_book.path] if this_book.path in library_books else None,
'uuid': book.Album 'uuid': book.Composer
} }
if self.report_progress is not None: if self.report_progress is not None:
@ -1426,10 +1425,10 @@ class ITUNES(DevicePlugin):
attempts = 9 attempts = 9
while attempts: while attempts:
# Try by uuid - only one hit # Try by uuid - only one hit
hits = dev_books.Search(search['uuid'],self.SearchField.index('Albums')) hits = dev_books.Search(search['uuid'],self.SearchField.index('All'))
if hits: if hits:
hit = hits[0] hit = hits[0]
self.log.info(" found '%s' by %s (%s)" % (hit.Name, hit.Artist, hit.Album)) self.log.info(" found '%s' by %s (%s)" % (hit.Name, hit.Artist, hit.Composer))
return hit return hit
# Try by author - there could be multiple hits # Try by author - there could be multiple hits
@ -1438,7 +1437,7 @@ class ITUNES(DevicePlugin):
for hit in hits: for hit in hits:
if hit.Name == search['title']: if hit.Name == search['title']:
if DEBUG: if DEBUG:
self.log.info(" found '%s' by %s (%s)" % (hit.Name, hit.Artist, hit.Album)) self.log.info(" found '%s' by %s (%s)" % (hit.Name, hit.Artist, hit.Composer))
return hit return hit
attempts -= 1 attempts -= 1
@ -1493,11 +1492,11 @@ class ITUNES(DevicePlugin):
if 'uuid' in search: if 'uuid' in search:
if DEBUG: if DEBUG:
self.log.info(" searching by uuid '%s' ..." % search['uuid']) self.log.info(" searching by uuid '%s' ..." % search['uuid'])
hits = lib_books.Search(search['uuid'],self.SearchField.index('Albums')) hits = lib_books.Search(search['uuid'],self.SearchField.index('All'))
if hits: if hits:
hit = hits[0] hit = hits[0]
if DEBUG: if DEBUG:
self.log.info(" found '%s' by %s (%s)" % (hit.Name, hit.Artist, hit.Album)) self.log.info(" found '%s' by %s (%s)" % (hit.Name, hit.Artist, hit.Composer))
return hit return hit
if DEBUG: if DEBUG:
@ -1507,7 +1506,7 @@ class ITUNES(DevicePlugin):
for hit in hits: for hit in hits:
if hit.Name == search['title']: if hit.Name == search['title']:
if DEBUG: if DEBUG:
self.log.info(" found '%s' by %s (%s)" % (hit.Name, hit.Artist, hit.Album)) self.log.info(" found '%s' by %s (%s)" % (hit.Name, hit.Artist, hit.Composer))
return hit return hit
attempts -= 1 attempts -= 1
@ -1558,6 +1557,10 @@ class ITUNES(DevicePlugin):
return thumb.getvalue() return thumb.getvalue()
except: except:
self.log.error(" error generating thumb for '%s'" % book.name()) self.log.error(" error generating thumb for '%s'" % book.name())
try:
zfw.close()
except:
pass
return None return None
elif iswindows: elif iswindows:
@ -1587,6 +1590,10 @@ class ITUNES(DevicePlugin):
return thumb.getvalue() return thumb.getvalue()
except: except:
self.log.error(" error generating thumb for '%s'" % book.Name) self.log.error(" error generating thumb for '%s'" % book.Name)
try:
zfw.close()
except:
pass
return None return None
def _get_device_book_size(self, file, compressed_size): def _get_device_book_size(self, file, compressed_size):
@ -1925,6 +1932,7 @@ class ITUNES(DevicePlugin):
self.log.error(" could not confirm valid iTunes.media_dir from %s" % 'com.apple.itunes') self.log.error(" could not confirm valid iTunes.media_dir from %s" % 'com.apple.itunes')
self.log.error(" media_dir: %s" % media_dir) self.log.error(" media_dir: %s" % media_dir)
if DEBUG: if DEBUG:
self.log.info(" %s %s" % (__appname__, __version__))
self.log.info(" [OSX %s - %s (%s), driver version %d.%d.%d]" % self.log.info(" [OSX %s - %s (%s), driver version %d.%d.%d]" %
(self.iTunes.name(), self.iTunes.version(), self.initial_status, (self.iTunes.name(), self.iTunes.version(), self.initial_status,
self.version[0],self.version[1],self.version[2])) self.version[0],self.version[1],self.version[2]))
@ -1954,6 +1962,7 @@ class ITUNES(DevicePlugin):
self.log.error(" '%s' not found" % media_dir) self.log.error(" '%s' not found" % media_dir)
if DEBUG: if DEBUG:
self.log.info(" %s %s" % (__appname__, __version__))
self.log.info(" [Windows %s - %s (%s), driver version %d.%d.%d]" % self.log.info(" [Windows %s - %s (%s), driver version %d.%d.%d]" %
(self.iTunes.Windows[0].name, self.iTunes.Version, self.initial_status, (self.iTunes.Windows[0].name, self.iTunes.Version, self.initial_status,
self.version[0],self.version[1],self.version[2])) self.version[0],self.version[1],self.version[2]))
@ -2041,7 +2050,7 @@ class ITUNES(DevicePlugin):
elif iswindows: elif iswindows:
dev_pl = self._get_device_books_playlist() dev_pl = self._get_device_books_playlist()
hits = dev_pl.Search(cached_book['uuid'],self.SearchField.index('Albums')) hits = dev_pl.Search(cached_book['uuid'],self.SearchField.index('All'))
if hits: if hits:
hit = hits[0] hit = hits[0]
if False: if False:
@ -2095,7 +2104,7 @@ class ITUNES(DevicePlugin):
self.iTunes.delete(cached_book['lib_book']) self.iTunes.delete(cached_book['lib_book'])
except: except:
if DEBUG: if DEBUG:
self.log.info(" '%s' not found in iTunes" % cached_book['title']) self.log.info(" unable to remove '%s' from iTunes" % cached_book['title'])
elif iswindows: elif iswindows:
''' '''
@ -2107,13 +2116,14 @@ class ITUNES(DevicePlugin):
path = book.Location path = book.Location
except: except:
book = self._find_library_book(cached_book) book = self._find_library_book(cached_book)
path = book.Location
if book: if book:
storage_path = os.path.split(book.Location) storage_path = os.path.split(path)
if book.Location.startswith(self.iTunes_media): if path.startswith(self.iTunes_media):
if DEBUG: if DEBUG:
self.log.info(" removing '%s' at %s" % self.log.info(" removing '%s' at %s" %
(cached_book['title'], book.Location)) (cached_book['title'], path))
try: try:
os.remove(path) os.remove(path)
except: except:
@ -2134,7 +2144,7 @@ class ITUNES(DevicePlugin):
book.Delete() book.Delete()
except: except:
if DEBUG: if DEBUG:
self.log.info(" '%s' not found in iTunes" % cached_book['title']) self.log.info(" unable to remove '%s' from iTunes" % cached_book['title'])
def _update_epub_metadata(self, fpath, metadata): def _update_epub_metadata(self, fpath, metadata):
''' '''
@ -2241,14 +2251,16 @@ class ITUNES(DevicePlugin):
if isosx: if isosx:
if lb_added: if lb_added:
lb_added.album.set(metadata.uuid) lb_added.album.set(metadata.title)
lb_added.composer.set(metadata.uuid)
lb_added.description.set("%s %s" % (self.description_prefix,strftime('%Y-%m-%d %H:%M:%S'))) lb_added.description.set("%s %s" % (self.description_prefix,strftime('%Y-%m-%d %H:%M:%S')))
lb_added.enabled.set(True) lb_added.enabled.set(True)
lb_added.sort_artist.set(metadata.author_sort.title()) lb_added.sort_artist.set(metadata.author_sort.title())
lb_added.sort_name.set(this_book.title_sorter) lb_added.sort_name.set(this_book.title_sorter)
if db_added: if db_added:
db_added.album.set(metadata.uuid) db_added.album.set(metadata.title)
db_added.composer.set(metadata.uuid)
db_added.description.set("%s %s" % (self.description_prefix,strftime('%Y-%m-%d %H:%M:%S'))) db_added.description.set("%s %s" % (self.description_prefix,strftime('%Y-%m-%d %H:%M:%S')))
db_added.enabled.set(True) db_added.enabled.set(True)
db_added.sort_artist.set(metadata.author_sort.title()) db_added.sort_artist.set(metadata.author_sort.title())
@ -2296,14 +2308,16 @@ class ITUNES(DevicePlugin):
elif iswindows: elif iswindows:
if lb_added: if lb_added:
lb_added.Album = metadata.uuid lb_added.Album = metadata.title
lb_added.Composer = metadata.uuid
lb_added.Description = ("%s %s" % (self.description_prefix,strftime('%Y-%m-%d %H:%M:%S'))) lb_added.Description = ("%s %s" % (self.description_prefix,strftime('%Y-%m-%d %H:%M:%S')))
lb_added.Enabled = True lb_added.Enabled = True
lb_added.SortArtist = (metadata.author_sort.title()) lb_added.SortArtist = (metadata.author_sort.title())
lb_added.SortName = (this_book.title_sorter) lb_added.SortName = (this_book.title_sorter)
if db_added: if db_added:
db_added.Album = metadata.uuid db_added.Album = metadata.title
db_added.Composer = metadata.uuid
db_added.Description = ("%s %s" % (self.description_prefix,strftime('%Y-%m-%d %H:%M:%S'))) db_added.Description = ("%s %s" % (self.description_prefix,strftime('%Y-%m-%d %H:%M:%S')))
db_added.Enabled = True db_added.Enabled = True
db_added.SortArtist = (metadata.author_sort.title()) db_added.SortArtist = (metadata.author_sort.title())

View File

@ -84,7 +84,7 @@ class EPUBOutput(OutputFormatPlugin):
OptionRecommendation(name='no_svg_cover', recommended_value=False, OptionRecommendation(name='no_svg_cover', recommended_value=False,
help=_('Do not use SVG for the book cover. Use this option if ' help=_('Do not use SVG for the book cover. Use this option if '
'your EPUB is going to be used ona device that does not ' 'your EPUB is going to be used on a device that does not '
'support SVG, like the iPhone or the JetBook Lite. ' 'support SVG, like the iPhone or the JetBook Lite. '
'Without this option, such devices will display the cover ' 'Without this option, such devices will display the cover '
'as a blank page.') 'as a blank page.')

View File

@ -93,10 +93,16 @@ class CoverView(QWidget): # {{{
self._current_pixmap_size = val self._current_pixmap_size = val
def do_layout(self): def do_layout(self):
if self.rect().width() == 0 or self.rect().height() == 0:
return
pixmap = self.pixmap pixmap = self.pixmap
pwidth, pheight = pixmap.width(), pixmap.height() pwidth, pheight = pixmap.width(), pixmap.height()
try:
self.pwidth, self.pheight = fit_image(pwidth, pheight, self.pwidth, self.pheight = fit_image(pwidth, pheight,
self.rect().width(), self.rect().height())[1:] self.rect().width(), self.rect().height())[1:]
except:
self.pwidth, self.pheight = self.rect().width()-1, \
self.rect().height()-1
self.current_pixmap_size = QSize(self.pwidth, self.pheight) self.current_pixmap_size = QSize(self.pwidth, self.pheight)
self.animation.setEndValue(self.current_pixmap_size) self.animation.setEndValue(self.current_pixmap_size)
@ -120,7 +126,8 @@ class CoverView(QWidget): # {{{
self.data = {'id':data.get('id', None)} self.data = {'id':data.get('id', None)}
if data.has_key('cover'): if data.has_key('cover'):
self.pixmap = QPixmap.fromImage(data.pop('cover')) self.pixmap = QPixmap.fromImage(data.pop('cover'))
if self.pixmap.isNull(): if self.pixmap.isNull() or self.pixmap.width() < 5 or \
self.pixmap.height() < 5:
self.pixmap = self.default_pixmap self.pixmap = self.default_pixmap
else: else:
self.pixmap = self.default_pixmap self.pixmap = self.default_pixmap

View File

@ -205,8 +205,8 @@ class CoverFlowMixin(object):
sm.select(index, sm.ClearAndSelect|sm.Rows) sm.select(index, sm.ClearAndSelect|sm.Rows)
self.library_view.setCurrentIndex(index) self.library_view.setCurrentIndex(index)
except: except:
pass import traceback
traceback.print_exc()
def sync_listview_to_cf(self, row): def sync_listview_to_cf(self, row):
self.cf_last_updated_at = time.time() self.cf_last_updated_at = time.time()

View File

@ -919,8 +919,8 @@ class DeviceBooksModel(BooksModel): # {{{
flags = QAbstractTableModel.flags(self, index) flags = QAbstractTableModel.flags(self, index)
if index.isValid() and self.editable: if index.isValid() and self.editable:
cname = self.column_map[index.column()] cname = self.column_map[index.column()]
if cname in ('title', 'authors') or (cname == 'collection' and \ if cname in ('title', 'authors') or \
self.db.supports_collections()): (cname == 'collections' and self.db.supports_collections()):
flags |= Qt.ItemIsEditable flags |= Qt.ItemIsEditable
return flags return flags

View File

@ -496,6 +496,7 @@ int PictureFlowPrivate::currentSlide() const
void PictureFlowPrivate::setCurrentSlide(int index) void PictureFlowPrivate::setCurrentSlide(int index)
{ {
animateTimer.stop();
step = 0; step = 0;
centerIndex = qBound(index, 0, slideImages->count()-1); centerIndex = qBound(index, 0, slideImages->count()-1);
target = centerIndex; target = centerIndex;

View File

@ -467,7 +467,8 @@ class CustomColumns(object):
books_ratings_link as bl, books_ratings_link as bl,
ratings as r ratings as r
WHERE {lt}.value={table}.id and bl.book={lt}.book and WHERE {lt}.value={table}.id and bl.book={lt}.book and
r.id = bl.rating and r.rating <> 0) avg_rating r.id = bl.rating and r.rating <> 0) avg_rating,
value AS sort
FROM {table}; FROM {table};
CREATE VIEW tag_browser_filtered_{table} AS SELECT CREATE VIEW tag_browser_filtered_{table} AS SELECT
@ -481,7 +482,8 @@ class CustomColumns(object):
ratings as r ratings as r
WHERE {lt}.value={table}.id AND bl.book={lt}.book AND WHERE {lt}.value={table}.id AND bl.book={lt}.book AND
r.id = bl.rating AND r.rating <> 0 AND r.id = bl.rating AND r.rating <> 0 AND
books_list_filter(bl.book)) avg_rating books_list_filter(bl.book)) avg_rating,
value AS sort
FROM {table}; FROM {table};
'''.format(lt=lt, table=table), '''.format(lt=lt, table=table),

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,9 +4,9 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: calibre 0.7.3\n" "Project-Id-Version: calibre 0.7.4\n"
"POT-Creation-Date: 2010-06-18 11:10+MDT\n" "POT-Creation-Date: 2010-06-19 18:08+MDT\n"
"PO-Revision-Date: 2010-06-18 11:10+MDT\n" "PO-Revision-Date: 2010-06-19 18:08+MDT\n"
"Last-Translator: Automatically generated\n" "Last-Translator: Automatically generated\n"
"Language-Team: LANGUAGE\n" "Language-Team: LANGUAGE\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -422,55 +422,55 @@ msgstr ""
msgid "Communicate with S60 phones." msgid "Communicate with S60 phones."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:78 #: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:77
msgid "Communicate with iBooks through iTunes." msgid "Communicate with iBooks through iTunes."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:84 #: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:83
msgid "Apple device detected, launching iTunes, please wait ..." msgid "Apple device detected, launching iTunes, please wait ..."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:227 #: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:226
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:230 #: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:229
msgid "Updating device metadata listing..." msgid "Updating device metadata listing..."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:301 #: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:300
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:338 #: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:337
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:842 #: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:841
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:876 #: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:875
msgid "%d of %d" msgid "%d of %d"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:345 #: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:344
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:881 #: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:880
msgid "finished" msgid "finished"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:519 #: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:518
msgid "" msgid ""
"Some books not found in iTunes database.\n" "Some books not found in iTunes database.\n"
"Delete using the iBooks app.\n" "Delete using the iBooks app.\n"
"Click 'Show Details' for a list." "Click 'Show Details' for a list."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:742 #: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:741
#: /home/kovid/work/calibre/src/calibre/devices/usbms/deviceconfig.py:28 #: /home/kovid/work/calibre/src/calibre/devices/usbms/deviceconfig.py:28
msgid "settings for device drivers" msgid "settings for device drivers"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:744 #: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:743
#: /home/kovid/work/calibre/src/calibre/devices/usbms/deviceconfig.py:30 #: /home/kovid/work/calibre/src/calibre/devices/usbms/deviceconfig.py:30
msgid "Ordered list of formats the device will accept" msgid "Ordered list of formats the device will accept"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:813 #: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:812
msgid "" msgid ""
"Some cover art could not be converted.\n" "Some cover art could not be converted.\n"
"Click 'Show Details' for a list." "Click 'Show Details' for a list."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2168 #: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2178
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:810 #: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:810
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:816 #: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:816
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:844 #: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:844
@ -1269,7 +1269,7 @@ msgid "Normally, if the input file has no cover and you don't specify one, a def
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:86 #: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:86
msgid "Do not use SVG for the book cover. Use this option if your EPUB is going to be used ona device that does not support SVG, like the iPhone or the JetBook Lite. Without this option, such devices will display the cover as a blank page." msgid "Do not use SVG for the book cover. Use this option if your EPUB is going to be used on a device that does not support SVG, like the iPhone or the JetBook Lite. Without this option, such devices will display the cover as a blank page."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:94 #: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:94
@ -1547,10 +1547,10 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:385 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:385
#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:34 #: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:34
#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:201
#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:202
#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:207
#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:208 #: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:208
#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:209
#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:214
#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:215
#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:184 #: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:184
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:99 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:99
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:67 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:67
@ -2886,7 +2886,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:22 #: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:22
#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:44 #: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:44
#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:53 #: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:53
#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:302 #: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:309
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:114 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:114
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:115 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:115
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:116 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:116
@ -2931,7 +2931,7 @@ msgstr ""
msgid "None" msgid "None"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:301 #: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:308
msgid "Click to open Book Details window" msgid "Click to open Book Details window"
msgstr "" msgstr ""

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff