From f9a5cab366058a40a6c296bd12c82465d4f1c24a Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 29 Jan 2013 13:01:59 +0530 Subject: [PATCH 1/7] PDF Output: Add an option to add page numbers to the bottom of every page in the generated PDF file --- resources/compiled_coffeescript.zip | Bin 62268 -> 64128 bytes .../ebooks/conversion/plugins/pdf_output.py | 12 +++++++ src/calibre/ebooks/oeb/display/paged.coffee | 29 +++++++++++++++ src/calibre/ebooks/pdf/render/from_html.py | 24 ++++++++++++- src/calibre/gui2/convert/pdf_output.py | 2 +- src/calibre/gui2/convert/pdf_output.ui | 33 +++++++++++------- 6 files changed, 85 insertions(+), 15 deletions(-) diff --git a/resources/compiled_coffeescript.zip b/resources/compiled_coffeescript.zip index 8186cccaa6d4d0aaf5d45e4bf23fc8ef2124df1b..8948c66f6928d134184026510400bfc14ed2274c 100644 GIT binary patch delta 1295 zcmdn$Dzf}F&X)X5u?MffvP6I0N{*dSscXZ%JWn`wLq~=*Gq+}KYJy2 zQh=+5D2xZH04ufzssVc!NeSHBFykP4fF=T6lbDi{nU@Y^D``&t&Z5eV@Q&u>0&WpV zP@qNyA}F9ih8z@7Az)C%(k>`~zMs6?O-mT&A*4{5{E%0~9vWqO}x1D1LQ7k*K2(UzD0Q*+fq>tsDn5g zsBN;{2e!!vwAt989s%kU!qhqWLYDaCbvEJ-*t`eKHfg1K$)FUgQIMFPnpc{usZho%aT5nf&U9DbvbCAk&wrE*mV;`qPA|suaw;@Y9G% cvl+~s*Tptj{+AY$ # Read page margins from the document. First checks for an @page rule. @@ -102,6 +106,7 @@ class PagedDisplay # than max_col_width sm += Math.ceil( (col_width - this.max_col_width) / 2*n ) col_width = Math.max(100, ((ww - adjust)/n) - 2*sm) + this.col_width = col_width this.page_width = col_width + 2*sm this.screen_width = this.page_width * this.cols_per_screen this.current_page_height = window.innerHeight - this.margin_top - this.margin_bottom @@ -171,6 +176,30 @@ class PagedDisplay # log('Time to layout:', new Date().getTime() - start_time) return sm + create_header_footer: () -> + if this.header_template != null + this.header = document.createElement('div') + this.header.setAttribute('style', "overflow:hidden; display:block; position:absolute; left:#{ this.side_margin }px; top: 0px; height: #{ this.margin_top }px; width: #{ this.col_width }px; margin: 0; padding: 0") + document.body.appendChild(this.header) + if this.footer_template != null + this.footer = document.createElement('div') + this.footer.setAttribute('style', "overflow:hidden; display:block; position:absolute; left:#{ this.side_margin }px; top: #{ window.innerHeight - this.margin_bottom }px; height: #{ this.margin_bottom }px; width: #{ this.col_width }px; margin: 0; padding: 0") + document.body.appendChild(this.footer) + this.update_header_footer(1) + + position_header_footer: () -> + [left, top] = calibre_utils.viewport_to_document(0, 0, document.body.ownerDocument) + if this.header != null + this.header.style.setProperty('left', left+'px') + if this.footer != null + this.footer.style.setProperty('left', left+'px') + + update_header_footer: (pagenum) -> + if this.header != null + this.header.innerHTML = this.header_template.replace(/_PAGENUM_/g, pagenum+"") + if this.footer != null + this.footer.innerHTML = this.footer_template.replace(/_PAGENUM_/g, pagenum+"") + fit_images: () -> # Ensure no images are wider than the available width in a column. Note # that this method use getBoundingClientRect() which means it will diff --git a/src/calibre/ebooks/pdf/render/from_html.py b/src/calibre/ebooks/pdf/render/from_html.py index 6beedc5dd4..2cdc804a9e 100644 --- a/src/calibre/ebooks/pdf/render/from_html.py +++ b/src/calibre/ebooks/pdf/render/from_html.py @@ -161,6 +161,17 @@ class PDFWriter(QObject): debug=self.log.debug, compress=not opts.uncompressed_pdf, mark_links=opts.pdf_mark_links) + self.footer = opts.pdf_footer_template + if self.footer is None and opts.pdf_page_numbers: + self.footer = '

_PAGENUM_

' + self.header = opts.pdf_header_template + min_margin = 36 + if self.footer and opts.margin_bottom < min_margin: + self.log.warn('Bottom margin is too small for footer, increasing it.') + opts.margin_bottom = min_margin + if self.header and opts.margin_top < min_margin: + self.log.warn('Top margin is too small for header, increasing it.') + opts.margin_top = min_margin self.page.setViewportSize(QSize(self.doc.width(), self.doc.height())) self.render_queue = items @@ -264,6 +275,15 @@ class PDFWriter(QObject): py_bridge.value = book_indexing.all_links_and_anchors(); '''%(self.margin_top, 0, self.margin_bottom)) + if self.header: + self.bridge_value = self.header + evaljs('paged_display.header_template = py_bridge.value') + if self.footer: + self.bridge_value = self.footer + evaljs('paged_display.footer_template = py_bridge.value') + if self.header or self.footer: + evaljs('paged_display.create_header_footer();') + amap = self.bridge_value if not isinstance(amap, dict): amap = {'links':[], 'anchors':{}} # Some javascript error occurred @@ -272,6 +292,8 @@ class PDFWriter(QObject): mf = self.view.page().mainFrame() while True: self.doc.init_page() + if self.header or self.footer: + evaljs('paged_display.update_header_footer(%d)'%self.current_page_num) self.painter.save() mf.render(self.painter) self.painter.restore() @@ -279,7 +301,7 @@ class PDFWriter(QObject): self.doc.end_page() if not nsl[1] or nsl[0] <= 0: break - evaljs('window.scrollTo(%d, 0)'%nsl[0]) + evaljs('window.scrollTo(%d, 0); paged_display.position_header_footer();'%nsl[0]) if self.doc.errors_occurred: break diff --git a/src/calibre/gui2/convert/pdf_output.py b/src/calibre/gui2/convert/pdf_output.py index e0674d066c..98334d1709 100644 --- a/src/calibre/gui2/convert/pdf_output.py +++ b/src/calibre/gui2/convert/pdf_output.py @@ -22,7 +22,7 @@ class PluginWidget(Widget, Ui_Form): 'override_profile_size', 'paper_size', 'custom_size', 'preserve_cover_aspect_ratio', 'pdf_serif_family', 'unit', 'pdf_sans_family', 'pdf_mono_family', 'pdf_standard_font', - 'pdf_default_font_size', 'pdf_mono_font_size']) + 'pdf_default_font_size', 'pdf_mono_font_size', 'pdf_page_numbers']) self.db, self.book_id = db, book_id for x in get_option('paper_size').option.choices: diff --git a/src/calibre/gui2/convert/pdf_output.ui b/src/calibre/gui2/convert/pdf_output.ui index 5e3c4c9137..a4d184d6bc 100644 --- a/src/calibre/gui2/convert/pdf_output.ui +++ b/src/calibre/gui2/convert/pdf_output.ui @@ -84,7 +84,7 @@ - + Se&rif family: @@ -94,10 +94,10 @@ - + - + &Sans family: @@ -107,10 +107,10 @@ - + - + &Monospace family: @@ -120,10 +120,10 @@ - + - + S&tandard font: @@ -133,10 +133,10 @@ - + - + Default font si&ze: @@ -146,14 +146,14 @@ - + px - + Monospace &font size: @@ -163,14 +163,14 @@ - + px - + Qt::Vertical @@ -183,6 +183,13 @@ + + + + Add page &numbers to the bottom of every page + + + From 71e77b85d786628f20c8f387de7bdf290d3abba1 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 29 Jan 2013 13:54:14 +0530 Subject: [PATCH 2/7] Add option to turn off reflections in the cover browser (Preferences->Look & Feel->Cover Browser) --- src/calibre/gui2/__init__.py | 77 ++++++++++---------- src/calibre/gui2/cover_flow.py | 2 + src/calibre/gui2/pictureflow/pictureflow.cpp | 55 ++++++++++---- src/calibre/gui2/pictureflow/pictureflow.h | 6 ++ src/calibre/gui2/pictureflow/pictureflow.sip | 4 + src/calibre/gui2/preferences/look_feel.py | 3 + src/calibre/gui2/preferences/look_feel.ui | 19 +++-- 7 files changed, 107 insertions(+), 59 deletions(-) diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index d7a2669b0b..301b5f7ea4 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -22,91 +22,94 @@ from calibre.utils.date import UNDEFINED_DATE # Setup gprefs {{{ gprefs = JSONConfig('gui') +defs = gprefs.defaults if isosx: - gprefs.defaults['action-layout-menubar'] = ( + defs['action-layout-menubar'] = ( 'Add Books', 'Edit Metadata', 'Convert Books', 'Choose Library', 'Save To Disk', 'Preferences', 'Help', ) - gprefs.defaults['action-layout-menubar-device'] = ( + defs['action-layout-menubar-device'] = ( 'Add Books', 'Edit Metadata', 'Convert Books', 'Location Manager', 'Send To Device', 'Save To Disk', 'Preferences', 'Help', ) - gprefs.defaults['action-layout-toolbar'] = ( + defs['action-layout-toolbar'] = ( 'Add Books', 'Edit Metadata', None, 'Convert Books', 'View', None, 'Choose Library', 'Donate', None, 'Fetch News', 'Store', 'Save To Disk', 'Connect Share', None, 'Remove Books', ) - gprefs.defaults['action-layout-toolbar-device'] = ( + defs['action-layout-toolbar-device'] = ( 'Add Books', 'Edit Metadata', None, 'Convert Books', 'View', 'Send To Device', None, None, 'Location Manager', None, None, 'Fetch News', 'Store', 'Save To Disk', 'Connect Share', None, 'Remove Books', ) else: - gprefs.defaults['action-layout-menubar'] = () - gprefs.defaults['action-layout-menubar-device'] = () - gprefs.defaults['action-layout-toolbar'] = ( + defs['action-layout-menubar'] = () + defs['action-layout-menubar-device'] = () + defs['action-layout-toolbar'] = ( 'Add Books', 'Edit Metadata', None, 'Convert Books', 'View', None, 'Store', 'Donate', 'Fetch News', 'Help', None, 'Remove Books', 'Choose Library', 'Save To Disk', 'Connect Share', 'Preferences', ) - gprefs.defaults['action-layout-toolbar-device'] = ( + defs['action-layout-toolbar-device'] = ( 'Add Books', 'Edit Metadata', None, 'Convert Books', 'View', 'Send To Device', None, None, 'Location Manager', None, None, 'Fetch News', 'Save To Disk', 'Store', 'Connect Share', None, 'Remove Books', None, 'Help', 'Preferences', ) -gprefs.defaults['action-layout-toolbar-child'] = () +defs['action-layout-toolbar-child'] = () -gprefs.defaults['action-layout-context-menu'] = ( +defs['action-layout-context-menu'] = ( 'Edit Metadata', 'Send To Device', 'Save To Disk', 'Connect Share', 'Copy To Library', None, 'Convert Books', 'View', 'Open Folder', 'Show Book Details', 'Similar Books', 'Tweak ePub', None, 'Remove Books', ) -gprefs.defaults['action-layout-context-menu-device'] = ( +defs['action-layout-context-menu-device'] = ( 'View', 'Save To Disk', None, 'Remove Books', None, 'Add To Library', 'Edit Collections', ) -gprefs.defaults['action-layout-context-menu-cover-browser'] = ( +defs['action-layout-context-menu-cover-browser'] = ( 'Edit Metadata', 'Send To Device', 'Save To Disk', 'Connect Share', 'Copy To Library', None, 'Convert Books', 'View', 'Open Folder', 'Show Book Details', 'Similar Books', 'Tweak ePub', None, 'Remove Books', ) -gprefs.defaults['show_splash_screen'] = True -gprefs.defaults['toolbar_icon_size'] = 'medium' -gprefs.defaults['automerge'] = 'ignore' -gprefs.defaults['toolbar_text'] = 'always' -gprefs.defaults['font'] = None -gprefs.defaults['tags_browser_partition_method'] = 'first letter' -gprefs.defaults['tags_browser_collapse_at'] = 100 -gprefs.defaults['tag_browser_dont_collapse'] = [] -gprefs.defaults['edit_metadata_single_layout'] = 'default' -gprefs.defaults['default_author_link'] = 'http://en.wikipedia.org/w/index.php?search={author}' -gprefs.defaults['preserve_date_on_ctl'] = True -gprefs.defaults['manual_add_auto_convert'] = False -gprefs.defaults['cb_fullscreen'] = False -gprefs.defaults['worker_max_time'] = 0 -gprefs.defaults['show_files_after_save'] = True -gprefs.defaults['auto_add_path'] = None -gprefs.defaults['auto_add_check_for_duplicates'] = False -gprefs.defaults['blocked_auto_formats'] = [] -gprefs.defaults['auto_add_auto_convert'] = True -gprefs.defaults['ui_style'] = 'calibre' if iswindows or isosx else 'system' -gprefs.defaults['tag_browser_old_look'] = False -gprefs.defaults['book_list_tooltips'] = True -gprefs.defaults['bd_show_cover'] = True -gprefs.defaults['bd_overlay_cover_size'] = False -gprefs.defaults['tags_browser_category_icons'] = {} +defs['show_splash_screen'] = True +defs['toolbar_icon_size'] = 'medium' +defs['automerge'] = 'ignore' +defs['toolbar_text'] = 'always' +defs['font'] = None +defs['tags_browser_partition_method'] = 'first letter' +defs['tags_browser_collapse_at'] = 100 +defs['tag_browser_dont_collapse'] = [] +defs['edit_metadata_single_layout'] = 'default' +defs['default_author_link'] = 'http://en.wikipedia.org/w/index.php?search={author}' +defs['preserve_date_on_ctl'] = True +defs['manual_add_auto_convert'] = False +defs['cb_fullscreen'] = False +defs['worker_max_time'] = 0 +defs['show_files_after_save'] = True +defs['auto_add_path'] = None +defs['auto_add_check_for_duplicates'] = False +defs['blocked_auto_formats'] = [] +defs['auto_add_auto_convert'] = True +defs['ui_style'] = 'calibre' if iswindows or isosx else 'system' +defs['tag_browser_old_look'] = False +defs['book_list_tooltips'] = True +defs['bd_show_cover'] = True +defs['bd_overlay_cover_size'] = False +defs['tags_browser_category_icons'] = {} +defs['cover_browser_reflections'] = True +del defs # }}} NONE = QVariant() #: Null value to return from the data function of item models diff --git a/src/calibre/gui2/cover_flow.py b/src/calibre/gui2/cover_flow.py index b7cebee2c0..8a7beb811c 100644 --- a/src/calibre/gui2/cover_flow.py +++ b/src/calibre/gui2/cover_flow.py @@ -106,6 +106,8 @@ if pictureflow is not None: self.setContextMenuPolicy(Qt.DefaultContextMenu) if hasattr(self, 'setSubtitleFont'): self.setSubtitleFont(QFont(rating_font())) + if not gprefs['cover_browser_reflections']: + self.setShowReflections(False) def set_context_menu(self, cm): self.context_menu = cm diff --git a/src/calibre/gui2/pictureflow/pictureflow.cpp b/src/calibre/gui2/pictureflow/pictureflow.cpp index 88fff1fd2c..e26309f4cf 100644 --- a/src/calibre/gui2/pictureflow/pictureflow.cpp +++ b/src/calibre/gui2/pictureflow/pictureflow.cpp @@ -340,6 +340,9 @@ public: int currentSlide() const; void setCurrentSlide(int index); + bool showReflections() const; + void setShowReflections(bool show); + int getTarget() const; void showPrevious(); @@ -378,6 +381,7 @@ private: int slideHeight; int fontSize; int queueLength; + bool doReflections; int centerIndex; SlideInfo centerSlide; @@ -416,6 +420,7 @@ PictureFlowPrivate::PictureFlowPrivate(PictureFlow* w, int queueLength_) slideWidth = 200; slideHeight = 200; fontSize = 10; + doReflections = true; centerIndex = 0; queueLength = queueLength_; @@ -494,6 +499,15 @@ void PictureFlowPrivate::setCurrentSlide(int index) widget->emitcurrentChanged(centerIndex); } +bool PictureFlowPrivate::showReflections() const { + return doReflections; +} + +void PictureFlowPrivate::setShowReflections(bool show) { + doReflections = show; + triggerRender(); +} + void PictureFlowPrivate::showPrevious() { if(step >= 0) @@ -584,7 +598,7 @@ void PictureFlowPrivate::resetSlides() } } -static QImage prepareSurface(QImage img, int w, int h) +static QImage prepareSurface(QImage img, int w, int h, bool doReflections) { img = img.scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); @@ -602,19 +616,21 @@ static QImage prepareSurface(QImage img, int w, int h) for(int y = 0; y < h; y++) result.setPixel(y, x, img.pixel(x, y)); - // create the reflection - int ht = hs - h; - for(int x = 0; x < w; x++) - for(int y = 0; y < ht; y++) - { - QRgb color = img.pixel(x, img.height()-y-1); - //QRgb565 color = img.scanLine(img.height()-y-1) + x*sizeof(QRgb565); //img.pixel(x, img.height()-y-1); - int a = qAlpha(color); - int r = qRed(color) * a / 256 * (ht - y) / ht * 3/5; - int g = qGreen(color) * a / 256 * (ht - y) / ht * 3/5; - int b = qBlue(color) * a / 256 * (ht - y) / ht * 3/5; - result.setPixel(h+y, x, qRgb(r, g, b)); - } + if (doReflections) { + // create the reflection + int ht = hs - h; + for(int x = 0; x < w; x++) + for(int y = 0; y < ht; y++) + { + QRgb color = img.pixel(x, img.height()-y-1); + //QRgb565 color = img.scanLine(img.height()-y-1) + x*sizeof(QRgb565); //img.pixel(x, img.height()-y-1); + int a = qAlpha(color); + int r = qRed(color) * a / 256 * (ht - y) / ht * 3/5; + int g = qGreen(color) * a / 256 * (ht - y) / ht * 3/5; + int b = qBlue(color) * a / 256 * (ht - y) / ht * 3/5; + result.setPixel(h+y, x, qRgb(r, g, b)); + } + } return result; } @@ -652,12 +668,12 @@ QImage* PictureFlowPrivate::surface(int slideIndex) painter.setBrush(QBrush()); painter.drawRect(2, 2, slideWidth-3, slideHeight-3); painter.end(); - blankSurface = prepareSurface(blankSurface, slideWidth, slideHeight); + blankSurface = prepareSurface(blankSurface, slideWidth, slideHeight, doReflections); } return &blankSurface; } - surfaceCache.insert(slideIndex, new QImage(prepareSurface(img, slideWidth, slideHeight))); + surfaceCache.insert(slideIndex, new QImage(prepareSurface(img, slideWidth, slideHeight, doReflections))); return surfaceCache[slideIndex]; } @@ -1196,6 +1212,13 @@ QImage PictureFlow::slide(int index) const return d->slide(index); } +bool PictureFlow::showReflections() const { + return d->showReflections(); +} + +void PictureFlow::setShowReflections(bool show) { + d->setShowReflections(show); +} void PictureFlow::setImages(FlowImages *images) { diff --git a/src/calibre/gui2/pictureflow/pictureflow.h b/src/calibre/gui2/pictureflow/pictureflow.h index c5a9c76190..bc427e8580 100644 --- a/src/calibre/gui2/pictureflow/pictureflow.h +++ b/src/calibre/gui2/pictureflow/pictureflow.h @@ -121,6 +121,12 @@ public: */ void setSlideSize(QSize size); + /*! + Turn the reflections on/off. + */ + void setShowReflections(bool show); + bool showReflections() const; + /*! Returns the font used to render subtitles */ diff --git a/src/calibre/gui2/pictureflow/pictureflow.sip b/src/calibre/gui2/pictureflow/pictureflow.sip index 21c6209df5..0fab379147 100644 --- a/src/calibre/gui2/pictureflow/pictureflow.sip +++ b/src/calibre/gui2/pictureflow/pictureflow.sip @@ -51,6 +51,10 @@ public : int currentSlide() const; + bool showReflections() const; + + void setShowReflections(bool show); + public slots: void setCurrentSlide(int index); diff --git a/src/calibre/gui2/preferences/look_feel.py b/src/calibre/gui2/preferences/look_feel.py index b3423e5a8c..54b5e3a625 100644 --- a/src/calibre/gui2/preferences/look_feel.py +++ b/src/calibre/gui2/preferences/look_feel.py @@ -110,6 +110,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): r('bd_overlay_cover_size', gprefs) r('cover_flow_queue_length', config, restart_required=True) + r('cover_browser_reflections', gprefs) def get_esc_lang(l): if l == 'en': @@ -289,6 +290,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.update_font_display() gui.tags_view.reread_collapse_parameters() gui.library_view.refresh_book_details() + if gui.cover_flow is not None: + gui.cover_flow.setShowReflections(gprefs['cover_browser_reflections']) if __name__ == '__main__': from calibre.gui2 import Application diff --git a/src/calibre/gui2/preferences/look_feel.ui b/src/calibre/gui2/preferences/look_feel.ui index fe6d9ecb62..5074eaf4e6 100644 --- a/src/calibre/gui2/preferences/look_feel.ui +++ b/src/calibre/gui2/preferences/look_feel.ui @@ -496,10 +496,7 @@ a few top-level elements. - - - - + Qt::Vertical @@ -512,14 +509,17 @@ a few top-level elements. - + + + + When showing cover browser in separate window, show it &fullscreen - + margin-left: 1.5em @@ -532,6 +532,13 @@ a few top-level elements. + + + + Show &reflections in the cover browser + + + From a42c073e2761f846ff67af3255a4049aa3209b8a Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 29 Jan 2013 14:31:44 +0530 Subject: [PATCH 3/7] ... --- recipes/hbr.recipe | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/recipes/hbr.recipe b/recipes/hbr.recipe index b80b0bace7..54c0f258d8 100644 --- a/recipes/hbr.recipe +++ b/recipes/hbr.recipe @@ -38,37 +38,24 @@ class HBR(BasicNewsRecipe): #articleAuthors{font-family:Georgia,"Times New Roman",Times,serif; font-style:italic; color:#000000;font-size:x-small;} #summaryText{font-family:Georgia,"Times New Roman",Times,serif; font-weight:bold; font-size:x-small;} ''' + use_javascript_to_login = True - def get_browser(self): - br = BasicNewsRecipe.get_browser(self) - self.logout_url = None - - #''' - br.open(self.LOGIN_URL) - br.select_form(name='signin-form') - br['signin-form:username'] = self.username - br['signin-form:password'] = self.password - raw = br.submit().read() - if '>Sign out<' not in raw: - raise Exception('Failed to login, are you sure your username and password are correct?') + def javascript_login(self, br, username, password): + from calibre.web.jsbrowser.browser import Timeout try: - link = br.find_link(text='Sign out') - if link: - self.logout_url = link.absolute_url - except: - self.logout_url = self.LOGOUT_URL - #''' - return br - - def cleanup(self): - if self.logout_url is not None: - self.browser.open(self.logout_url) + br.visit('https://hbr.org/login?request_url=/', timeout=20) + except Timeout: + pass + br.click('#accordion div[tabindex="0"]', wait_for_load=False) + f = br.select_form('#signin-form') + f['signin-form:username'] = 'test-account' + f['signin-form:password'] = 'testaccount' + br.submit(ajax_replies=3) def map_url(self, url): if url.endswith('/ar/1'): return url[:-1]+'pr' - def hbr_get_toc(self): #return self.index_to_soup(open('/t/hbr.html').read()) From 67dab7c4991cfbb326a1f9736a8133bdde161a5b Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 30 Jan 2013 09:27:10 +0530 Subject: [PATCH 4/7] ... --- manual/faq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manual/faq.rst b/manual/faq.rst index b6c88acbb4..a851e69624 100644 --- a/manual/faq.rst +++ b/manual/faq.rst @@ -794,7 +794,7 @@ Why doesn't |app| have an automatic update? For many reasons: * *There is no need to update every week*. If you are happy with how |app| works turn off the update notification and be on your merry way. Check back to see if you want to update once a year or so. - * Pre downloading the updates for all users in the background would mean require about 80TB of bandwidth *every week*. That costs thousands of dollars a month. And |app| is currently growing at 300,000 new users every month. + * Pre downloading the updates for all users in the background would require about 80TB of bandwidth *every week*. That costs thousands of dollars a month. And |app| is currently growing at 300,000 new users every month. * If I implement a dialog that downloads the update and launches it, instead of going to the website as it does now, that would save the most ardent |app| updater, *at most five clicks a week*. There are far higher priority things to do in |app| development. * If you really, really hate downloading |app| every week but still want to be up to the latest, I encourage you to run from source, which makes updating trivial. Instructions are :ref:`available here `. From 6ace77f1bc49a3cdd142655117c47dbf5550d21f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 30 Jan 2013 10:04:17 +0530 Subject: [PATCH 5/7] ... --- manual/faq.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/manual/faq.rst b/manual/faq.rst index a851e69624..51485a29a5 100644 --- a/manual/faq.rst +++ b/manual/faq.rst @@ -682,8 +682,11 @@ There are three possible things I know of, that can cause this: * The Logitech SetPoint Settings application causes random crashes in |app| when it is open. Close it before starting |app|. + * Constant Guard Protection by Xfinity causes crashes in |app|. You have to + manually allow |app| in it or uninstall Constant Guard Protection. + If none of the above apply to you, then there is some other program on your -computer that is interfering with |app|. First reboot your computer is safe +computer that is interfering with |app|. First reboot your computer in safe mode, to have as few running programs as possible, and see if the crashes still happen. If they do not, then you know it is some program causing the problem. The most likely such culprit is a program that modifies other programs' From 5d3ec0672ff5ad4a9e59374a84324d30a4675168 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 30 Jan 2013 10:59:00 +0530 Subject: [PATCH 6/7] Fix Harvard Business Review --- recipes/hbr.recipe | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/recipes/hbr.recipe b/recipes/hbr.recipe index 54c0f258d8..742d1605fa 100644 --- a/recipes/hbr.recipe +++ b/recipes/hbr.recipe @@ -11,11 +11,11 @@ class HBR(BasicNewsRecipe): timefmt = ' [%B %Y]' language = 'en' no_stylesheets = True - recipe_disabled = ('hbr.org has started requiring the use of javascript' - ' to log into their website. This is unsupported in calibre, so' - ' this recipe has been disabled. If you would like to see ' - ' HBR supported in calibre, contact hbr.org and ask them' - ' to provide a javascript free login method.') + # recipe_disabled = ('hbr.org has started requiring the use of javascript' + # ' to log into their website. This is unsupported in calibre, so' + # ' this recipe has been disabled. If you would like to see ' + # ' HBR supported in calibre, contact hbr.org and ask them' + # ' to provide a javascript free login method.') LOGIN_URL = 'https://hbr.org/login?request_url=/' LOGOUT_URL = 'https://hbr.org/logout?request_url=/' @@ -50,21 +50,25 @@ class HBR(BasicNewsRecipe): f = br.select_form('#signin-form') f['signin-form:username'] = 'test-account' f['signin-form:password'] = 'testaccount' - br.submit(ajax_replies=3) + f.submit_control().qwe.evaluateJavaScript('this.click()') + br.run_for_a_time(30) def map_url(self, url): if url.endswith('/ar/1'): return url[:-1]+'pr' def hbr_get_toc(self): - #return self.index_to_soup(open('/t/hbr.html').read()) + # return self.index_to_soup(open('/t/toc.html').read()) today = date.today() future = today + timedelta(days=30) for x in [x.strftime('%y%m') for x in (future, today)]: url = self.INDEX + x soup = self.index_to_soup(url) - if not soup.find(text='Issue Not Found'): + if (not soup.find(text='Issue Not Found') and not soup.find( + text="We're Sorry. There was an error processing your request") + and 'Exception: java.io.FileNotFoundException' not in + unicode(soup)): return soup raise Exception('Could not find current issue') @@ -72,8 +76,9 @@ class HBR(BasicNewsRecipe): feeds = [] current_section = None articles = [] - for x in soup.find(id='archiveToc').findAll(['h3', 'h4']): - if x.name == 'h3': + for x in soup.find(id='issueFeaturesContent').findAll(['li', 'h4']): + if x.name == 'h4': + if x.get('class', None) == 'basic':continue if current_section is not None and articles: feeds.append((current_section, articles)) current_section = self.tag_to_string(x).capitalize() @@ -89,7 +94,7 @@ class HBR(BasicNewsRecipe): if url.startswith('/'): url = 'http://hbr.org' + url url = self.map_url(url) - p = x.parent.find('p') + p = x.find('p', attrs={'class':'author'}) desc = '' if p is not None: desc = self.tag_to_string(p) @@ -101,10 +106,9 @@ class HBR(BasicNewsRecipe): 'date':''}) return feeds - def parse_index(self): soup = self.hbr_get_toc() - #open('/t/hbr.html', 'wb').write(unicode(soup).encode('utf-8')) + # open('/t/hbr.html', 'wb').write(unicode(soup).encode('utf-8')) feeds = self.hbr_parse_toc(soup) return feeds From ae0e0e66b59820d272b764898a3140a783ad4dc0 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 30 Jan 2013 11:33:02 +0530 Subject: [PATCH 7/7] ... --- recipes/hbr.recipe | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/recipes/hbr.recipe b/recipes/hbr.recipe index 742d1605fa..702795109b 100644 --- a/recipes/hbr.recipe +++ b/recipes/hbr.recipe @@ -48,9 +48,9 @@ class HBR(BasicNewsRecipe): pass br.click('#accordion div[tabindex="0"]', wait_for_load=False) f = br.select_form('#signin-form') - f['signin-form:username'] = 'test-account' - f['signin-form:password'] = 'testaccount' - f.submit_control().qwe.evaluateJavaScript('this.click()') + f['signin-form:username'] = username + f['signin-form:password'] = password + br.submit(wait_for_load=False) br.run_for_a_time(30) def map_url(self, url):