diff --git a/recipes/metro_uk.recipe b/recipes/metro_uk.recipe index deced5976b..2d5155ef29 100644 --- a/recipes/metro_uk.recipe +++ b/recipes/metro_uk.recipe @@ -1,29 +1,32 @@ from calibre.web.feeds.news import BasicNewsRecipe class AdvancedUserRecipe1306097511(BasicNewsRecipe): title = u'Metro UK' - - no_stylesheets = True - oldest_article = 1 - max_articles_per_feed = 200 + description = 'News as provide by The Metro -UK' __author__ = 'Dave Asbury' + no_stylesheets = True + oldest_article = 1 + max_articles_per_feed = 25 + remove_empty_feeds = True + remove_javascript = True + + language = 'en_GB' - simultaneous_downloads= 3 + masthead_url = 'http://e-edition.metro.co.uk/images/metro_logo.gif' + extra_css = 'h2 {font: sans-serif medium;}' keep_only_tags = [ + dict(name='h1'),dict(name='h2', attrs={'class':'h2'}), dict(attrs={'class':['img-cnt figure']}), - dict(attrs={'class':['art-img']}), - dict(name='h1'), - dict(name='h2', attrs={'class':'h2'}), + dict(attrs={'class':['art-img']}), + dict(name='div', attrs={'class':'art-lft'}) ] - remove_tags = [dict(name='div', attrs={'class':[ 'metroCommentFormWrap', - 'commentForm', 'metroCommentInnerWrap', - 'art-rgt','pluck-app pluck-comm','news m12 clrd clr-l p5t', 'flt-r' ]})] - + remove_tags = [dict(name='div', attrs={'class':[ 'news m12 clrd clr-b p5t shareBtm', 'commentForm', 'metroCommentInnerWrap', + 'art-rgt','pluck-app pluck-comm','news m12 clrd clr-l p5t', 'flt-r' ]}), + dict(attrs={'class':[ 'metroCommentFormWrap','commentText','commentsNav','avatar','submDateAndTime']}) + ] feeds = [ (u'News', u'http://www.metro.co.uk/rss/news/'), (u'Money', u'http://www.metro.co.uk/rss/money/'), (u'Sport', u'http://www.metro.co.uk/rss/sport/'), (u'Film', u'http://www.metro.co.uk/rss/metrolife/film/'), (u'Music', u'http://www.metro.co.uk/rss/metrolife/music/'), (u'TV', u'http://www.metro.co.uk/rss/tv/'), (u'Showbiz', u'http://www.metro.co.uk/rss/showbiz/'), (u'Weird News', u'http://www.metro.co.uk/rss/weird/'), (u'Travel', u'http://www.metro.co.uk/rss/travel/'), (u'Lifestyle', u'http://www.metro.co.uk/rss/lifestyle/'), (u'Books', u'http://www.metro.co.uk/rss/lifestyle/books/'), (u'Food', u'http://www.metro.co.uk/rss/lifestyle/restaurants/')] - - diff --git a/recipes/noticias_r7.recipe b/recipes/noticias_r7.recipe new file mode 100644 index 0000000000..b7495bb77e --- /dev/null +++ b/recipes/noticias_r7.recipe @@ -0,0 +1,40 @@ +import re +from calibre.web.feeds.news import BasicNewsRecipe + +class PortalR7(BasicNewsRecipe): + title = 'Noticias R7' + __author__ = 'Diniz Bortolotto' + description = 'Noticias Portal R7' + oldest_article = 2 + max_articles_per_feed = 20 + encoding = 'utf8' + publisher = 'Rede Record' + category = 'news, Brazil' + language = 'pt_BR' + publication_type = 'newsportal' + use_embedded_content = False + no_stylesheets = True + remove_javascript = True + remove_attributes = ['style'] + + feeds = [ + (u'Brasil', u'http://www.r7.com/data/rss/brasil.xml'), + (u'Economia', u'http://www.r7.com/data/rss/economia.xml'), + (u'Internacional', u'http://www.r7.com/data/rss/internacional.xml'), + (u'Tecnologia e Ci\xeancia', u'http://www.r7.com/data/rss/tecnologiaCiencia.xml') + ] + reverse_article_order = True + + keep_only_tags = [dict(name='div', attrs={'class':'materia'})] + remove_tags = [ + dict(id=['espalhe', 'report-erro']), + dict(name='ul', attrs={'class':'controles'}), + dict(name='ul', attrs={'class':'relacionados'}), + dict(name='div', attrs={'class':'materia_banner'}), + dict(name='div', attrs={'class':'materia_controles'}) + ] + + preprocess_regexps = [ + (re.compile(r'
.*
',re.DOTALL|re.IGNORECASE), + lambda match: '
') + ] diff --git a/resources/content_server/read/monocle.js b/resources/content_server/read/monocle.js index 8d58ba8a06..560e4af641 100644 --- a/resources/content_server/read/monocle.js +++ b/resources/content_server/read/monocle.js @@ -1,5 +1,5 @@ Monocle = { - VERSION: "1.0.0" + VERSION: "2.0.0" }; @@ -170,7 +170,8 @@ Monocle.Browser.has.iframeTouchBug = Monocle.Browser.iOSVersionBelow("4.2"); Monocle.Browser.has.selectThruBug = Monocle.Browser.iOSVersionBelow("4.2"); Monocle.Browser.has.mustScrollSheaf = Monocle.Browser.is.MobileSafari; -Monocle.Browser.has.iframeDoubleWidthBug = Monocle.Browser.has.mustScrollSheaf; +Monocle.Browser.has.iframeDoubleWidthBug = + Monocle.Browser.has.mustScrollSheaf || Monocle.Browser.on.Kindle3; Monocle.Browser.has.floatColumnBug = Monocle.Browser.is.WebKit; @@ -181,6 +182,11 @@ Monocle.Browser.has.jumpFlickerBug = Monocle.Browser.on.MacOSX && Monocle.Browser.is.WebKit; +Monocle.Browser.has.columnOverflowPaintBug = Monocle.Browser.is.WebKit && + !Monocle.Browser.is.MobileSafari && + navigator.userAgent.indexOf("AppleWebKit/534") > 0; + + if (typeof window.console == "undefined") { window.console = { messages: [], @@ -241,6 +247,7 @@ Monocle.Factory = function (element, label, index, reader) { function initialize() { + if (!p.label) { return; } var node = p.reader.properties.graph; node[p.label] = node[p.label] || []; if (typeof p.index == 'undefined' && node[p.label][p.index]) { @@ -274,7 +281,11 @@ Monocle.Factory = function (element, label, index, reader) { function make(tagName, oLabel, index_or_options, or_options) { var oIndex, options; - if (arguments.length == 2) { + if (arguments.length == 1) { + oLabel = null, + oIndex = 0; + options = {}; + } else if (arguments.length == 2) { oIndex = 0; options = {}; } else if (arguments.length == 4) { @@ -376,6 +387,22 @@ Monocle.pieceLoaded('factory'); Monocle.Events = {} +Monocle.Events.dispatch = function (elem, evtType, data, cancelable) { + if (!document.createEvent) { + return true; + } + var evt = document.createEvent("Events"); + evt.initEvent(evtType, false, cancelable || false); + evt.m = data; + try { + return elem.dispatchEvent(evt); + } catch(e) { + console.warn("Failed to dispatch event: "+evtType); + return false; + } +} + + Monocle.Events.listen = function (elem, evtType, fn, useCapture) { if (elem.addEventListener) { return elem.addEventListener(evtType, fn, useCapture || false); @@ -405,7 +432,7 @@ Monocle.Events.listenForContact = function (elem, fns, options) { pageY: ci.pageY }; - var target = evt.target || window.srcElement; + var target = evt.target || evt.srcElement; while (target.nodeType != 1 && target.parentNode) { target = target.parentNode; } @@ -527,13 +554,18 @@ Monocle.Events.deafenForContact = function (elem, listeners) { } -Monocle.Events.listenForTap = function (elem, fn) { +Monocle.Events.listenForTap = function (elem, fn, activeClass) { var startPos; if (Monocle.Browser.on.Kindle3) { Monocle.Events.listen(elem, 'click', function () {}); } + var annul = function () { + startPos = null; + if (activeClass && elem.dom) { elem.dom.removeClass(activeClass); } + } + var annulIfOutOfBounds = function (evt) { if (evt.type.match(/^mouse/)) { return; @@ -545,7 +577,7 @@ Monocle.Events.listenForTap = function (elem, fn) { evt.m.registrantX < 0 || evt.m.registrantX > elem.offsetWidth || evt.m.registrantY < 0 || evt.m.registrantY > elem.offsetHeight ) { - startPos = null; + annul(); } else { evt.preventDefault(); } @@ -557,6 +589,7 @@ Monocle.Events.listenForTap = function (elem, fn) { start: function (evt) { startPos = [evt.m.pageX, evt.m.pageY]; evt.preventDefault(); + if (activeClass && elem.dom) { elem.dom.addClass(activeClass); } }, move: annulIfOutOfBounds, end: function (evt) { @@ -565,10 +598,9 @@ Monocle.Events.listenForTap = function (elem, fn) { evt.m.startOffset = startPos; fn(evt); } + annul(); }, - cancel: function (evt) { - startPos = null; - } + cancel: annul }, { useCapture: false @@ -997,6 +1029,9 @@ Monocle.Reader = function (node, bookData, options, onLoadCallback) { createReaderElements(); p.defaultStyles = addPageStyles(k.DEFAULT_STYLE_RULES, false); + if (options.stylesheet) { + p.initialStyles = addPageStyles(options.stylesheet, false); + } primeFrames(options.primeURL, function () { applyStyles(); @@ -1077,6 +1112,7 @@ Monocle.Reader = function (node, bookData, options, onLoadCallback) { if (Monocle.Browser.is.WebKit) { frame.contentDocument.documentElement.style.overflow = "hidden"; } + dispatchEvent('monocle:frameprimed', { frame: frame, pageIndex: pageCount }); if ((pageCount += 1) == pageMax) { Monocle.defer(callback); } @@ -1131,6 +1167,7 @@ Monocle.Reader = function (node, bookData, options, onLoadCallback) { var pageCount = 0; if (typeof callback == 'function') { var watcher = function (evt) { + dispatchEvent('monocle:firstcomponentchange', evt.m); if ((pageCount += 1) == p.flipper.pageCount) { deafen('monocle:componentchange', watcher); callback(); @@ -1239,7 +1276,7 @@ Monocle.Reader = function (node, bookData, options, onLoadCallback) { page.appendChild(runner); ctrlData.elements.push(runner); } - } else if (cType == "modal" || cType == "popover") { + } else if (cType == "modal" || cType == "popover" || cType == "hud") { ctrlElem = ctrl.createControlElements(overlay); overlay.appendChild(ctrlElem); ctrlData.elements.push(ctrlElem); @@ -1312,24 +1349,33 @@ Monocle.Reader = function (node, bookData, options, onLoadCallback) { var controlData = dataForControl(ctrl); if (!controlData) { console.warn("No data for control: " + ctrl); - return; + return false; } - if (controlData.hidden == false) { - return; + + if (showingControl(ctrl)) { + return false; } + + var overlay = dom.find('overlay'); + if (controlData.usesOverlay && controlData.controlType != "hud") { + for (var i = 0, ii = p.controls.length; i < ii; ++i) { + if (p.controls[i].usesOverlay && !p.controls[i].hidden) { + return false; + } + } + overlay.style.display = "block"; + } + for (var i = 0; i < controlData.elements.length; ++i) { controlData.elements[i].style.display = "block"; } - var overlay = dom.find('overlay'); - if (controlData.usesOverlay) { - overlay.style.display = "block"; - } + if (controlData.controlType == "popover") { overlay.listeners = Monocle.Events.listenForContact( overlay, { start: function (evt) { - obj = evt.target || window.event.srcElement; + var obj = evt.target || window.event.srcElement; do { if (obj == controlData.elements[0]) { return true; } } while (obj && (obj = obj.parentNode)); @@ -1346,22 +1392,18 @@ Monocle.Reader = function (node, bookData, options, onLoadCallback) { ctrl.properties.hidden = false; } dispatchEvent('controlshow', ctrl, false); + return true; + } + + + function showingControl(ctrl) { + var controlData = dataForControl(ctrl); + return controlData.hidden == false; } function dispatchEvent(evtType, data, cancelable) { - if (!document.createEvent) { - return true; - } - var evt = document.createEvent("Events"); - evt.initEvent(evtType, false, cancelable || false); - evt.m = data; - try { - return dom.find('box').dispatchEvent(evt); - } catch(e) { - console.warn("Failed to dispatch event: " + evtType); - return false; - } + return Monocle.Events.dispatch(dom.find('box'), evtType, data, cancelable); } @@ -1502,6 +1544,7 @@ Monocle.Reader = function (node, bookData, options, onLoadCallback) { API.addControl = addControl; API.hideControl = hideControl; API.showControl = showControl; + API.showingControl = showingControl; API.dispatchEvent = dispatchEvent; API.listen = listen; API.deafen = deafen; @@ -1527,22 +1570,32 @@ Monocle.Reader.DEFAULT_CLASS_PREFIX = 'monelem_' Monocle.Reader.FLIPPER_DEFAULT_CLASS = "Slider"; Monocle.Reader.FLIPPER_LEGACY_CLASS = "Legacy"; Monocle.Reader.DEFAULT_STYLE_RULES = [ - "html * {" + + "html#RS\\:monocle * {" + + "-webkit-font-smoothing: subpixel-antialiased;" + "text-rendering: auto !important;" + "word-wrap: break-word !important;" + + "overflow: visible !important;" + (Monocle.Browser.has.floatColumnBug ? "float: none !important;" : "") + - "}" + - "body {" + + "}", + "html#RS\\:monocle body {" + "margin: 0 !important;" + "padding: 0 !important;" + "-webkit-text-size-adjust: none;" + - "}" + - "table, img {" + + "}", + "html#RS\\:monocle body * {" + "max-width: 100% !important;" + - "max-height: 90% !important;" + + "}", + "html#RS\\:monocle img, html#RS\\:monocle video, html#RS\\:monocle object {" + + "max-height: 95% !important;" + "}" ] +if (Monocle.Browser.has.columnOverflowPaintBug) { + Monocle.Reader.DEFAULT_STYLE_RULES.push( + "::-webkit-scrollbar { width: 0; height: 0; }" + ) +} + Monocle.pieceLoaded('reader'); /* BOOK */ @@ -1586,6 +1639,16 @@ Monocle.Book = function (dataSource) { locus.load = true; locus.componentId = p.componentIds[0]; return locus; + } else if ( + cIndex < 0 && + locus.componentId && + currComponent.properties.id != locus.componentId + ) { + pageDiv.m.reader.dispatchEvent( + "monocle:notfound", + { href: locus.componentId } + ); + return null; } else if (cIndex < 0) { component = currComponent; locus.componentId = pageDiv.m.activeFrame.m.component.properties.id; @@ -1619,6 +1682,8 @@ Monocle.Book = function (dataSource) { result.page += locus.direction; } else if (typeof(locus.anchor) == "string") { result.page = component.pageForChapter(locus.anchor, pageDiv); + } else if (typeof(locus.xpath) == "string") { + result.page = component.pageForXPath(locus.xpath, pageDiv); } else if (typeof(locus.position) == "string") { if (locus.position == "start") { result.page = 1; @@ -1638,6 +1703,7 @@ Monocle.Book = function (dataSource) { if (result.page < 1) { if (cIndex == 0) { result.page = 1; + result.boundarystart = true; } else { result.load = true; result.componentId = p.componentIds[cIndex - 1]; @@ -1647,6 +1713,7 @@ Monocle.Book = function (dataSource) { } else if (result.page > lastPageNum['new']) { if (cIndex == p.lastCIndex) { result.page = lastPageNum['new']; + result.boundaryend = true; } else { result.load = true; result.componentId = p.componentIds[cIndex + 1]; @@ -1660,18 +1727,25 @@ Monocle.Book = function (dataSource) { function setPageAt(pageDiv, locus) { locus = pageNumberAt(pageDiv, locus); - if (!locus.load) { - var component = p.components[p.componentIds.indexOf(locus.componentId)]; - pageDiv.m.place = pageDiv.m.place || new Monocle.Place(); - pageDiv.m.place.setPlace(component, locus.page); + if (locus && !locus.load) { + var evtData = { locus: locus, page: pageDiv } + if (locus.boundarystart) { + pageDiv.m.reader.dispatchEvent('monocle:boundarystart', evtData); + } else if (locus.boundaryend) { + pageDiv.m.reader.dispatchEvent('monocle:boundaryend', evtData); + } else { + var component = p.components[p.componentIds.indexOf(locus.componentId)]; + pageDiv.m.place = pageDiv.m.place || new Monocle.Place(); + pageDiv.m.place.setPlace(component, locus.page); - var evtData = { - page: pageDiv, - locus: locus, - pageNumber: pageDiv.m.place.pageNumber(), - componentId: locus.componentId + var evtData = { + page: pageDiv, + locus: locus, + pageNumber: pageDiv.m.place.pageNumber(), + componentId: locus.componentId + } + pageDiv.m.reader.dispatchEvent("monocle:pagechange", evtData); } - pageDiv.m.reader.dispatchEvent("monocle:pagechange", evtData); } return locus; } @@ -1683,6 +1757,10 @@ Monocle.Book = function (dataSource) { locus = pageNumberAt(pageDiv, locus); } + if (!locus) { + return; + } + if (!locus.load) { callback(locus); return; @@ -1690,7 +1768,9 @@ Monocle.Book = function (dataSource) { var findPageNumber = function () { locus = setPageAt(pageDiv, locus); - if (locus.load) { + if (!locus) { + return; + } else if (locus.load) { loadPageAt(pageDiv, locus, callback, progressCallback) } else { callback(locus); @@ -1715,10 +1795,12 @@ Monocle.Book = function (dataSource) { } - function setOrLoadPageAt(pageDiv, locus, callback, progressCallback) { + function setOrLoadPageAt(pageDiv, locus, callback, onProgress, onFail) { locus = setPageAt(pageDiv, locus); - if (locus.load) { - loadPageAt(pageDiv, locus, callback, progressCallback); + if (!locus) { + if (onFail) { onFail(); } + } else if (locus.load) { + loadPageAt(pageDiv, locus, callback, onProgress); } else { callback(locus); } @@ -1864,13 +1946,18 @@ Monocle.Place = function () { } - function percentageThrough() { + function percentAtTopOfPage() { + return p.percent - 1.0 / p.component.lastPageNumber(); + } + + + function percentAtBottomOfPage() { return p.percent; } - function pageAtPercentageThrough(pc) { - return Math.max(Math.round(p.component.lastPageNumber() * pc), 1); + function pageAtPercentageThrough(percent) { + return Math.max(Math.round(p.component.lastPageNumber() * percent), 1); } @@ -1911,6 +1998,8 @@ Monocle.Place = function () { } if (options.direction) { locus.page += options.direction; + } else { + locus.percent = percentAtBottomOfPage(); } return locus; } @@ -1942,7 +2031,9 @@ Monocle.Place = function () { API.setPlace = setPlace; API.setPercentageThrough = setPercentageThrough; API.componentId = componentId; - API.percentageThrough = percentageThrough; + API.percentAtTopOfPage = percentAtTopOfPage; + API.percentAtBottomOfPage = percentAtBottomOfPage; + API.percentageThrough = percentAtBottomOfPage; API.pageAtPercentageThrough = pageAtPercentageThrough; API.pageNumber = pageNumber; API.chapterInfo = chapterInfo; @@ -2158,11 +2249,13 @@ Monocle.Component = function (book, id, index, chapters, source) { if (p.chapters[0] && typeof p.chapters[0].percent == "number") { return; } + var doc = pageDiv.m.activeFrame.contentDocument; for (var i = 0; i < p.chapters.length; ++i) { var chp = p.chapters[i]; chp.percent = 0; if (chp.fragment) { - chp.percent = pageDiv.m.dimensions.percentageThroughOfId(chp.fragment); + var node = doc.getElementById(chp.fragment); + chp.percent = pageDiv.m.dimensions.percentageThroughOfNode(node); } } return p.chapters; @@ -2187,14 +2280,37 @@ Monocle.Component = function (book, id, index, chapters, source) { if (!fragment) { return 1; } - var pc2pn = function (pc) { return Math.floor(pc * p.pageLength) + 1 } for (var i = 0; i < p.chapters.length; ++i) { if (p.chapters[i].fragment == fragment) { - return pc2pn(p.chapters[i].percent); + return percentToPageNumber(p.chapters[i].percent); } } - var percent = pageDiv.m.dimensions.percentageThroughOfId(fragment); - return pc2pn(percent); + var doc = pageDiv.m.activeFrame.contentDocument; + var node = doc.getElementById(fragment); + var percent = pageDiv.m.dimensions.percentageThroughOfNode(node); + return percentToPageNumber(percent); + } + + + function pageForXPath(xpath, pageDiv) { + var doc = pageDiv.m.activeFrame.contentDocument; + var percent = 0; + if (typeof doc.evaluate == "function") { + var node = doc.evaluate( + xpath, + doc, + null, + 9, + null + ).singleNodeValue; + var percent = pageDiv.m.dimensions.percentageThroughOfNode(node); + } + return percentToPageNumber(percent); + } + + + function percentToPageNumber(pc) { + return Math.floor(pc * p.pageLength) + 1; } @@ -2207,6 +2323,7 @@ Monocle.Component = function (book, id, index, chapters, source) { API.updateDimensions = updateDimensions; API.chapterForPage = chapterForPage; API.pageForChapter = pageForChapter; + API.pageForXPath = pageForXPath; API.lastPageNumber = lastPageNumber; return API; @@ -2415,9 +2532,11 @@ Monocle.Dimensions.Vert = function (pageDiv) { } - function percentageThroughOfId(id) { + function percentageThroughOfNode(target) { + if (!target) { + return 0; + } var doc = p.page.m.activeFrame.contentDocument; - var target = doc.getElementById(id); var offset = 0; if (target.getBoundingClientRect) { offset = target.getBoundingClientRect().top; @@ -2456,7 +2575,7 @@ Monocle.Dimensions.Vert = function (pageDiv) { API.hasChanged = hasChanged; API.measure = measure; API.pages = pages; - API.percentageThroughOfId = percentageThroughOfId; + API.percentageThroughOfNode = percentageThroughOfNode; API.locusToOffset = locusToOffset; initialize(); @@ -2713,8 +2832,7 @@ Monocle.Dimensions.Columns = function (pageDiv) { (!p.measurements) || (p.measurements.width != newMeasurements.width) || (p.measurements.height != newMeasurements.height) || - (p.measurements.scrollWidth != newMeasurements.scrollWidth) || - (p.measurements.fontSize != newMeasurements.fontSize) + (p.measurements.scrollWidth != newMeasurements.scrollWidth) ); } @@ -2736,10 +2854,16 @@ Monocle.Dimensions.Columns = function (pageDiv) { if (!lc || !lc.getBoundingClientRect) { console.warn('Empty document for page['+p.page.m.pageIndex+']'); p.measurements.scrollWidth = p.measurements.width; - } else if (lc.getBoundingClientRect().bottom > p.measurements.height) { - p.measurements.scrollWidth = p.measurements.width * 2; } else { - p.measurements.scrollWidth = p.measurements.width; + var bcr = lc.getBoundingClientRect(); + if ( + bcr.right > p.measurements.width || + bcr.bottom > p.measurements.height + ) { + p.measurements.scrollWidth = p.measurements.width * 2; + } else { + p.measurements.scrollWidth = p.measurements.width; + } } } @@ -2758,12 +2882,11 @@ Monocle.Dimensions.Columns = function (pageDiv) { } - function percentageThroughOfId(id) { - var doc = p.page.m.activeFrame.contentDocument; - var target = doc.getElementById(id); + function percentageThroughOfNode(target) { if (!target) { return 0; } + var doc = p.page.m.activeFrame.contentDocument; var offset = 0; if (target.getBoundingClientRect) { offset = target.getBoundingClientRect().left; @@ -2785,20 +2908,30 @@ Monocle.Dimensions.Columns = function (pageDiv) { function componentChanged(evt) { if (evt.m['page'] != p.page) { return; } var doc = evt.m['document']; - Monocle.Styles.applyRules(doc.body, k.BODY_STYLES); + if (Monocle.Browser.has.columnOverflowPaintBug) { + var div = doc.createElement('div'); + Monocle.Styles.applyRules(div, k.BODY_STYLES); + div.style.cssText += "overflow: scroll !important;"; + while (doc.body.childNodes.length) { + div.appendChild(doc.body.firstChild); + } + doc.body.appendChild(div); + } else { + Monocle.Styles.applyRules(doc.body, k.BODY_STYLES); - if (Monocle.Browser.is.WebKit) { - doc.documentElement.style.overflow = 'hidden'; + if (Monocle.Browser.is.WebKit) { + doc.documentElement.style.overflow = 'hidden'; + } } + p.dirty = true; } function setColumnWidth() { var cw = p.page.m.sheafDiv.clientWidth; - var doc = p.page.m.activeFrame.contentDocument; if (currBodyStyleValue('column-width') != cw+"px") { - Monocle.Styles.affix(doc.body, 'column-width', cw+"px"); + Monocle.Styles.affix(columnedElement(), 'column-width', cw+"px"); p.dirty = true; } } @@ -2809,8 +2942,7 @@ Monocle.Dimensions.Columns = function (pageDiv) { return { width: sheaf.clientWidth, height: sheaf.clientHeight, - scrollWidth: scrollerWidth(), - fontSize: currBodyStyleValue('font-size') + scrollWidth: scrollerWidth() } } @@ -2819,16 +2951,24 @@ Monocle.Dimensions.Columns = function (pageDiv) { if (Monocle.Browser.has.mustScrollSheaf) { return p.page.m.sheafDiv; } else { - return p.page.m.activeFrame.contentDocument.body; + return columnedElement(); } } + function columnedElement() { + var elem = p.page.m.activeFrame.contentDocument.body; + return Monocle.Browser.has.columnOverflowPaintBug ? elem.firstChild : elem; + } + + function scrollerWidth() { var bdy = p.page.m.activeFrame.contentDocument.body; if (Monocle.Browser.has.iframeDoubleWidthBug) { - if (Monocle.Browser.on.Android) { - return bdy.scrollWidth * 1.5; // I actually have no idea why 1.5. + if (Monocle.Browser.on.Kindle3) { + return scrollerElement().scrollWidth; + } else if (Monocle.Browser.on.Android) { + return bdy.scrollWidth; } else if (Monocle.Browser.iOSVersion < "4.1") { var hbw = bdy.scrollWidth / 2; var sew = scrollerElement().scrollWidth; @@ -2838,15 +2978,18 @@ Monocle.Dimensions.Columns = function (pageDiv) { var hbw = bdy.scrollWidth / 2; return hbw; } - } else if (Monocle.Browser.is.Gecko) { - var lc = bdy.lastChild; - while (lc && lc.nodeType != 1) { - lc = lc.previousSibling; - } - if (lc && lc.getBoundingClientRect) { - return lc.getBoundingClientRect().right; + } else if (bdy.getBoundingClientRect) { + var elems = bdy.getElementsByTagName('*'); + var bdyRect = bdy.getBoundingClientRect(); + var l = bdyRect.left, r = bdyRect.right; + for (var i = elems.length - 1; i >= 0; --i) { + var rect = elems[i].getBoundingClientRect(); + l = Math.min(l, rect.left); + r = Math.max(r, rect.right); } + return Math.abs(l) + Math.abs(r); } + return scrollerElement().scrollWidth; } @@ -2867,8 +3010,14 @@ Monocle.Dimensions.Columns = function (pageDiv) { function translateToLocus(locus) { var offset = locusToOffset(locus); - var bdy = p.page.m.activeFrame.contentDocument.body; - Monocle.Styles.affix(bdy, "transform", "translateX("+offset+"px)"); + p.page.m.offset = 0 - offset; + if (k.SETX && !Monocle.Browser.has.columnOverflowPaintBug) { + var bdy = p.page.m.activeFrame.contentDocument.body; + Monocle.Styles.affix(bdy, "transform", "translateX("+offset+"px)"); + } else { + var scrElem = scrollerElement(); + scrElem.scrollLeft = 0 - offset; + } return offset; } @@ -2876,7 +3025,7 @@ Monocle.Dimensions.Columns = function (pageDiv) { API.hasChanged = hasChanged; API.measure = measure; API.pages = pages; - API.percentageThroughOfId = percentageThroughOfId; + API.percentageThroughOfNode = percentageThroughOfNode; API.locusToOffset = locusToOffset; API.translateToLocus = translateToLocus; @@ -2898,6 +3047,8 @@ Monocle.Dimensions.Columns.BODY_STYLES = { "column-fill": "auto" } +Monocle.Dimensions.Columns.SETX = true; // Set to false for scrollLeft. + if (Monocle.Browser.has.iframeDoubleWidthBug) { Monocle.Dimensions.Columns.BODY_STYLES["min-width"] = "200%"; } else { @@ -2924,6 +3075,8 @@ Monocle.Flippers.Slider = function (reader) { function addPage(pageDiv) { pageDiv.m.dimensions = new Monocle.Dimensions.Columns(pageDiv); + + Monocle.Styles.setX(pageDiv, "0px"); } @@ -2963,6 +3116,7 @@ Monocle.Flippers.Slider = function (reader) { function interactiveMode(bState) { + p.reader.dispatchEvent('monocle:interactive:'+(bState ? 'on' : 'off')); if (!Monocle.Browser.has.selectThruBug) { return; } @@ -2994,10 +3148,10 @@ Monocle.Flippers.Slider = function (reader) { function moveTo(locus, callback) { var fn = function () { - prepareNextPage(announceTurn); - if (typeof callback == "function") { - callback(); - } + prepareNextPage(function () { + if (typeof callback == "function") { callback(); } + announceTurn(); + }); } setPage(upperPage(), locus, fn); } @@ -3045,12 +3199,26 @@ Monocle.Flippers.Slider = function (reader) { if (dir == k.FORWARDS) { if (getPlace().onLastPageOfBook()) { + p.reader.dispatchEvent( + 'monocle:boundaryend', + { + locus: getPlace().getLocus({ direction : dir }), + page: upperPage() + } + ); resetTurnData(); return; } onGoingForward(boxPointX); } else if (dir == k.BACKWARDS) { if (getPlace().onFirstPageOfBook()) { + p.reader.dispatchEvent( + 'monocle:boundarystart', + { + locus: getPlace().getLocus({ direction : dir }), + page: upperPage() + } + ); resetTurnData(); return; } @@ -3215,14 +3383,14 @@ Monocle.Flippers.Slider = function (reader) { function announceTurn() { - hideWaitControl(upperPage()); - hideWaitControl(lowerPage()); p.reader.dispatchEvent('monocle:turn'); resetTurnData(); } function resetTurnData() { + hideWaitControl(upperPage()); + hideWaitControl(lowerPage()); p.turnData = {}; } @@ -3268,7 +3436,7 @@ Monocle.Flippers.Slider = function (reader) { (new Date()).getTime() - stamp > duration || Math.abs(currX - finalX) <= Math.abs((currX + step) - finalX) ) { - clearTimeout(elem.setXTransitionInterval) + clearTimeout(elem.setXTransitionInterval); Monocle.Styles.setX(elem, finalX); if (elem.setXTCB) { elem.setXTCB(); @@ -3366,13 +3534,17 @@ Monocle.Flippers.Slider = function (reader) { function jumpIn(pageDiv, callback) { var dur = Monocle.Browser.has.jumpFlickerBug ? 1 : 0; - setX(pageDiv, 0, { duration: dur }, callback); + Monocle.defer(function () { + setX(pageDiv, 0, { duration: dur }, callback); + }); } function jumpOut(pageDiv, callback) { var dur = Monocle.Browser.has.jumpFlickerBug ? 1 : 0; - setX(pageDiv, 0 - pageDiv.offsetWidth, { duration: dur }, callback); + Monocle.defer(function () { + setX(pageDiv, 0 - pageDiv.offsetWidth, { duration: dur }, callback); + }); } @@ -3382,7 +3554,9 @@ Monocle.Flippers.Slider = function (reader) { duration: k.durations.SLIDE, timing: 'ease-in' }; - setX(upperPage(), 0, slideOpts, callback); + Monocle.defer(function () { + setX(upperPage(), 0, slideOpts, callback); + }); } @@ -3391,7 +3565,9 @@ Monocle.Flippers.Slider = function (reader) { duration: k.durations.SLIDE, timing: 'ease-in' }; - setX(upperPage(), 0 - upperPage().offsetWidth, slideOpts, callback); + Monocle.defer(function () { + setX(upperPage(), 0 - upperPage().offsetWidth, slideOpts, callback); + }); } @@ -3418,13 +3594,13 @@ Monocle.Flippers.Slider = function (reader) { function showWaitControl(page) { var ctrl = p.reader.dom.find('flippers_slider_wait', page.m.pageIndex); - ctrl.style.opacity = 0.5; + ctrl.style.visibility = "visible"; } function hideWaitControl(page) { var ctrl = p.reader.dom.find('flippers_slider_wait', page.m.pageIndex); - ctrl.style.opacity = 0; + ctrl.style.visibility = "hidden"; } API.pageCount = p.pageCount; diff --git a/resources/images/devices/itunes.png b/resources/images/devices/itunes.png index cd8579d492..cc0493d9eb 100644 Binary files a/resources/images/devices/itunes.png and b/resources/images/devices/itunes.png differ diff --git a/src/calibre/devices/apple/driver.py b/src/calibre/devices/apple/driver.py index e1133ab929..dea5844028 100644 --- a/src/calibre/devices/apple/driver.py +++ b/src/calibre/devices/apple/driver.py @@ -135,7 +135,8 @@ class ITUNES(DriverBase): ''' Calling sequences: Initialization: - can_handle() or can_handle_windows() + can_handle() | can_handle_windows() + _launch_iTunes() reset() open() card_prefix() diff --git a/src/calibre/devices/nook/driver.py b/src/calibre/devices/nook/driver.py index 2fe8f667b0..9c8f882f3d 100644 --- a/src/calibre/devices/nook/driver.py +++ b/src/calibre/devices/nook/driver.py @@ -88,6 +88,7 @@ class NOOK_COLOR(NOOK): WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = 'EBOOK_DISK' EBOOK_DIR_MAIN = 'My Files' + NEWS_IN_FOLDER = False def upload_cover(self, path, filename, metadata, filepath): pass diff --git a/src/calibre/devices/usbms/device.py b/src/calibre/devices/usbms/device.py index f0090989d9..442f3701c4 100644 --- a/src/calibre/devices/usbms/device.py +++ b/src/calibre/devices/usbms/device.py @@ -101,6 +101,9 @@ class Device(DeviceConfig, DevicePlugin): #: The maximum length of paths created on the device MAX_PATH_LEN = 250 + #: Put news in its own folder + NEWS_IN_FOLDER = True + def reset(self, key='-1', log_packets=False, report_progress=None, detected_device=None): self._main_prefix = self._card_a_prefix = self._card_b_prefix = None @@ -946,7 +949,8 @@ class Device(DeviceConfig, DevicePlugin): extra_components = [] tag = special_tag if tag.startswith(_('News')): - extra_components.append('News') + if self.NEWS_IN_FOLDER: + extra_components.append('News') else: for c in tag.split('/'): c = sanitize(c) diff --git a/src/calibre/ebooks/mobi/writer.py b/src/calibre/ebooks/mobi/writer.py index 2ca62f0dea..bf9de37513 100644 --- a/src/calibre/ebooks/mobi/writer.py +++ b/src/calibre/ebooks/mobi/writer.py @@ -241,6 +241,7 @@ class Serializer(object): if self.write_page_breaks_after_item: buffer.write('') buffer.write('
') + self.anchor_offset = None def serialize_elem(self, elem, item, nsrmap=NSRMAP): buffer = self.buffer diff --git a/src/calibre/gui2/dialogs/plugin_updater.py b/src/calibre/gui2/dialogs/plugin_updater.py index 146a7cd64a..e7d641b43e 100644 --- a/src/calibre/gui2/dialogs/plugin_updater.py +++ b/src/calibre/gui2/dialogs/plugin_updater.py @@ -586,7 +586,7 @@ class PluginUpdaterDialog(SizePersistedDialog): # Force our toolbar/action to be updated based on uninstalled updates if self.model: update_plugins = filter(filter_upgradeable_plugins, self.model.display_plugins) - self.gui.plugin_update_found(len(update_plugins)) + self.gui.recalc_update_label(len(update_plugins)) self.reject() def _plugin_current_changed(self, current, previous): diff --git a/src/calibre/gui2/metadata/single_download.py b/src/calibre/gui2/metadata/single_download.py index 013ab42684..ff4b9feac8 100644 --- a/src/calibre/gui2/metadata/single_download.py +++ b/src/calibre/gui2/metadata/single_download.py @@ -236,6 +236,11 @@ class ResultsView(QTableView): # {{{ self.resizeRowsToContents() self.resizeColumnsToContents() self.setFocus(Qt.OtherFocusReason) + idx = self.model().index(0, 0) + if idx.isValid() and self.model().rowCount() > 0: + self.show_details(idx) + sm = self.selectionModel() + sm.select(idx, sm.ClearAndSelect|sm.Rows) def currentChanged(self, current, previous): ret = QTableView.currentChanged(self, current, previous) @@ -480,12 +485,6 @@ class IdentifyWidget(QWidget): # {{{ return self.results_view.show_results(self.worker.results) - - self.comments_view.show_data(''' -
Found %d results
-
To see details, click on any result
''' % - len(self.worker.results)) - self.results_found.emit() diff --git a/src/calibre/gui2/preferences/plugins.ui b/src/calibre/gui2/preferences/plugins.ui index a3655df2b8..b4dfd4426e 100644 --- a/src/calibre/gui2/preferences/plugins.ui +++ b/src/calibre/gui2/preferences/plugins.ui @@ -122,13 +122,13 @@ - + - &Add a new plugin + Get &new plugins - :/images/plugins.png:/images/plugins.png + :/images/plugins/plugin_new.png:/images/plugins/plugin_new.png @@ -144,13 +144,13 @@ - + - Get &new plugins + &Load plugin from file - :/images/plugins/plugin_new.png:/images/plugins/plugin_new.png + :/images/document_open.png:/images/document_open.png diff --git a/src/calibre/gui2/update.py b/src/calibre/gui2/update.py index ed159f4778..aacf30fe10 100644 --- a/src/calibre/gui2/update.py +++ b/src/calibre/gui2/update.py @@ -122,28 +122,36 @@ class UpdateNotification(QDialog): class UpdateMixin(object): def __init__(self, opts): + self.last_newest_calibre_version = NO_CALIBRE_UPDATE if not opts.no_update_check: self.update_checker = CheckForUpdates(self) self.update_checker.update_found.connect(self.update_found, type=Qt.QueuedConnection) self.update_checker.start() - def update_found(self, version, force=False): + def recalc_update_label(self, number_of_plugin_updates): + self.update_found('%s%s%d'%(self.last_newest_calibre_version, VSEP, + number_of_plugin_updates), no_show_popup=True) + + def update_found(self, version, force=False, no_show_popup=False): try: calibre_version, plugin_updates = version.split(VSEP) plugin_updates = int(plugin_updates) except: traceback.print_exc() return + self.last_newest_calibre_version = calibre_version has_calibre_update = calibre_version and calibre_version != NO_CALIBRE_UPDATE has_plugin_updates = plugin_updates > 0 + self.plugin_update_found(plugin_updates) + if not has_calibre_update and not has_plugin_updates: self.status_bar.update_label.setVisible(False) return if has_calibre_update: plt = u'' if has_plugin_updates: - plt = ' (%d plugin updates)'%plugin_updates + plt = _(' (%d plugin updates)')%plugin_updates msg = (u'%s: ' u'%s%s') % ( _('Update found'), version, calibre_version, plt) @@ -153,15 +161,14 @@ class UpdateMixin(object): self.status_bar.update_label.setText(msg) self.status_bar.update_label.setVisible(True) - if has_plugin_updates: - self.plugin_update_found(plugin_updates) if has_calibre_update: - if force or (config.get('new_version_notification') and \ - dynamic.get('update to version %s'%calibre_version, True)): - self._update_notification__ = UpdateNotification(calibre_version, - plugin_updates, parent=self) - self._update_notification__.show() + if (force or (config.get('new_version_notification') and + dynamic.get('update to version %s'%calibre_version, True))): + if not no_show_popup: + self._update_notification__ = UpdateNotification(calibre_version, + plugin_updates, parent=self) + self._update_notification__.show() elif has_plugin_updates: if force: from calibre.gui2.dialogs.plugin_updater import (PluginUpdaterDialog, diff --git a/src/calibre/library/catalog.py b/src/calibre/library/catalog.py index a19534191b..97454c90e2 100644 --- a/src/calibre/library/catalog.py +++ b/src/calibre/library/catalog.py @@ -149,6 +149,15 @@ class CSV_XML(CatalogPlugin): # {{{ elif field == 'comments': item = item.replace(u'\r\n',u' ') item = item.replace(u'\n',u' ') + + # Convert HTML to markdown text + if type(item) is unicode: + opening_tag = re.search('<(\w+)(\x20|>)',item) + if opening_tag: + closing_tag = re.search('<\/%s>$' % opening_tag.group(1), item) + if closing_tag: + item = html2text(item) + outstr.append(u'"%s"' % unicode(item).replace('"','""')) outfile.write(u','.join(outstr) + u'\n') diff --git a/src/calibre/manual/faq.rst b/src/calibre/manual/faq.rst index 274bf03eb3..4b527e169c 100644 --- a/src/calibre/manual/faq.rst +++ b/src/calibre/manual/faq.rst @@ -515,7 +515,7 @@ Downloading from the internet can sometimes result in a corrupted download. If t * Try rebooting your computer and running a registry cleaner like `Wise registry cleaner `_. * Try downloading the installer with an alternate browser. For example if you are using Internet Explorer, try using Firefox or Chrome instead. -Best place to ask for more help is in the `forums `_. +If you still cannot get the installer to work and you are on windows, you can use the `calibre portable install `_, which does not need an installer (it is just a zip file). My antivirus program claims |app| is a virus/trojan? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~