mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge from trunk.
This commit is contained in:
commit
d358176125
@ -355,6 +355,25 @@ h2.library_name {
|
|||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#booklist > #pagelist { display: none; }
|
||||||
|
|
||||||
|
#goto_page_dialog ul {
|
||||||
|
list-style-type: none;
|
||||||
|
font-size: medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
#goto_page_dialog li {
|
||||||
|
margin-bottom: 1.5ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#goto_page_dialog a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#goto_page_dialog a:hover {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
#booklist .left .ui-button-text {
|
#booklist .left .ui-button-text {
|
||||||
font-size: medium;
|
font-size: medium;
|
||||||
|
@ -96,5 +96,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="book_details_dialog"></div>
|
<div id="book_details_dialog"></div>
|
||||||
|
<div id="goto_page_dialog"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -202,6 +202,23 @@ function previous_page() {
|
|||||||
else last_page();
|
else last_page();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function gp_internal(id) {
|
||||||
|
var gp = $('#goto_page_dialog');
|
||||||
|
gp.dialog('close');
|
||||||
|
var elem = $("#booklist #" + id);
|
||||||
|
load_page(elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
function goto_page() {
|
||||||
|
var gp = $('#goto_page_dialog');
|
||||||
|
var pl = $('#booklist > #pagelist');
|
||||||
|
gp.html(pl.html());
|
||||||
|
gp.dialog('option', 'title', pl.attr('title'));
|
||||||
|
gp.dialog('option', 'height', $(window).height() - 100);
|
||||||
|
gp.dialog('open');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function load_page(elem) {
|
function load_page(elem) {
|
||||||
if (elem.is(":visible")) return;
|
if (elem.is(":visible")) return;
|
||||||
var ld = elem.find('.load_data');
|
var ld = elem.find('.load_data');
|
||||||
@ -251,6 +268,12 @@ function booklist(hide_sort) {
|
|||||||
modal: true,
|
modal: true,
|
||||||
show: 'slide'
|
show: 'slide'
|
||||||
});
|
});
|
||||||
|
$("#goto_page_dialog").dialog({
|
||||||
|
autoOpen: false,
|
||||||
|
modal: true,
|
||||||
|
show: 'slide'
|
||||||
|
});
|
||||||
|
|
||||||
first_page();
|
first_page();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2009, Darko Miletic <darko.miletic at gmail.com>'
|
__copyright__ = '2009-2010, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
|
||||||
'''
|
'''
|
||||||
aljazeera.net
|
english.aljazeera.net
|
||||||
'''
|
'''
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
@ -13,40 +11,58 @@ class AlJazeera(BasicNewsRecipe):
|
|||||||
__author__ = 'Darko Miletic'
|
__author__ = 'Darko Miletic'
|
||||||
description = 'News from Middle East'
|
description = 'News from Middle East'
|
||||||
language = 'en'
|
language = 'en'
|
||||||
|
|
||||||
publisher = 'Al Jazeera'
|
publisher = 'Al Jazeera'
|
||||||
category = 'news, politics, middle east'
|
category = 'news, politics, middle east'
|
||||||
simultaneous_downloads = 1
|
delay = 1
|
||||||
delay = 4
|
oldest_article = 2
|
||||||
oldest_article = 1
|
|
||||||
max_articles_per_feed = 100
|
max_articles_per_feed = 100
|
||||||
no_stylesheets = True
|
no_stylesheets = True
|
||||||
encoding = 'iso-8859-1'
|
encoding = 'iso-8859-1'
|
||||||
remove_javascript = True
|
|
||||||
use_embedded_content = False
|
use_embedded_content = False
|
||||||
|
extra_css = """
|
||||||
|
body{font-family: Arial,sans-serif}
|
||||||
|
#ctl00_cphBody_dvSummary{font-weight: bold}
|
||||||
|
#dvArticleDate{font-size: small; color: #999999}
|
||||||
|
"""
|
||||||
|
conversion_options = {
|
||||||
|
'comment' : description
|
||||||
|
, 'tags' : category
|
||||||
|
, 'publisher' : publisher
|
||||||
|
, 'language' : language
|
||||||
|
}
|
||||||
|
|
||||||
html2lrf_options = [
|
keep_only_tags = [
|
||||||
'--comment', description
|
dict(attrs={'id':['DetailedTitle','ctl00_cphBody_dvSummary','dvArticleDate']})
|
||||||
, '--category', category
|
,dict(name='td',attrs={'class':'DetailedSummary'})
|
||||||
, '--publisher', publisher
|
|
||||||
, '--ignore-tables'
|
|
||||||
]
|
]
|
||||||
|
|
||||||
html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"\nlinearize_table=True'
|
|
||||||
|
|
||||||
keep_only_tags = [dict(name='div', attrs={'id':'ctl00_divContent'})]
|
|
||||||
|
|
||||||
remove_tags = [
|
remove_tags = [
|
||||||
dict(name=['object','link'])
|
dict(name=['object','link','table','meta','base','iframe','embed'])
|
||||||
,dict(name='td', attrs={'class':['MostActiveDescHeader','MostActiveDescBody']})
|
,dict(name='td', attrs={'class':['MostActiveDescHeader','MostActiveDescBody']})
|
||||||
]
|
]
|
||||||
|
|
||||||
feeds = [(u'AL JAZEERA ENGLISH (AJE)', u'http://english.aljazeera.net/Services/Rss/?PostingId=2007731105943979989' )]
|
feeds = [(u'AL JAZEERA ENGLISH (AJE)', u'http://english.aljazeera.net/Services/Rss/?PostingId=2007731105943979989' )]
|
||||||
|
|
||||||
|
def get_article_url(self, article):
|
||||||
|
artlurl = article.get('link', None)
|
||||||
|
return artlurl.replace('http://english.aljazeera.net//','http://english.aljazeera.net/')
|
||||||
|
|
||||||
def preprocess_html(self, soup):
|
def preprocess_html(self, soup):
|
||||||
for item in soup.findAll(style=True):
|
for item in soup.findAll(style=True):
|
||||||
del item['style']
|
del item['style']
|
||||||
for item in soup.findAll(face=True):
|
for item in soup.findAll(face=True):
|
||||||
del item['face']
|
del item['face']
|
||||||
|
td = soup.find('td',attrs={'class':'DetailedSummary'})
|
||||||
|
if td:
|
||||||
|
td.name = 'div'
|
||||||
|
spn = soup.find('span',attrs={'id':'DetailedTitle'})
|
||||||
|
if spn:
|
||||||
|
spn.name='h1'
|
||||||
|
for itm in soup.findAll('span', attrs={'id':['dvArticleDate','ctl00_cphBody_lblDate']}):
|
||||||
|
itm.name = 'div'
|
||||||
|
for alink in soup.findAll('a'):
|
||||||
|
if alink.string is not None:
|
||||||
|
tstr = alink.string
|
||||||
|
alink.replaceWith(tstr)
|
||||||
return soup
|
return soup
|
||||||
|
|
||||||
|
47
resources/recipes/globes_co_il.recipe
Normal file
47
resources/recipes/globes_co_il.recipe
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
from calibre.ebooks.BeautifulSoup import re
|
||||||
|
|
||||||
|
class AdvancedUserRecipe1283848012(BasicNewsRecipe):
|
||||||
|
description = 'This is Globes.co.il.'
|
||||||
|
cover_url = 'http://www.the7eye.org.il/SiteCollectionImages/BAKTANA/arye_avnery_010709_377.jpg'
|
||||||
|
title = u'Globes'
|
||||||
|
language = 'he'
|
||||||
|
__author__ = 'marbs'
|
||||||
|
extra_css='img {max-width:100%;} body{direction: rtl;max-width:100%;}title{direction: rtl; } article_description{direction: rtl; }, a.article{direction: rtl;max-width:100%;} calibre_feed_description{direction: rtl; }'
|
||||||
|
simultaneous_downloads = 5
|
||||||
|
remove_javascript = True
|
||||||
|
timefmt = '[%a, %d %b, %Y]'
|
||||||
|
oldest_article = 1
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
remove_attributes = ['width','style']
|
||||||
|
|
||||||
|
|
||||||
|
feeds = [(u'שוק ההון', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=585'),
|
||||||
|
(u'נדל"ן', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=607'),
|
||||||
|
(u'וול סטריט ושווקי העולם', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=1225'),
|
||||||
|
(u'ניתוח טכני', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=1294'),
|
||||||
|
(u'היי טק', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=594'),
|
||||||
|
(u'נתח שוק וצרכנות', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=821'),
|
||||||
|
(u'דין וחשבון', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=829'),
|
||||||
|
(u'רכב', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=3220'),
|
||||||
|
(u'דעות', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=845'),
|
||||||
|
(u'קניון המניות - טור שבועי', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=3175'),
|
||||||
|
(u'סביבה', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=3221')]
|
||||||
|
|
||||||
|
def print_version(self, url):
|
||||||
|
split1 = url.split("=")
|
||||||
|
print_url = 'http://www.globes.co.il/serve/globes/printwindow.asp?did=' + split1[1]
|
||||||
|
return print_url
|
||||||
|
|
||||||
|
|
||||||
|
def preprocess_html(self, soup):
|
||||||
|
soup.find('tr',attrs={'bgcolor':'black'}).findPrevious('tr').extract()
|
||||||
|
soup.find('tr',attrs={'bgcolor':'black'}).extract()
|
||||||
|
return soup
|
||||||
|
|
||||||
|
def fixChars(self,string):
|
||||||
|
# Replace lsquo (\x91)
|
||||||
|
fixed = re.sub("■","■",string)
|
||||||
|
return fixed
|
||||||
|
|
||||||
|
|
38
resources/recipes/hannoversche_zeitung.recipe
Normal file
38
resources/recipes/hannoversche_zeitung.recipe
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class AdvancedUserRecipe1287519083(BasicNewsRecipe):
|
||||||
|
title = u'Hannoversche Allgemeine Zeitung'
|
||||||
|
oldest_article = 1
|
||||||
|
__author__ = 'Artemis'
|
||||||
|
max_articles_per_feed = 30
|
||||||
|
language = 'de'
|
||||||
|
no_stylesheets = True
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
#(u'Schlagzeilen', u'http://www.haz.de/rss/feed/haz_schlagzeilen'),
|
||||||
|
(u'Politik', u'http://www.haz.de/rss/feed/haz_politik'),
|
||||||
|
(u'Wirtschaft', u'http://www.haz.de/rss/feed/haz_wirtschaft'),
|
||||||
|
(u'Panorama', u'http://www.haz.de/rss/feed/haz_panorama'),
|
||||||
|
(u'Wissen', u'http://www.haz.de/rss/feed/haz_wissen'),
|
||||||
|
(u'Kultur', u'http://www.haz.de/rss/feed/haz_kultur'),
|
||||||
|
(u'Sp\xe4tvorstellung', u'http://www.haz.de/rss/feed/haz_spaetvorstellung'),
|
||||||
|
(u'Hannover & Region', u'http://www.haz.de/rss/feed/haz_hannoverregion'),
|
||||||
|
(u'Netzgefl\xfcster', u'http://www.haz.de/rss/feed/haz_netzgefluester'),
|
||||||
|
(u'Meinung', u'http://www.haz.de/rss/feed/haz_meinung'),
|
||||||
|
(u'ZiSH', u'http://www.haz.de/rss/feed/haz_zish'),
|
||||||
|
(u'Medien', u'http://www.haz.de/rss/feed/haz_medien'),
|
||||||
|
#(u'Sport', u'http://www.haz.de/rss/feed/haz_sport'),
|
||||||
|
#(u'Hannover 96', u'http://www.haz.de/rss/feed/haz_hannover96')
|
||||||
|
]
|
||||||
|
|
||||||
|
remove_tags_before =dict(id='modul_artikel')
|
||||||
|
remove_tags_after =dict(id='articlecontent')
|
||||||
|
|
||||||
|
remove_tags = dict(id='articlesidebar')
|
||||||
|
|
||||||
|
remove_tags = [
|
||||||
|
dict(name='div', attrs={'class':['articlecomment',
|
||||||
|
'articlebookmark', 'teaser_anzeige', 'teaser_umfrage',
|
||||||
|
'navigation', 'subnavigation']})
|
||||||
|
]
|
||||||
|
|
@ -13,7 +13,6 @@ class IrishTimes(BasicNewsRecipe):
|
|||||||
language = 'en_IE'
|
language = 'en_IE'
|
||||||
timefmt = ' (%A, %B %d, %Y)'
|
timefmt = ' (%A, %B %d, %Y)'
|
||||||
|
|
||||||
|
|
||||||
oldest_article = 3
|
oldest_article = 3
|
||||||
no_stylesheets = True
|
no_stylesheets = True
|
||||||
simultaneous_downloads= 1
|
simultaneous_downloads= 1
|
||||||
@ -36,11 +35,10 @@ class IrishTimes(BasicNewsRecipe):
|
|||||||
def print_version(self, url):
|
def print_version(self, url):
|
||||||
if url.count('rss.feedsportal.com'):
|
if url.count('rss.feedsportal.com'):
|
||||||
u = 'http://www.irishtimes.com' + \
|
u = 'http://www.irishtimes.com' + \
|
||||||
(((url[69:].replace('0C','/')).replace('0A','0'))).replace('0Bhtml/story01..htm','_pf.html')
|
(((url[69:].replace('0C','/')).replace('0A','0'))).replace('0Bhtml/story01.htm','_pf.html')
|
||||||
else:
|
else:
|
||||||
u = url.replace('.html','_pf.html')
|
u = url.replace('.html','_pf.html')
|
||||||
return u
|
return u
|
||||||
|
|
||||||
|
|
||||||
def get_article_url(self, article):
|
def get_article_url(self, article):
|
||||||
return article.link
|
return article.link
|
||||||
|
18
resources/recipes/rds.recipe
Normal file
18
resources/recipes/rds.recipe
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class AdvancedUserRecipe1290013720(BasicNewsRecipe):
|
||||||
|
title = u'RDS'
|
||||||
|
__author__ = 'Nexus'
|
||||||
|
language = 'en_CA'
|
||||||
|
description = 'Hockey News'
|
||||||
|
oldest_article = 7
|
||||||
|
max_articles_per_feed = 25
|
||||||
|
no_stylesheets = True
|
||||||
|
remove_tags = [dict(name='div', attrs={'id':'rdsWrap'}),
|
||||||
|
dict(name='table', attrs={'id':'aVoir'}),
|
||||||
|
dict(name='div', attrs={'id':'imageChronique'})]
|
||||||
|
keep_only_tags = [dict(name='div', attrs={'id':['enteteChronique']}),
|
||||||
|
dict(name='div', attrs={'id':['contenuChronique']})]
|
||||||
|
|
||||||
|
|
||||||
|
feeds = [(u'RDS', u'http://www.rds.ca/hockey/fildepresse_rds.xml')]
|
19
resources/recipes/thn.recipe
Normal file
19
resources/recipes/thn.recipe
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class AdvancedUserRecipe1289990851(BasicNewsRecipe):
|
||||||
|
title = u'The Hockey News'
|
||||||
|
language = 'en_CA'
|
||||||
|
__author__ = 'Nexus'
|
||||||
|
oldest_article = 7
|
||||||
|
max_articles_per_feed = 25
|
||||||
|
no_stylesheets = True
|
||||||
|
remove_tags = [dict(name='div', attrs={'class':'article_info'}),
|
||||||
|
dict(name='div', attrs={'class':'photo_details'}),
|
||||||
|
dict(name='div', attrs={'class':'tool_menu'}),
|
||||||
|
dict(name='div', attrs={'id':'comments_container'}),
|
||||||
|
dict(name='div', attrs={'id':'wrapper'})]
|
||||||
|
keep_only_tags = [dict(name='h1', attrs={'class':['headline']}),
|
||||||
|
dict(name='div', attrs={'class':['box_container']})]
|
||||||
|
|
||||||
|
feeds = [(u'THN', u'http://www.thehockeynews.com/rss/all_categories.xml')]
|
||||||
|
|
@ -269,11 +269,6 @@ class HTMLInput(InputFormatPlugin):
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
OptionRecommendation(name='unwrap_factor', recommended_value=0.0,
|
|
||||||
help=_('Average line length for line breaking if the HTML is from a '
|
|
||||||
'previous partial conversion of a PDF file. Default is %default '
|
|
||||||
'which disables this.')),
|
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
def convert(self, stream, opts, file_ext, log,
|
def convert(self, stream, opts, file_ext, log,
|
||||||
|
@ -118,8 +118,8 @@ class SNBFile:
|
|||||||
return False
|
return False
|
||||||
if self.rev80 != SNBFile.REV80:
|
if self.rev80 != SNBFile.REV80:
|
||||||
return False
|
return False
|
||||||
if self.revA3 != SNBFile.REVA3:
|
# if self.revA3 != SNBFile.REVA3:
|
||||||
return False
|
# return False
|
||||||
if self.revZ1 != SNBFile.REVZ1:
|
if self.revZ1 != SNBFile.REVZ1:
|
||||||
return False
|
return False
|
||||||
if self.revZ2 != SNBFile.REVZ2:
|
if self.revZ2 != SNBFile.REVZ2:
|
||||||
|
@ -20,8 +20,7 @@ from calibre.gui2.dialogs.choose_format import ChooseFormatDialog
|
|||||||
from calibre.utils.ipc.job import BaseJob
|
from calibre.utils.ipc.job import BaseJob
|
||||||
from calibre.devices.scanner import DeviceScanner
|
from calibre.devices.scanner import DeviceScanner
|
||||||
from calibre.gui2 import config, error_dialog, Dispatcher, dynamic, \
|
from calibre.gui2 import config, error_dialog, Dispatcher, dynamic, \
|
||||||
warning_dialog, \
|
warning_dialog, info_dialog, choose_dir
|
||||||
question_dialog, info_dialog, choose_dir
|
|
||||||
from calibre.ebooks.metadata import authors_to_string
|
from calibre.ebooks.metadata import authors_to_string
|
||||||
from calibre import preferred_encoding, prints, force_unicode
|
from calibre import preferred_encoding, prints, force_unicode
|
||||||
from calibre.utils.filenames import ascii_filename
|
from calibre.utils.filenames import ascii_filename
|
||||||
@ -665,6 +664,16 @@ class DeviceMixin(object): # {{{
|
|||||||
if tweaks['auto_connect_to_folder']:
|
if tweaks['auto_connect_to_folder']:
|
||||||
self.connect_to_folder_named(tweaks['auto_connect_to_folder'])
|
self.connect_to_folder_named(tweaks['auto_connect_to_folder'])
|
||||||
|
|
||||||
|
def auto_convert_question(self, msg, autos):
|
||||||
|
autos = u'\n'.join(map(unicode, map(force_unicode, autos)))
|
||||||
|
return self.ask_a_yes_no_question(
|
||||||
|
_('No suitable formats'), msg,
|
||||||
|
buttons=QMessageBox.Yes|QMessageBox.Cancel,
|
||||||
|
ans_when_user_unavailable=True,
|
||||||
|
det_msg=autos,
|
||||||
|
show_copy_button=False
|
||||||
|
)
|
||||||
|
|
||||||
def set_default_thumbnail(self, height):
|
def set_default_thumbnail(self, height):
|
||||||
img = I('book.png', data=True)
|
img = I('book.png', data=True)
|
||||||
self.default_thumbnail = thumbnail(img, height, height)
|
self.default_thumbnail = thumbnail(img, height, height)
|
||||||
@ -978,11 +987,9 @@ class DeviceMixin(object): # {{{
|
|||||||
bad += auto
|
bad += auto
|
||||||
else:
|
else:
|
||||||
autos = [self.library_view.model().db.title(id, index_is_id=True) for id in auto]
|
autos = [self.library_view.model().db.title(id, index_is_id=True) for id in auto]
|
||||||
autos = '\n'.join('%s'%i for i in autos)
|
if self.auto_convert_question(
|
||||||
if question_dialog(self, _('No suitable formats'),
|
|
||||||
_('Auto convert the following books before sending via '
|
_('Auto convert the following books before sending via '
|
||||||
'email?'), det_msg=autos,
|
'email?'), autos):
|
||||||
buttons=QMessageBox.Yes|QMessageBox.Cancel):
|
|
||||||
self.iactions['Convert Books'].auto_convert_mail(to, fmts, delete_from_library, auto, format)
|
self.iactions['Convert Books'].auto_convert_mail(to, fmts, delete_from_library, auto, format)
|
||||||
|
|
||||||
if bad:
|
if bad:
|
||||||
@ -1085,11 +1092,9 @@ class DeviceMixin(object): # {{{
|
|||||||
break
|
break
|
||||||
if format is not None:
|
if format is not None:
|
||||||
autos = [self.library_view.model().db.title(id, index_is_id=True) for id in auto]
|
autos = [self.library_view.model().db.title(id, index_is_id=True) for id in auto]
|
||||||
autos = '\n'.join('%s'%i for i in autos)
|
if self.auto_convert_question(
|
||||||
if question_dialog(self, _('No suitable formats'),
|
|
||||||
_('Auto convert the following books before uploading to '
|
_('Auto convert the following books before uploading to '
|
||||||
'the device?'), det_msg=autos,
|
'the device?'), autos):
|
||||||
buttons=QMessageBox.Yes|QMessageBox.Cancel):
|
|
||||||
self.iactions['Convert Books'].auto_convert_catalogs(auto, format)
|
self.iactions['Convert Books'].auto_convert_catalogs(auto, format)
|
||||||
files = [f for f in files if f is not None]
|
files = [f for f in files if f is not None]
|
||||||
if not files:
|
if not files:
|
||||||
@ -1170,11 +1175,9 @@ class DeviceMixin(object): # {{{
|
|||||||
break
|
break
|
||||||
if format is not None:
|
if format is not None:
|
||||||
autos = [self.library_view.model().db.title(id, index_is_id=True) for id in auto]
|
autos = [self.library_view.model().db.title(id, index_is_id=True) for id in auto]
|
||||||
autos = '\n'.join('%s'%i for i in autos)
|
if self.auto_convert_question(
|
||||||
if question_dialog(self, _('No suitable formats'),
|
|
||||||
_('Auto convert the following books before uploading to '
|
_('Auto convert the following books before uploading to '
|
||||||
'the device?'), det_msg=autos,
|
'the device?'), autos):
|
||||||
buttons=QMessageBox.Yes|QMessageBox.Cancel):
|
|
||||||
self.iactions['Convert Books'].auto_convert_news(auto, format)
|
self.iactions['Convert Books'].auto_convert_news(auto, format)
|
||||||
files = [f for f in files if f is not None]
|
files = [f for f in files if f is not None]
|
||||||
for f in files:
|
for f in files:
|
||||||
@ -1289,11 +1292,9 @@ class DeviceMixin(object): # {{{
|
|||||||
bad += auto
|
bad += auto
|
||||||
else:
|
else:
|
||||||
autos = [self.library_view.model().db.title(id, index_is_id=True) for id in auto]
|
autos = [self.library_view.model().db.title(id, index_is_id=True) for id in auto]
|
||||||
autos = '\n'.join('%s'%i for i in autos)
|
if self.auto_convert_question(
|
||||||
if question_dialog(self, _('No suitable formats'),
|
|
||||||
_('Auto convert the following books before uploading to '
|
_('Auto convert the following books before uploading to '
|
||||||
'the device?'), det_msg=autos,
|
'the device?'), autos):
|
||||||
buttons=QMessageBox.Yes|QMessageBox.Cancel):
|
|
||||||
self.iactions['Convert Books'].auto_convert(auto, on_card, format)
|
self.iactions['Convert Books'].auto_convert(auto, on_card, format)
|
||||||
|
|
||||||
if bad:
|
if bad:
|
||||||
|
@ -315,6 +315,9 @@ class ToolBar(QToolBar): # {{{
|
|||||||
self.child_bar.addWidget(self.spacers[1])
|
self.child_bar.addWidget(self.spacers[1])
|
||||||
if gprefs['show_child_bar']:
|
if gprefs['show_child_bar']:
|
||||||
self.addWidget(self.spacers[3])
|
self.addWidget(self.spacers[3])
|
||||||
|
else:
|
||||||
|
for s in self.spacers[2:]:
|
||||||
|
s.setVisible(False)
|
||||||
|
|
||||||
def setup_tool_button(self, ac, menu_mode=None):
|
def setup_tool_button(self, ac, menu_mode=None):
|
||||||
ch = self.widgetForAction(ac)
|
ch = self.widgetForAction(ac)
|
||||||
|
@ -26,7 +26,8 @@ from calibre.utils.ipc.server import Server
|
|||||||
from calibre.library.database2 import LibraryDatabase2
|
from calibre.library.database2 import LibraryDatabase2
|
||||||
from calibre.customize.ui import interface_actions
|
from calibre.customize.ui import interface_actions
|
||||||
from calibre.gui2 import error_dialog, GetMetadata, open_local_file, \
|
from calibre.gui2 import error_dialog, GetMetadata, open_local_file, \
|
||||||
gprefs, max_available_height, config, info_dialog, Dispatcher
|
gprefs, max_available_height, config, info_dialog, Dispatcher, \
|
||||||
|
question_dialog
|
||||||
from calibre.gui2.cover_flow import CoverFlowMixin
|
from calibre.gui2.cover_flow import CoverFlowMixin
|
||||||
from calibre.gui2.widgets import ProgressIndicator
|
from calibre.gui2.widgets import ProgressIndicator
|
||||||
from calibre.gui2.update import UpdateMixin
|
from calibre.gui2.update import UpdateMixin
|
||||||
@ -181,8 +182,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
self.connect(self.donate_action, SIGNAL('triggered(bool)'), self.donate)
|
self.connect(self.donate_action, SIGNAL('triggered(bool)'), self.donate)
|
||||||
self.connect(self.restore_action, SIGNAL('triggered()'),
|
self.connect(self.restore_action, SIGNAL('triggered()'),
|
||||||
self.show_windows)
|
self.show_windows)
|
||||||
self.connect(self.system_tray_icon,
|
self.system_tray_icon.activated.connect(
|
||||||
SIGNAL('activated(QSystemTrayIcon::ActivationReason)'),
|
|
||||||
self.system_tray_icon_activated)
|
self.system_tray_icon_activated)
|
||||||
|
|
||||||
|
|
||||||
@ -250,7 +250,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
|
|
||||||
self.keyboard_interrupt.connect(self.quit, type=Qt.QueuedConnection)
|
self.keyboard_interrupt.connect(self.quit, type=Qt.QueuedConnection)
|
||||||
|
|
||||||
|
|
||||||
self.read_settings()
|
self.read_settings()
|
||||||
self.finalize_layout()
|
self.finalize_layout()
|
||||||
if self.tool_bar.showing_donate:
|
if self.tool_bar.showing_donate:
|
||||||
@ -301,6 +300,16 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
else:
|
else:
|
||||||
self.show_windows()
|
self.show_windows()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_minimized_to_tray(self):
|
||||||
|
return getattr(self, '__systray_minimized', False)
|
||||||
|
|
||||||
|
def ask_a_yes_no_question(self, title, msg, **kwargs):
|
||||||
|
awu = kwargs.pop('ans_when_user_unavailable', True)
|
||||||
|
if self.is_minimized_to_tray:
|
||||||
|
return awu
|
||||||
|
return question_dialog(self, title, msg, **kwargs)
|
||||||
|
|
||||||
def hide_windows(self):
|
def hide_windows(self):
|
||||||
for window in QApplication.topLevelWidgets():
|
for window in QApplication.topLevelWidgets():
|
||||||
if isinstance(window, (MainWindow, QDialog)) and \
|
if isinstance(window, (MainWindow, QDialog)) and \
|
||||||
@ -428,12 +437,14 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
def job_exception(self, job):
|
def job_exception(self, job):
|
||||||
if not hasattr(self, '_modeless_dialogs'):
|
if not hasattr(self, '_modeless_dialogs'):
|
||||||
self._modeless_dialogs = []
|
self._modeless_dialogs = []
|
||||||
|
minz = self.is_minimized_to_tray
|
||||||
if self.isVisible():
|
if self.isVisible():
|
||||||
for x in list(self._modeless_dialogs):
|
for x in list(self._modeless_dialogs):
|
||||||
if not x.isVisible():
|
if not x.isVisible():
|
||||||
self._modeless_dialogs.remove(x)
|
self._modeless_dialogs.remove(x)
|
||||||
try:
|
try:
|
||||||
if 'calibre.ebooks.DRMError' in job.details:
|
if 'calibre.ebooks.DRMError' in job.details:
|
||||||
|
if not minz:
|
||||||
d = error_dialog(self, _('Conversion Error'),
|
d = error_dialog(self, _('Conversion Error'),
|
||||||
_('<p>Could not convert: %s<p>It is a '
|
_('<p>Could not convert: %s<p>It is a '
|
||||||
'<a href="%s">DRM</a>ed book. You must first remove the '
|
'<a href="%s">DRM</a>ed book. You must first remove the '
|
||||||
@ -445,6 +456,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
self._modeless_dialogs.append(d)
|
self._modeless_dialogs.append(d)
|
||||||
return
|
return
|
||||||
if 'calibre.web.feeds.input.RecipeDisabled' in job.details:
|
if 'calibre.web.feeds.input.RecipeDisabled' in job.details:
|
||||||
|
if not minz:
|
||||||
msg = job.details
|
msg = job.details
|
||||||
msg = msg[msg.find('calibre.web.feeds.input.RecipeDisabled:'):]
|
msg = msg[msg.find('calibre.web.feeds.input.RecipeDisabled:'):]
|
||||||
msg = msg.partition(':')[-1]
|
msg = msg.partition(':')[-1]
|
||||||
@ -462,6 +474,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
|||||||
prints(job.details, file=sys.stderr)
|
prints(job.details, file=sys.stderr)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
if not minz:
|
||||||
d = error_dialog(self, _('Conversion Error'),
|
d = error_dialog(self, _('Conversion Error'),
|
||||||
_('<b>Failed</b>')+': '+unicode(job.description),
|
_('<b>Failed</b>')+': '+unicode(job.description),
|
||||||
det_msg=job.details)
|
det_msg=job.details)
|
||||||
|
@ -131,7 +131,8 @@ def comments_to_html(comments):
|
|||||||
def sanitize_comments_html(html):
|
def sanitize_comments_html(html):
|
||||||
text = html2text(html)
|
text = html2text(html)
|
||||||
md = markdown.Markdown(safe_mode=True)
|
md = markdown.Markdown(safe_mode=True)
|
||||||
return md.convert(text)
|
cleansed = re.sub('\n+', '', md.convert(text))
|
||||||
|
return cleansed
|
||||||
|
|
||||||
def test():
|
def test():
|
||||||
for pat, val in [
|
for pat, val in [
|
||||||
|
@ -147,7 +147,7 @@ class LibraryServer(ContentServer, MobileServer, XMLServer, OPDSServer, Cache,
|
|||||||
self.config['/'] = {
|
self.config['/'] = {
|
||||||
'tools.digest_auth.on' : True,
|
'tools.digest_auth.on' : True,
|
||||||
'tools.digest_auth.realm' : (
|
'tools.digest_auth.realm' : (
|
||||||
_('Password to access your calibre library. Username is ')
|
'Password to access your calibre library. Username is '
|
||||||
+ opts.username.strip()),
|
+ opts.username.strip()),
|
||||||
'tools.digest_auth.users' : {opts.username.strip():opts.password.strip()},
|
'tools.digest_auth.users' : {opts.username.strip():opts.password.strip()},
|
||||||
}
|
}
|
||||||
|
@ -43,18 +43,33 @@ def render_book_list(ids, prefix, suffix=''): # {{{
|
|||||||
<div class="loaded"></div>
|
<div class="loaded"></div>
|
||||||
</div>
|
</div>
|
||||||
'''
|
'''
|
||||||
rpages = []
|
pagelist_template = u'''\
|
||||||
|
<div class="pagelist">
|
||||||
|
<ul>
|
||||||
|
{pages}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
'''
|
||||||
|
rpages, lpages = [], []
|
||||||
for i, x in enumerate(pages):
|
for i, x in enumerate(pages):
|
||||||
pg, pos = x
|
pg, pos = x
|
||||||
ld = xml(json.dumps(pg), True)
|
ld = xml(json.dumps(pg), True)
|
||||||
|
start, end = pos+1, pos+len(pg)
|
||||||
rpages.append(page_template.format(i, ld,
|
rpages.append(page_template.format(i, ld,
|
||||||
xml(_('Loading, please wait')) + '…',
|
xml(_('Loading, please wait')) + '…',
|
||||||
start=pos+1, end=pos+len(pg), prefix=prefix))
|
start=start, end=end, prefix=prefix))
|
||||||
|
lpages.append(' '*20 + (u'<li><a href="#" title="Books {start} to {end}"'
|
||||||
|
' onclick="gp_internal(\'{id}\'); return false;"> '
|
||||||
|
'{start} to {end}</a></li>').format(start=start, end=end,
|
||||||
|
id='page%d'%i))
|
||||||
rpages = u'\n\n'.join(rpages)
|
rpages = u'\n\n'.join(rpages)
|
||||||
|
lpages = u'\n'.join(lpages)
|
||||||
|
pagelist = pagelist_template.format(pages=lpages)
|
||||||
|
|
||||||
templ = u'''\
|
templ = u'''\
|
||||||
<h3>{0} {suffix}</h3>
|
<h3>{0} {suffix}</h3>
|
||||||
<div id="booklist">
|
<div id="booklist">
|
||||||
|
<div id="pagelist" title="{goto}">{pagelist}</div>
|
||||||
<div class="listnav topnav">
|
<div class="listnav topnav">
|
||||||
{navbar}
|
{navbar}
|
||||||
</div>
|
</div>
|
||||||
@ -64,24 +79,31 @@ def render_book_list(ids, prefix, suffix=''): # {{{
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
'''
|
'''
|
||||||
|
gp_start = gp_end = ''
|
||||||
|
if len(pages) > 1:
|
||||||
|
gp_start = '<a href="#" onclick="goto_page(); return false;" title="%s">' % \
|
||||||
|
(_('Go to') + '…')
|
||||||
|
gp_end = '</a>'
|
||||||
navbar = u'''\
|
navbar = u'''\
|
||||||
<div class="navleft">
|
<div class="navleft">
|
||||||
<a href="#" onclick="first_page(); return false;">{first}</a>
|
<a href="#" onclick="first_page(); return false;">{first}</a>
|
||||||
<a href="#" onclick="previous_page(); return false;">{previous}</a>
|
<a href="#" onclick="previous_page(); return false;">{previous}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="navmiddle">
|
<div class="navmiddle">
|
||||||
<span class="start">0</span> to <span class="end">0</span> of {num}
|
{gp_start}
|
||||||
|
<span class="start">0</span> to <span class="end">0</span>
|
||||||
|
{gp_end}of {num}
|
||||||
</div>
|
</div>
|
||||||
<div class="navright">
|
<div class="navright">
|
||||||
<a href="#" onclick="next_page(); return false;">{next}</a>
|
<a href="#" onclick="next_page(); return false;">{next}</a>
|
||||||
<a href="#" onclick="last_page(); return false;">{last}</a>
|
<a href="#" onclick="last_page(); return false;">{last}</a>
|
||||||
</div>
|
</div>
|
||||||
'''.format(first=_('First'), last=_('Last'), previous=_('Previous'),
|
'''.format(first=_('First'), last=_('Last'), previous=_('Previous'),
|
||||||
next=_('Next'), num=num)
|
next=_('Next'), num=num, gp_start=gp_start, gp_end=gp_end)
|
||||||
|
|
||||||
return templ.format(_('Browsing %d books')%num, suffix=suffix,
|
return templ.format(_('Browsing %d books')%num, suffix=suffix,
|
||||||
pages=rpages, navbar=navbar)
|
pages=rpages, navbar=navbar, pagelist=pagelist,
|
||||||
|
goto=xml(_('Go to'), True) + '…')
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user