mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 10:44:09 -04:00
Merge from trunk
This commit is contained in:
commit
1617ffb510
@ -4,6 +4,7 @@ __copyright__ = '2008-2010, Darko Miletic <darko.miletic at gmail.com>'
|
|||||||
economictimes.indiatimes.com
|
economictimes.indiatimes.com
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
class TheEconomicTimes(BasicNewsRecipe):
|
class TheEconomicTimes(BasicNewsRecipe):
|
||||||
@ -32,18 +33,17 @@ class TheEconomicTimes(BasicNewsRecipe):
|
|||||||
, 'language' : language
|
, 'language' : language
|
||||||
}
|
}
|
||||||
|
|
||||||
keep_only_tags = [dict(attrs={'class':'printdiv'})]
|
|
||||||
remove_tags = [dict(name=['object','link','embed','iframe','base','table','meta'])]
|
|
||||||
remove_attributes = ['name']
|
|
||||||
|
|
||||||
|
remove_tags_before = dict(name='h1')
|
||||||
feeds = [(u'All articles', u'http://economictimes.indiatimes.com/rssfeedsdefault.cms')]
|
feeds = [(u'All articles', u'http://economictimes.indiatimes.com/rssfeedsdefault.cms')]
|
||||||
|
|
||||||
def print_version(self, url):
|
def print_version(self, url):
|
||||||
rest, sep, art = url.rpartition('/articleshow/')
|
rest, sep, art = url.rpartition('/articleshow/')
|
||||||
|
return 'http://m.economictimes.com/PDAET/articleshow/' + art
|
||||||
return 'http://economictimes.indiatimes.com/articleshow/' + art + '?prtpage=1'
|
return 'http://economictimes.indiatimes.com/articleshow/' + art + '?prtpage=1'
|
||||||
|
|
||||||
def get_article_url(self, article):
|
def get_article_url(self, article):
|
||||||
rurl = article.get('link', None)
|
rurl = article.get('guid', None)
|
||||||
if (rurl.find('/quickieslist/') > 0) or (rurl.find('/quickiearticleshow/') > 0):
|
if (rurl.find('/quickieslist/') > 0) or (rurl.find('/quickiearticleshow/') > 0):
|
||||||
return None
|
return None
|
||||||
return rurl
|
return rurl
|
||||||
|
@ -8,9 +8,10 @@ class TimesOfIndia(BasicNewsRecipe):
|
|||||||
max_articles_per_feed = 25
|
max_articles_per_feed = 25
|
||||||
|
|
||||||
no_stylesheets = True
|
no_stylesheets = True
|
||||||
keep_only_tags = [dict(attrs={'class':'prttabl'})]
|
keep_only_tags = [dict(attrs={'class':'maintable12'})]
|
||||||
remove_tags = [
|
remove_tags = [
|
||||||
dict(style=lambda x: x and 'float' in x)
|
dict(style=lambda x: x and 'float' in x),
|
||||||
|
dict(attrs={'class':'prvnxtbg'}),
|
||||||
]
|
]
|
||||||
|
|
||||||
feeds = [
|
feeds = [
|
||||||
|
@ -101,6 +101,13 @@ class EPUBOutput(OutputFormatPlugin):
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
|
OptionRecommendation(name='epub_flatten', recommended_value=False,
|
||||||
|
help=_('This option is needed only if you intend to use the EPUB'
|
||||||
|
' with FBReaderJ. It will flatten the file system inside the'
|
||||||
|
' EPUB, putting all files into the top level.')
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
recommendations = set([('pretty_print', True, OptionRecommendation.HIGH)])
|
recommendations = set([('pretty_print', True, OptionRecommendation.HIGH)])
|
||||||
@ -142,8 +149,12 @@ class EPUBOutput(OutputFormatPlugin):
|
|||||||
def convert(self, oeb, output_path, input_plugin, opts, log):
|
def convert(self, oeb, output_path, input_plugin, opts, log):
|
||||||
self.log, self.opts, self.oeb = log, opts, oeb
|
self.log, self.opts, self.oeb = log, opts, oeb
|
||||||
|
|
||||||
#from calibre.ebooks.oeb.transforms.filenames import UniqueFilenames
|
if self.opts.epub_flatten:
|
||||||
#UniqueFilenames()(oeb, opts)
|
from calibre.ebooks.oeb.transforms.filenames import FlatFilenames
|
||||||
|
FlatFilenames()(oeb, opts)
|
||||||
|
else:
|
||||||
|
from calibre.ebooks.oeb.transforms.filenames import UniqueFilenames
|
||||||
|
UniqueFilenames()(oeb, opts)
|
||||||
|
|
||||||
self.workaround_ade_quirks()
|
self.workaround_ade_quirks()
|
||||||
self.workaround_webkit_quirks()
|
self.workaround_webkit_quirks()
|
||||||
|
@ -276,12 +276,13 @@ def result_index(source, result):
|
|||||||
return -1
|
return -1
|
||||||
|
|
||||||
def merge_results(one, two):
|
def merge_results(one, two):
|
||||||
for x in two:
|
if two is not None and one is not None:
|
||||||
idx = result_index(one, x)
|
for x in two:
|
||||||
if idx < 0:
|
idx = result_index(one, x)
|
||||||
one.append(x)
|
if idx < 0:
|
||||||
else:
|
one.append(x)
|
||||||
one[idx].smart_update(x)
|
else:
|
||||||
|
one[idx].smart_update(x)
|
||||||
|
|
||||||
class MetadataSources(object):
|
class MetadataSources(object):
|
||||||
|
|
||||||
@ -337,7 +338,7 @@ def search(title=None, author=None, publisher=None, isbn=None, isbndb_key=None,
|
|||||||
manager(title, author, publisher, isbn, verbose)
|
manager(title, author, publisher, isbn, verbose)
|
||||||
manager.join()
|
manager.join()
|
||||||
|
|
||||||
results = list(fetchers[0].results)
|
results = list(fetchers[0].results) if fetchers else []
|
||||||
for fetcher in fetchers[1:]:
|
for fetcher in fetchers[1:]:
|
||||||
merge_results(results, fetcher.results)
|
merge_results(results, fetcher.results)
|
||||||
|
|
||||||
|
@ -29,6 +29,9 @@ from calibre.ebooks.metadata import MetaInformation
|
|||||||
from calibre.ebooks.metadata.opf2 import OPFCreator, OPF
|
from calibre.ebooks.metadata.opf2 import OPFCreator, OPF
|
||||||
from calibre.ebooks.metadata.toc import TOC
|
from calibre.ebooks.metadata.toc import TOC
|
||||||
|
|
||||||
|
class TopazError(ValueError):
|
||||||
|
pass
|
||||||
|
|
||||||
class EXTHHeader(object):
|
class EXTHHeader(object):
|
||||||
|
|
||||||
def __init__(self, raw, codec, title):
|
def __init__(self, raw, codec, title):
|
||||||
@ -239,7 +242,7 @@ class MobiReader(object):
|
|||||||
self.base_css_rules = textwrap.dedent('''
|
self.base_css_rules = textwrap.dedent('''
|
||||||
blockquote { margin: 0em 0em 0em 2em; text-align: justify }
|
blockquote { margin: 0em 0em 0em 2em; text-align: justify }
|
||||||
|
|
||||||
p { margin: 0em; text-align: justify }
|
p { margin: 0em; text-align: justify; text-indent: 1.5em }
|
||||||
|
|
||||||
.bold { font-weight: bold }
|
.bold { font-weight: bold }
|
||||||
|
|
||||||
@ -259,7 +262,7 @@ class MobiReader(object):
|
|||||||
|
|
||||||
raw = stream.read()
|
raw = stream.read()
|
||||||
if raw.startswith('TPZ'):
|
if raw.startswith('TPZ'):
|
||||||
raise ValueError(_('This is an Amazon Topaz book. It cannot be processed.'))
|
raise TopazError(_('This is an Amazon Topaz book. It cannot be processed.'))
|
||||||
|
|
||||||
self.header = raw[0:72]
|
self.header = raw[0:72]
|
||||||
self.name = self.header[:32].replace('\x00', '')
|
self.name = self.header[:32].replace('\x00', '')
|
||||||
@ -832,6 +835,15 @@ class MobiReader(object):
|
|||||||
im.save(open(path, 'wb'), format='JPEG')
|
im.save(open(path, 'wb'), format='JPEG')
|
||||||
|
|
||||||
def get_metadata(stream):
|
def get_metadata(stream):
|
||||||
|
stream.seek(0)
|
||||||
|
try:
|
||||||
|
raw = stream.read(3)
|
||||||
|
except:
|
||||||
|
raw = ''
|
||||||
|
stream.seek(0)
|
||||||
|
if raw == 'TPZ':
|
||||||
|
from calibre.ebooks.metadata.topaz import get_metadata
|
||||||
|
return get_metadata(stream)
|
||||||
from calibre.utils.logging import Log
|
from calibre.utils.logging import Log
|
||||||
log = Log()
|
log = Log()
|
||||||
mi = MetaInformation(os.path.basename(stream.name), [_('Unknown')])
|
mi = MetaInformation(os.path.basename(stream.name), [_('Unknown')])
|
||||||
@ -861,7 +873,10 @@ def get_metadata(stream):
|
|||||||
cover_index = mh.first_image_index + mh.exth.cover_offset
|
cover_index = mh.first_image_index + mh.exth.cover_offset
|
||||||
data = mh.section_data(int(cover_index))
|
data = mh.section_data(int(cover_index))
|
||||||
else:
|
else:
|
||||||
data = mh.section_data(mh.first_image_index)
|
try:
|
||||||
|
data = mh.section_data(mh.first_image_index)
|
||||||
|
except:
|
||||||
|
data = ''
|
||||||
buf = cStringIO.StringIO(data)
|
buf = cStringIO.StringIO(data)
|
||||||
try:
|
try:
|
||||||
im = PILImage.open(buf)
|
im = PILImage.open(buf)
|
||||||
|
@ -13,15 +13,16 @@ import cssutils
|
|||||||
|
|
||||||
from calibre.ebooks.oeb.base import rewrite_links, urlnormalize
|
from calibre.ebooks.oeb.base import rewrite_links, urlnormalize
|
||||||
|
|
||||||
class RenameFiles(object):
|
class RenameFiles(object): # {{{
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Rename files and adjust all links pointing to them. Note that the spine
|
Rename files and adjust all links pointing to them. Note that the spine
|
||||||
and manifest are not touched by this transform.
|
and manifest are not touched by this transform.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, rename_map):
|
def __init__(self, rename_map, renamed_items_map = None):
|
||||||
self.rename_map = rename_map
|
self.rename_map = rename_map
|
||||||
|
self.renamed_items_map = renamed_items_map
|
||||||
|
|
||||||
def __call__(self, oeb, opts):
|
def __call__(self, oeb, opts):
|
||||||
self.log = oeb.logger
|
self.log = oeb.logger
|
||||||
@ -49,7 +50,6 @@ class RenameFiles(object):
|
|||||||
if self.oeb.toc:
|
if self.oeb.toc:
|
||||||
self.fix_toc_entry(self.oeb.toc)
|
self.fix_toc_entry(self.oeb.toc)
|
||||||
|
|
||||||
|
|
||||||
def fix_toc_entry(self, toc):
|
def fix_toc_entry(self, toc):
|
||||||
if toc.href:
|
if toc.href:
|
||||||
href = urlnormalize(toc.href)
|
href = urlnormalize(toc.href)
|
||||||
@ -66,18 +66,22 @@ class RenameFiles(object):
|
|||||||
self.fix_toc_entry(x)
|
self.fix_toc_entry(x)
|
||||||
|
|
||||||
def url_replacer(self, orig_url):
|
def url_replacer(self, orig_url):
|
||||||
url = urlnormalize(orig_url)
|
url = urlnormalize(orig_url)
|
||||||
path, frag = urldefrag(url)
|
path, frag = urldefrag(url)
|
||||||
href = self.current_item.abshref(path)
|
if self.renamed_items_map:
|
||||||
replacement = self.rename_map.get(href, None)
|
orig_item = self.renamed_items_map.get(self.current_item.href, self.current_item)
|
||||||
if replacement is None:
|
else:
|
||||||
return orig_url
|
orig_item = self.current_item
|
||||||
replacement = self.current_item.relhref(replacement)
|
|
||||||
if frag:
|
|
||||||
replacement += '#' + frag
|
|
||||||
return replacement
|
|
||||||
|
|
||||||
class UniqueFilenames(object):
|
href = orig_item.abshref(path)
|
||||||
|
replacement = self.current_item.relhref(self.rename_map.get(href, href))
|
||||||
|
if frag:
|
||||||
|
replacement += '#' + frag
|
||||||
|
return replacement
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
class UniqueFilenames(object): # {{{
|
||||||
|
|
||||||
'Ensure that every item in the manifest has a unique filename'
|
'Ensure that every item in the manifest has a unique filename'
|
||||||
|
|
||||||
@ -127,4 +131,48 @@ class UniqueFilenames(object):
|
|||||||
candidate = base + suffix + ext
|
candidate = base + suffix + ext
|
||||||
if candidate not in self.seen_filenames:
|
if candidate not in self.seen_filenames:
|
||||||
return suffix
|
return suffix
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
class FlatFilenames(object): # {{{
|
||||||
|
|
||||||
|
'Ensure that every item in the manifest has a unique filename without subdirectories.'
|
||||||
|
|
||||||
|
def __call__(self, oeb, opts):
|
||||||
|
self.log = oeb.logger
|
||||||
|
self.opts = opts
|
||||||
|
self.oeb = oeb
|
||||||
|
|
||||||
|
self.rename_map = {}
|
||||||
|
self.renamed_items_map = {}
|
||||||
|
|
||||||
|
for item in list(oeb.manifest.items):
|
||||||
|
# Flatten URL by removing directories.
|
||||||
|
# Example: a/b/c/index.html -> a_b_c_index.html
|
||||||
|
nhref = item.href.replace("/", "_")
|
||||||
|
|
||||||
|
if item.href == nhref:
|
||||||
|
# URL hasn't changed, skip item.
|
||||||
|
continue
|
||||||
|
|
||||||
|
data = item.data
|
||||||
|
nhref = oeb.manifest.generate(href=nhref)[1]
|
||||||
|
nitem = oeb.manifest.add(item.id, nhref, item.media_type, data=data,
|
||||||
|
fallback=item.fallback)
|
||||||
|
self.rename_map[item.href] = nhref
|
||||||
|
self.renamed_items_map[nhref] = item
|
||||||
|
if item.spine_position is not None:
|
||||||
|
oeb.spine.insert(item.spine_position, nitem, item.linear)
|
||||||
|
oeb.spine.remove(item)
|
||||||
|
oeb.manifest.remove(item)
|
||||||
|
|
||||||
|
if self.rename_map:
|
||||||
|
self.log('Found non-flat filenames, renaming to support broken'
|
||||||
|
' EPUB readers like FBReader...')
|
||||||
|
from pprint import pformat
|
||||||
|
self.log.debug(pformat(self.rename_map))
|
||||||
|
self.log.debug(pformat(self.renamed_items_map))
|
||||||
|
|
||||||
|
renamer = RenameFiles(self.rename_map, self.renamed_items_map)
|
||||||
|
renamer(oeb, opts)
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
@ -120,6 +120,7 @@ class AddAction(InterfaceAction):
|
|||||||
if self.gui.current_view() is not self.gui.library_view:
|
if self.gui.current_view() is not self.gui.library_view:
|
||||||
return
|
return
|
||||||
db = self.gui.library_view.model().db
|
db = self.gui.library_view.model().db
|
||||||
|
cover_changed = False
|
||||||
current_idx = self.gui.library_view.currentIndex()
|
current_idx = self.gui.library_view.currentIndex()
|
||||||
if not current_idx.isValid(): return
|
if not current_idx.isValid(): return
|
||||||
cid = db.id(current_idx.row())
|
cid = db.id(current_idx.row())
|
||||||
@ -133,12 +134,16 @@ class AddAction(InterfaceAction):
|
|||||||
if not pmap.isNull():
|
if not pmap.isNull():
|
||||||
accept = True
|
accept = True
|
||||||
db.set_cover(cid, pmap)
|
db.set_cover(cid, pmap)
|
||||||
|
cover_changed = True
|
||||||
elif ext in BOOK_EXTENSIONS:
|
elif ext in BOOK_EXTENSIONS:
|
||||||
db.add_format_with_hooks(cid, ext, path, index_is_id=True)
|
db.add_format_with_hooks(cid, ext, path, index_is_id=True)
|
||||||
accept = True
|
accept = True
|
||||||
if accept:
|
if accept:
|
||||||
event.accept()
|
event.accept()
|
||||||
self.gui.library_view.model().current_changed(current_idx, current_idx)
|
self.gui.library_view.model().current_changed(current_idx, current_idx)
|
||||||
|
if cover_changed:
|
||||||
|
if self.gui.cover_flow:
|
||||||
|
self.gui.cover_flow.dataChanged()
|
||||||
|
|
||||||
def __add_filesystem_book(self, paths, allow_device=True):
|
def __add_filesystem_book(self, paths, allow_device=True):
|
||||||
if isinstance(paths, basestring):
|
if isinstance(paths, basestring):
|
||||||
|
@ -253,7 +253,12 @@ class BookInfo(QWebView):
|
|||||||
% (left_pane, right_pane)))
|
% (left_pane, right_pane)))
|
||||||
|
|
||||||
def mouseDoubleClickEvent(self, ev):
|
def mouseDoubleClickEvent(self, ev):
|
||||||
ev.ignore()
|
if self.width() - ev.x() < 25 or \
|
||||||
|
self.height() - ev.y() < 25:
|
||||||
|
# Filter out double clicks on the scroll bar
|
||||||
|
ev.accept()
|
||||||
|
else:
|
||||||
|
ev.ignore()
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ class PluginWidget(Widget, Ui_Form):
|
|||||||
Widget.__init__(self, parent,
|
Widget.__init__(self, parent,
|
||||||
['dont_split_on_page_breaks', 'flow_size',
|
['dont_split_on_page_breaks', 'flow_size',
|
||||||
'no_default_epub_cover', 'no_svg_cover',
|
'no_default_epub_cover', 'no_svg_cover',
|
||||||
'preserve_cover_aspect_ratio',]
|
'preserve_cover_aspect_ratio', 'epub_flatten']
|
||||||
)
|
)
|
||||||
for i in range(2):
|
for i in range(2):
|
||||||
self.opt_no_svg_cover.toggle()
|
self.opt_no_svg_cover.toggle()
|
||||||
|
@ -81,6 +81,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QCheckBox" name="opt_epub_flatten">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Flatten EPUB file structure</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
@ -23,10 +23,6 @@ class BookInfo(QDialog, Ui_BookInfo):
|
|||||||
self.comments.sizeHint = self.comments_size_hint
|
self.comments.sizeHint = self.comments_size_hint
|
||||||
self.view_func = view_func
|
self.view_func = view_func
|
||||||
|
|
||||||
desktop = QCoreApplication.instance().desktop()
|
|
||||||
screen_height = desktop.availableGeometry().height() - 100
|
|
||||||
self.resize(self.size().width(), screen_height)
|
|
||||||
|
|
||||||
|
|
||||||
self.view = view
|
self.view = view
|
||||||
self.current_row = None
|
self.current_row = None
|
||||||
@ -40,8 +36,13 @@ class BookInfo(QDialog, Ui_BookInfo):
|
|||||||
self.fit_cover.stateChanged.connect(self.toggle_cover_fit)
|
self.fit_cover.stateChanged.connect(self.toggle_cover_fit)
|
||||||
self.cover.resizeEvent = self.cover_view_resized
|
self.cover.resizeEvent = self.cover_view_resized
|
||||||
|
|
||||||
|
desktop = QCoreApplication.instance().desktop()
|
||||||
|
screen_height = desktop.availableGeometry().height() - 100
|
||||||
|
self.resize(self.size().width(), screen_height)
|
||||||
|
|
||||||
|
|
||||||
def comments_size_hint(self):
|
def comments_size_hint(self):
|
||||||
return QSize(350, 350)
|
return QSize(350, 250)
|
||||||
|
|
||||||
def toggle_cover_fit(self, state):
|
def toggle_cover_fit(self, state):
|
||||||
dynamic.set('book_info_dialog_fit_cover', self.fit_cover.isChecked())
|
dynamic.set('book_info_dialog_fit_cover', self.fit_cover.isChecked())
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>917</width>
|
<width>917</width>
|
||||||
<height>783</height>
|
<height>480</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -399,14 +399,11 @@ Future conversion of these books will use the default settings.</string>
|
|||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Change &cover</string>
|
<string>Change &cover</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QRadioButton" name="cover_no_change">
|
<widget class="QRadioButton" name="cover_generate">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&No change</string>
|
<string>&Generate default cover</string>
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -417,13 +414,6 @@ Future conversion of these books will use the default settings.</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="cover_generate">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Generate default cover</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -105,7 +105,8 @@ class BooksView(QTableView): # {{{
|
|||||||
hv.setCursor(Qt.PointingHandCursor)
|
hv.setCursor(Qt.PointingHandCursor)
|
||||||
self.selected_ids = []
|
self.selected_ids = []
|
||||||
self._model.about_to_be_sorted.connect(self.about_to_be_sorted)
|
self._model.about_to_be_sorted.connect(self.about_to_be_sorted)
|
||||||
self._model.sorting_done.connect(self.sorting_done)
|
self._model.sorting_done.connect(self.sorting_done,
|
||||||
|
type=Qt.QueuedConnection)
|
||||||
|
|
||||||
# Column Header Context Menu {{{
|
# Column Header Context Menu {{{
|
||||||
def column_header_context_handler(self, action=None, column=None):
|
def column_header_context_handler(self, action=None, column=None):
|
||||||
@ -227,6 +228,7 @@ class BooksView(QTableView): # {{{
|
|||||||
sm = self.selectionModel()
|
sm = self.selectionModel()
|
||||||
for idx in indices:
|
for idx in indices:
|
||||||
sm.select(idx, sm.Select|sm.Rows)
|
sm.select(idx, sm.Select|sm.Rows)
|
||||||
|
self.scroll_to_row(indices[0].row())
|
||||||
self.selected_ids = []
|
self.selected_ids = []
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
name = unicode(fi.family())
|
name = unicode(fi.family())
|
||||||
|
|
||||||
self.font_display.setFont(font)
|
self.font_display.setFont(font)
|
||||||
self.font_display.setText(_('Current font:') + ' ' + name +
|
self.font_display.setText(name +
|
||||||
' [%dpt]'%fi.pointSize())
|
' [%dpt]'%fi.pointSize())
|
||||||
|
|
||||||
def change_font(self, *args):
|
def change_font(self, *args):
|
||||||
|
@ -183,6 +183,34 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Interface font:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>font_display</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="font_display">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
|
<widget class="QPushButton" name="change_font_button">
|
||||||
|
<property name="text">
|
||||||
|
<string>Change &font (needs restart)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="9" column="0" colspan="2">
|
<item row="9" column="0" colspan="2">
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@ -196,20 +224,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="0">
|
|
||||||
<widget class="QLineEdit" name="font_display">
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="1">
|
|
||||||
<widget class="QPushButton" name="change_font_button">
|
|
||||||
<property name="text">
|
|
||||||
<string>Change &font (needs restart)</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
@ -236,6 +236,10 @@ def fetch_scheduled_recipe(arg):
|
|||||||
recs.append(('header', True, OptionRecommendation.HIGH))
|
recs.append(('header', True, OptionRecommendation.HIGH))
|
||||||
recs.append(('header_format', '%t', OptionRecommendation.HIGH))
|
recs.append(('header_format', '%t', OptionRecommendation.HIGH))
|
||||||
|
|
||||||
|
epub = load_defaults('epub_output')
|
||||||
|
if epub.get('epub_flatten', False):
|
||||||
|
recs.append(('epub_flatten', True, OptionRecommendation.HIGH))
|
||||||
|
|
||||||
args = [arg['recipe'], pt.name, recs]
|
args = [arg['recipe'], pt.name, recs]
|
||||||
if arg['username'] is not None:
|
if arg['username'] is not None:
|
||||||
recs.append(('username', arg['username'], OptionRecommendation.HIGH))
|
recs.append(('username', arg['username'], OptionRecommendation.HIGH))
|
||||||
|
@ -51,7 +51,7 @@ def config(defaults=None):
|
|||||||
c.add_opt('hyphenate_default_lang', default='en',
|
c.add_opt('hyphenate_default_lang', default='en',
|
||||||
help=_('Default language for hyphenation rules'))
|
help=_('Default language for hyphenation rules'))
|
||||||
c.add_opt('remember_current_page', default=True,
|
c.add_opt('remember_current_page', default=True,
|
||||||
help=_('Save the current position in the documentwhen quitting'))
|
help=_('Save the current position in the document, when quitting'))
|
||||||
|
|
||||||
fonts = c.add_group('FONTS', _('Font options'))
|
fonts = c.add_group('FONTS', _('Font options'))
|
||||||
fonts('serif_family', default='Times New Roman' if iswindows else 'Liberation Serif',
|
fonts('serif_family', default='Times New Roman' if iswindows else 'Liberation Serif',
|
||||||
|
@ -1153,6 +1153,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
else:
|
else:
|
||||||
vals = book[dex].split(mult)
|
vals = book[dex].split(mult)
|
||||||
for val in vals:
|
for val in vals:
|
||||||
|
if not val: continue
|
||||||
try:
|
try:
|
||||||
(item_id, sort_val) = tids[cat][val] # let exceptions fly
|
(item_id, sort_val) = tids[cat][val] # let exceptions fly
|
||||||
item = tcategories[cat].get(val, None)
|
item = tcategories[cat].get(val, None)
|
||||||
|
@ -552,16 +552,18 @@ class BrowseServer(object):
|
|||||||
ids = self.search_cache('search:"%s"'%which)
|
ids = self.search_cache('search:"%s"'%which)
|
||||||
except:
|
except:
|
||||||
raise cherrypy.HTTPError(404, 'Search: %r not understood'%which)
|
raise cherrypy.HTTPError(404, 'Search: %r not understood'%which)
|
||||||
elif category == 'newest':
|
all_ids = self.search_cache('')
|
||||||
ids = self.search_cache('')
|
if category == 'newest':
|
||||||
|
ids = all_ids
|
||||||
hide_sort = 'true'
|
hide_sort = 'true'
|
||||||
elif category == 'allbooks':
|
elif category == 'allbooks':
|
||||||
ids = self.search_cache('')
|
ids = all_ids
|
||||||
else:
|
else:
|
||||||
q = category
|
q = category
|
||||||
if q == 'news':
|
if q == 'news':
|
||||||
q = 'tags'
|
q = 'tags'
|
||||||
ids = self.db.get_books_for_category(q, cid)
|
ids = self.db.get_books_for_category(q, cid)
|
||||||
|
ids = [x for x in ids if x in all_ids]
|
||||||
|
|
||||||
items = [self.db.data._data[x] for x in ids]
|
items = [self.db.data._data[x] for x in ids]
|
||||||
if category == 'newest':
|
if category == 'newest':
|
||||||
|
Loading…
x
Reference in New Issue
Block a user