From bd4fbc30603f5955b692b179eaf0237b589236da Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Dec 2010 12:45:03 -0700 Subject: [PATCH 01/15] Fix #7826 (Book Details window sizing on netbooks screen version) --- src/calibre/gui2/book_details.py | 7 ++++++- src/calibre/gui2/dialogs/book_info.py | 11 ++++++----- src/calibre/gui2/dialogs/book_info.ui | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/calibre/gui2/book_details.py b/src/calibre/gui2/book_details.py index 5214f1a1d5..b7394b9dd1 100644 --- a/src/calibre/gui2/book_details.py +++ b/src/calibre/gui2/book_details.py @@ -253,7 +253,12 @@ class BookInfo(QWebView): % (left_pane, right_pane))) 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() # }}} diff --git a/src/calibre/gui2/dialogs/book_info.py b/src/calibre/gui2/dialogs/book_info.py index df21314712..016f132c57 100644 --- a/src/calibre/gui2/dialogs/book_info.py +++ b/src/calibre/gui2/dialogs/book_info.py @@ -23,10 +23,6 @@ class BookInfo(QDialog, Ui_BookInfo): self.comments.sizeHint = self.comments_size_hint 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.current_row = None @@ -40,8 +36,13 @@ class BookInfo(QDialog, Ui_BookInfo): self.fit_cover.stateChanged.connect(self.toggle_cover_fit) 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): - return QSize(350, 350) + return QSize(350, 250) def toggle_cover_fit(self, state): dynamic.set('book_info_dialog_fit_cover', self.fit_cover.isChecked()) diff --git a/src/calibre/gui2/dialogs/book_info.ui b/src/calibre/gui2/dialogs/book_info.ui index 7eb6ccd3d3..2902a2c917 100644 --- a/src/calibre/gui2/dialogs/book_info.ui +++ b/src/calibre/gui2/dialogs/book_info.ui @@ -7,7 +7,7 @@ 0 0 917 - 783 + 480 From 85ae7c7d4f9a016502b77b1e2f2a4dc65eeb57ba Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Dec 2010 13:25:21 -0700 Subject: [PATCH 02/15] ... --- src/calibre/gui2/dialogs/metadata_bulk.ui | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/calibre/gui2/dialogs/metadata_bulk.ui b/src/calibre/gui2/dialogs/metadata_bulk.ui index cd644f88ba..ecb34d8e5b 100644 --- a/src/calibre/gui2/dialogs/metadata_bulk.ui +++ b/src/calibre/gui2/dialogs/metadata_bulk.ui @@ -399,14 +399,11 @@ Future conversion of these books will use the default settings. Change &cover - + - + - &No change - - - true + &Generate default cover @@ -417,13 +414,6 @@ Future conversion of these books will use the default settings. - - - - &Generate default cover - - - From 1a90427d8d2c2220c379146f76c52355470179f1 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Dec 2010 13:31:09 -0700 Subject: [PATCH 03/15] get_categories(): ignore empty is_mult values --- src/calibre/library/database2.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 33e4295f05..23375995ae 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -1153,6 +1153,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): else: vals = book[dex].split(mult) for val in vals: + if not val: continue try: (item_id, sort_val) = tids[cat][val] # let exceptions fly item = tcategories[cat].get(val, None) From 1b2bdfae81d83132cb02c1a48b1d558175824a27 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Dec 2010 13:46:09 -0700 Subject: [PATCH 04/15] EPUB Output: Ensure all files inside the generated EPUB have unique filenames, to support broken EPUB readers like Stanza, Aldiko, FBReader and Sigil --- src/calibre/ebooks/epub/output.py | 4 +- .../ebooks/oeb/transforms/filenames.py | 76 +++++++++++++++---- 2 files changed, 64 insertions(+), 16 deletions(-) diff --git a/src/calibre/ebooks/epub/output.py b/src/calibre/ebooks/epub/output.py index c5d11edc2b..4bc0f679cc 100644 --- a/src/calibre/ebooks/epub/output.py +++ b/src/calibre/ebooks/epub/output.py @@ -142,8 +142,8 @@ class EPUBOutput(OutputFormatPlugin): def convert(self, oeb, output_path, input_plugin, opts, log): self.log, self.opts, self.oeb = log, opts, oeb - #from calibre.ebooks.oeb.transforms.filenames import UniqueFilenames - #UniqueFilenames()(oeb, opts) + from calibre.ebooks.oeb.transforms.filenames import UniqueFilenames + UniqueFilenames()(oeb, opts) self.workaround_ade_quirks() self.workaround_webkit_quirks() diff --git a/src/calibre/ebooks/oeb/transforms/filenames.py b/src/calibre/ebooks/oeb/transforms/filenames.py index 2b22474d30..46f9fc5539 100644 --- a/src/calibre/ebooks/oeb/transforms/filenames.py +++ b/src/calibre/ebooks/oeb/transforms/filenames.py @@ -13,15 +13,16 @@ import cssutils 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 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.renamed_items_map = renamed_items_map def __call__(self, oeb, opts): self.log = oeb.logger @@ -49,7 +50,6 @@ class RenameFiles(object): if self.oeb.toc: self.fix_toc_entry(self.oeb.toc) - def fix_toc_entry(self, toc): if toc.href: href = urlnormalize(toc.href) @@ -66,18 +66,22 @@ class RenameFiles(object): self.fix_toc_entry(x) def url_replacer(self, orig_url): - url = urlnormalize(orig_url) - path, frag = urldefrag(url) - href = self.current_item.abshref(path) - replacement = self.rename_map.get(href, None) - if replacement is None: - return orig_url - replacement = self.current_item.relhref(replacement) - if frag: - replacement += '#' + frag - return replacement + url = urlnormalize(orig_url) + path, frag = urldefrag(url) + if self.renamed_items_map: + orig_item = self.renamed_items_map.get(self.current_item.href, self.current_item) + else: + orig_item = self.current_item -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' @@ -127,4 +131,48 @@ class UniqueFilenames(object): candidate = base + suffix + ext if candidate not in self.seen_filenames: 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) +# }}} From 5f91edf752bf938ddd6935156b676a30dbe28dc4 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Dec 2010 14:23:28 -0700 Subject: [PATCH 05/15] EPUB Output: Add an option to flatten the EPUB file structure, specially for FBReaderJ. Fixes #7788 (Flatten content of EPUB created by recipes to make them more compatible) --- src/calibre/ebooks/epub/output.py | 15 +++++++++++++-- src/calibre/gui2/convert/epub_output.py | 2 +- src/calibre/gui2/convert/epub_output.ui | 7 +++++++ src/calibre/gui2/tools.py | 4 ++++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/calibre/ebooks/epub/output.py b/src/calibre/ebooks/epub/output.py index 4bc0f679cc..2e254e99cc 100644 --- a/src/calibre/ebooks/epub/output.py +++ b/src/calibre/ebooks/epub/output.py @@ -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)]) @@ -142,8 +149,12 @@ class EPUBOutput(OutputFormatPlugin): def convert(self, oeb, output_path, input_plugin, opts, log): self.log, self.opts, self.oeb = log, opts, oeb - from calibre.ebooks.oeb.transforms.filenames import UniqueFilenames - UniqueFilenames()(oeb, opts) + if self.opts.epub_flatten: + 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_webkit_quirks() diff --git a/src/calibre/gui2/convert/epub_output.py b/src/calibre/gui2/convert/epub_output.py index c1ef6282f7..2fcbd751fe 100644 --- a/src/calibre/gui2/convert/epub_output.py +++ b/src/calibre/gui2/convert/epub_output.py @@ -21,7 +21,7 @@ class PluginWidget(Widget, Ui_Form): Widget.__init__(self, parent, ['dont_split_on_page_breaks', 'flow_size', 'no_default_epub_cover', 'no_svg_cover', - 'preserve_cover_aspect_ratio',] + 'preserve_cover_aspect_ratio', 'epub_flatten'] ) for i in range(2): self.opt_no_svg_cover.toggle() diff --git a/src/calibre/gui2/convert/epub_output.ui b/src/calibre/gui2/convert/epub_output.ui index abca2405e8..a0d9570226 100644 --- a/src/calibre/gui2/convert/epub_output.ui +++ b/src/calibre/gui2/convert/epub_output.ui @@ -81,6 +81,13 @@ + + + + &Flatten EPUB file structure + + + diff --git a/src/calibre/gui2/tools.py b/src/calibre/gui2/tools.py index fc84e88d09..d18cc61baf 100644 --- a/src/calibre/gui2/tools.py +++ b/src/calibre/gui2/tools.py @@ -236,6 +236,10 @@ def fetch_scheduled_recipe(arg): recs.append(('header', True, 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] if arg['username'] is not None: recs.append(('username', arg['username'], OptionRecommendation.HIGH)) From b3e77bac61060055de3e16208bce47335f1541d7 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Dec 2010 14:49:49 -0700 Subject: [PATCH 06/15] Fix #7890 (Drag/drop of new cover to book detail panel does not update cover browser) --- src/calibre/gui2/actions/add.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/calibre/gui2/actions/add.py b/src/calibre/gui2/actions/add.py index 014fa573d2..38c28661b7 100644 --- a/src/calibre/gui2/actions/add.py +++ b/src/calibre/gui2/actions/add.py @@ -120,6 +120,7 @@ class AddAction(InterfaceAction): if self.gui.current_view() is not self.gui.library_view: return db = self.gui.library_view.model().db + cover_changed = False current_idx = self.gui.library_view.currentIndex() if not current_idx.isValid(): return cid = db.id(current_idx.row()) @@ -133,12 +134,16 @@ class AddAction(InterfaceAction): if not pmap.isNull(): accept = True db.set_cover(cid, pmap) + cover_changed = True elif ext in BOOK_EXTENSIONS: db.add_format_with_hooks(cid, ext, path, index_is_id=True) accept = True if accept: event.accept() 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): if isinstance(paths, basestring): From 4881958675282342b8f5c092be2bf0b6bdb3d613 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Dec 2010 17:44:33 -0700 Subject: [PATCH 07/15] Fix Times of India recipe --- resources/recipes/toi.recipe | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/resources/recipes/toi.recipe b/resources/recipes/toi.recipe index 9539bcade7..643d120a36 100644 --- a/resources/recipes/toi.recipe +++ b/resources/recipes/toi.recipe @@ -8,9 +8,10 @@ class TimesOfIndia(BasicNewsRecipe): max_articles_per_feed = 25 no_stylesheets = True - keep_only_tags = [dict(attrs={'class':'prttabl'})] + keep_only_tags = [dict(attrs={'class':'maintable12'})] 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 = [ From a9ffac7885ce88baa95e475ce397401236d450a2 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Dec 2010 18:46:00 -0700 Subject: [PATCH 08/15] ... --- src/calibre/gui2/preferences/look_feel.py | 2 +- src/calibre/gui2/preferences/look_feel.ui | 42 +++++++++++++++-------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/calibre/gui2/preferences/look_feel.py b/src/calibre/gui2/preferences/look_feel.py index b2ba87d1e0..de1116c231 100644 --- a/src/calibre/gui2/preferences/look_feel.py +++ b/src/calibre/gui2/preferences/look_feel.py @@ -88,7 +88,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): name = unicode(fi.family()) self.font_display.setFont(font) - self.font_display.setText(_('Current font:') + ' ' + name + + self.font_display.setText(name + ' [%dpt]'%fi.pointSize()) def change_font(self, *args): diff --git a/src/calibre/gui2/preferences/look_feel.ui b/src/calibre/gui2/preferences/look_feel.ui index 91f45a155f..8e57f8c17e 100644 --- a/src/calibre/gui2/preferences/look_feel.ui +++ b/src/calibre/gui2/preferences/look_feel.ui @@ -183,6 +183,34 @@ + + + + + + Interface font: + + + font_display + + + + + + + true + + + + + + + + + Change &font (needs restart) + + + @@ -196,20 +224,6 @@ - - - - true - - - - - - - Change &font (needs restart) - - - From 491d1a8954519f4443c998f8f002ce809c7c498e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Dec 2010 18:57:04 -0700 Subject: [PATCH 09/15] MOBI metadata reader: Handle invalid PRC files with spurious image_offset headers --- src/calibre/ebooks/mobi/reader.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/calibre/ebooks/mobi/reader.py b/src/calibre/ebooks/mobi/reader.py index 48ece79f45..b39c4483ec 100644 --- a/src/calibre/ebooks/mobi/reader.py +++ b/src/calibre/ebooks/mobi/reader.py @@ -861,7 +861,10 @@ def get_metadata(stream): cover_index = mh.first_image_index + mh.exth.cover_offset data = mh.section_data(int(cover_index)) else: - data = mh.section_data(mh.first_image_index) + try: + data = mh.section_data(mh.first_image_index) + except: + data = '' buf = cStringIO.StringIO(data) try: im = PILImage.open(buf) From 61fb4f30e04733c7233162590dd56c03095a8ce8 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Dec 2010 19:06:44 -0700 Subject: [PATCH 10/15] MOBI Input: Handle the (rare) MOBI files that do not specify per paragraph text indents correctly. Fixes #7869 (Converting mobipocket to mobipocket removes paragraph indentation) --- src/calibre/ebooks/mobi/reader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/ebooks/mobi/reader.py b/src/calibre/ebooks/mobi/reader.py index b39c4483ec..ec55e67899 100644 --- a/src/calibre/ebooks/mobi/reader.py +++ b/src/calibre/ebooks/mobi/reader.py @@ -239,7 +239,7 @@ class MobiReader(object): self.base_css_rules = textwrap.dedent(''' 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 } From fd20c4ac7f0351ada9a6288da4e69b16e36586ef Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Dec 2010 19:18:14 -0700 Subject: [PATCH 11/15] Topaz metadata: Read metadata correctly from Topaz files that have MOBI file extensions --- src/calibre/ebooks/mobi/reader.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/calibre/ebooks/mobi/reader.py b/src/calibre/ebooks/mobi/reader.py index ec55e67899..02abc51cd3 100644 --- a/src/calibre/ebooks/mobi/reader.py +++ b/src/calibre/ebooks/mobi/reader.py @@ -29,6 +29,9 @@ from calibre.ebooks.metadata import MetaInformation from calibre.ebooks.metadata.opf2 import OPFCreator, OPF from calibre.ebooks.metadata.toc import TOC +class TopazError(ValueError): + pass + class EXTHHeader(object): def __init__(self, raw, codec, title): @@ -259,7 +262,7 @@ class MobiReader(object): raw = stream.read() 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.name = self.header[:32].replace('\x00', '') @@ -832,6 +835,15 @@ class MobiReader(object): im.save(open(path, 'wb'), format='JPEG') 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 log = Log() mi = MetaInformation(os.path.basename(stream.name), [_('Unknown')]) From 4c947784ce5f503f3da90135664074fb91391fa2 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Dec 2010 20:29:36 -0700 Subject: [PATCH 12/15] Fix #7887 (The news fetch for "Times of India" and "The Economic Times" (ENGLISH_ INDIA) not working.) --- resources/recipes/theeconomictimes_india.recipe | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/recipes/theeconomictimes_india.recipe b/resources/recipes/theeconomictimes_india.recipe index 92d2a64a70..d87eb91d0f 100644 --- a/resources/recipes/theeconomictimes_india.recipe +++ b/resources/recipes/theeconomictimes_india.recipe @@ -4,6 +4,7 @@ __copyright__ = '2008-2010, Darko Miletic ' economictimes.indiatimes.com ''' + from calibre.web.feeds.news import BasicNewsRecipe class TheEconomicTimes(BasicNewsRecipe): @@ -32,18 +33,17 @@ class TheEconomicTimes(BasicNewsRecipe): , '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')] def print_version(self, url): rest, sep, art = url.rpartition('/articleshow/') + return 'http://m.economictimes.com/PDAET/articleshow/' + art return 'http://economictimes.indiatimes.com/articleshow/' + art + '?prtpage=1' 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): return None return rurl From a1c7d0615c8c18c1920873d01c151777bbf30f88 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Dec 2010 20:33:00 -0700 Subject: [PATCH 13/15] Handle case of no metadata fetchers or fetcher returning None result --- src/calibre/ebooks/metadata/fetch.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/calibre/ebooks/metadata/fetch.py b/src/calibre/ebooks/metadata/fetch.py index b797a477d6..390f288d8e 100644 --- a/src/calibre/ebooks/metadata/fetch.py +++ b/src/calibre/ebooks/metadata/fetch.py @@ -145,7 +145,7 @@ class MetadataSource(Plugin): # {{{ setattr(w, '_'+x, cb) cb.setChecked(c.get(x, True)) w._layout.addWidget(cb) - + if self.has_html_comments: cb = QCheckBox(_('Convert comments downloaded from %s to plain text')%(self.name)) setattr(w, '_textcomments', cb) @@ -276,12 +276,13 @@ def result_index(source, result): return -1 def merge_results(one, two): - for x in two: - idx = result_index(one, x) - if idx < 0: - one.append(x) - else: - one[idx].smart_update(x) + if two is not None and one is not None: + for x in two: + idx = result_index(one, x) + if idx < 0: + one.append(x) + else: + one[idx].smart_update(x) 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.join() - results = list(fetchers[0].results) + results = list(fetchers[0].results) if fetchers else [] for fetcher in fetchers[1:]: merge_results(results, fetcher.results) From ef23a7c8c4685c46c8f200fa6fb552de7b7a092a Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Dec 2010 21:22:30 -0700 Subject: [PATCH 14/15] Fix #7876 (Books excluded by saved search via tag are visible on server) --- src/calibre/library/server/browse.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/calibre/library/server/browse.py b/src/calibre/library/server/browse.py index fa058eb303..37f024c08d 100644 --- a/src/calibre/library/server/browse.py +++ b/src/calibre/library/server/browse.py @@ -552,16 +552,18 @@ class BrowseServer(object): ids = self.search_cache('search:"%s"'%which) except: raise cherrypy.HTTPError(404, 'Search: %r not understood'%which) - elif category == 'newest': - ids = self.search_cache('') + all_ids = self.search_cache('') + if category == 'newest': + ids = all_ids hide_sort = 'true' elif category == 'allbooks': - ids = self.search_cache('') + ids = all_ids else: q = category if q == 'news': q = 'tags' 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] if category == 'newest': From ec7bd8628841063f90b35d8498eba2acdaf0eb6f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Dec 2010 23:23:17 -0700 Subject: [PATCH 15/15] When sorting the book list, keep the current book visible after the sort completes. Fixes #7504 (Book List to Maintain book pointer when the list is sorted by another column) --- src/calibre/gui2/library/views.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/calibre/gui2/library/views.py b/src/calibre/gui2/library/views.py index f724ca7b58..0e0cc0eec2 100644 --- a/src/calibre/gui2/library/views.py +++ b/src/calibre/gui2/library/views.py @@ -105,7 +105,8 @@ class BooksView(QTableView): # {{{ hv.setCursor(Qt.PointingHandCursor) self.selected_ids = [] 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 {{{ def column_header_context_handler(self, action=None, column=None): @@ -227,6 +228,7 @@ class BooksView(QTableView): # {{{ sm = self.selectionModel() for idx in indices: sm.select(idx, sm.Select|sm.Rows) + self.scroll_to_row(indices[0].row()) self.selected_ids = [] # }}}