From 411c397bede89df5cee37c6358bb0b555e922539 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 29 Mar 2009 10:37:30 -0700 Subject: [PATCH 01/10] Fix #2175 (Error when trying to open ebook viewer) --- src/calibre/gui2/viewer/documentview.py | 182 ++++++++++++------------ 1 file changed, 91 insertions(+), 91 deletions(-) diff --git a/src/calibre/gui2/viewer/documentview.py b/src/calibre/gui2/viewer/documentview.py index 6b821eed55..89fc7824e1 100644 --- a/src/calibre/gui2/viewer/documentview.py +++ b/src/calibre/gui2/viewer/documentview.py @@ -52,29 +52,29 @@ def config(defaults=None): c = Config('viewer', desc) else: c = StringConfig(defaults, desc) - + c.add_opt('user_css', default='', help=_('Set the user CSS stylesheet. This can be used to customize the look of all books.')) - + 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', help=_('The serif font family')) - fonts('sans_family', default='Verdana' if iswindows else 'Liberation Sans', + fonts('sans_family', default='Verdana' if iswindows else 'Liberation Sans', help=_('The sans-serif font family')) - fonts('mono_family', default='Courier New' if iswindows else 'Liberation Mono', + fonts('mono_family', default='Courier New' if iswindows else 'Liberation Mono', help=_('The monospaced font family')) fonts('default_font_size', default=20, help=_('The standard font size in px')) fonts('mono_font_size', default=16, help=_('The monospaced font size in px')) fonts('standard_font', default='serif', help=_('The standard font type')) - + return c class ConfigDialog(QDialog, Ui_Dialog): - + def __init__(self, *args): QDialog.__init__(self, *args) self.setupUi(self) - + opts = config().parse() self.serif_family.setCurrentFont(QFont(opts.serif_family)) self.sans_family.setCurrentFont(QFont(opts.sans_family)) @@ -84,7 +84,7 @@ class ConfigDialog(QDialog, Ui_Dialog): self.standard_font.setCurrentIndex({'serif':0, 'sans':1, 'mono':2}[opts.standard_font]) self.css.setPlainText(opts.user_css) self.css.setToolTip(_('Set the user CSS stylesheet. This can be used to customize the look of all books.')) - + def accept(self, *args): c = config() c.set('serif_family', unicode(self.serif_family.currentFont().family())) @@ -95,10 +95,10 @@ class ConfigDialog(QDialog, Ui_Dialog): c.set('standard_font', {0:'serif', 1:'sans', 2:'mono'}[self.standard_font.currentIndex()]) c.set('user_css', unicode(self.css.toPlainText())) return QDialog.accept(self, *args) - + class Document(QWebPage): - + def set_font_settings(self): opts = config().parse() settings = self.settings() @@ -110,14 +110,14 @@ class Document(QWebPage): settings.setFontFamily(QWebSettings.SerifFont, opts.serif_family) settings.setFontFamily(QWebSettings.SansSerifFont, opts.sans_family) settings.setFontFamily(QWebSettings.FixedFont, opts.mono_family) - + def do_config(self, parent=None): d = ConfigDialog(parent) if d.exec_() == QDialog.Accepted: self.set_font_settings() self.set_user_stylesheet() self.triggerAction(QWebPage.Reload) - + def __init__(self, *args): QWebPage.__init__(self, *args) self.setLinkDelegationPolicy(self.DelegateAllLinks) @@ -125,53 +125,53 @@ class Document(QWebPage): pal = self.palette() pal.setBrush(QPalette.Background, QColor(0xee, 0xee, 0xee)) self.setPalette(pal) - + settings = self.settings() - + # Fonts load_builtin_fonts() self.set_font_settings() - + # Security settings.setAttribute(QWebSettings.JavaEnabled, False) settings.setAttribute(QWebSettings.PluginsEnabled, False) settings.setAttribute(QWebSettings.JavascriptCanOpenWindows, False) settings.setAttribute(QWebSettings.JavascriptCanAccessClipboard, False) - + # Miscellaneous settings.setAttribute(QWebSettings.LinksIncludedInFocusChain, True) self.set_user_stylesheet() - + # Load jQuery - self.connect(self.mainFrame(), SIGNAL('javaScriptWindowObjectCleared()'), + self.connect(self.mainFrame(), SIGNAL('javaScriptWindowObjectCleared()'), self.load_javascript_libraries) - + def set_user_stylesheet(self): raw = config().parse().user_css pt = PersistentTemporaryFile('_user_stylesheet.css') pt.write(raw.encode('utf-8')) pt.close() self.settings().setUserStyleSheetUrl(QUrl.fromLocalFile(pt.name)) - + def load_javascript_libraries(self): from calibre.resources import jquery, jquery_scrollTo self.javascript(jquery) self.javascript(jquery_scrollTo) self.javascript(bookmarks) self.javascript(referencing) - + def reference_mode(self, enable): self.javascript(('enter' if enable else 'leave')+'_reference_mode()') - + def set_reference_prefix(self, prefix): self.javascript('reference_prefix = "%s"'%prefix) - + def goto(self, ref): self.javascript('goto_reference("%s")'%ref) - + def goto_bookmark(self, bm): self.javascript('scroll_to_bookmark("%s")'%bm) - + def javascript(self, string, typ=None): ans = self.mainFrame().evaluateJavaScript(string) if typ == 'int': @@ -182,65 +182,65 @@ class Document(QWebPage): if typ == 'string': return unicode(ans.toString()) return ans - + def scroll_by(self, x=0, y=0): self.javascript('window.scrollBy(%d, %d)'%(x, y)) - + def scroll_to(self, x=0, y=0): self.javascript('window.scrollTo(%d, %d)'%(x, y)) - + def jump_to_anchor(self, anchor): self.javascript('document.location.hash = "%s"'%anchor) - + def quantize(self): if self.height > self.window_height: r = self.height%self.window_height if r > 0: self.javascript('document.body.style.paddingBottom = "%dpx"'%r) - + def bookmark(self): return self.javascript('calculate_bookmark(%d)'%(self.ypos+25), 'string') - + @apply def at_bottom(): def fget(self): return self.height - self.ypos <= self.window_height return property(fget=fget) - + @apply def at_top(): def fget(self): return self.ypos <= 0 return property(fget=fget) - - + + def test(self): pass - + @apply def ypos(): def fget(self): return self.javascript('window.pageYOffset', 'int') return property(fget=fget) - + @apply def window_height(): def fget(self): return self.javascript('window.innerHeight', 'int') return property(fget=fget) - + @apply def window_width(): def fget(self): return self.javascript('window.innerWidth', 'int') return property(fget=fget) - + @apply def xpos(): def fget(self): return self.javascript('window.pageXOffset', 'int') return property(fget=fget) - + @apply def scroll_fraction(): def fget(self): @@ -249,19 +249,19 @@ class Document(QWebPage): except ZeroDivisionError: return 0. return property(fget=fget) - + @apply def hscroll_fraction(): def fget(self): return float(self.xpos)/self.width return property(fget=fget) - + @apply def height(): def fget(self): return self.javascript('document.body.offsetHeight', 'int') # contentsSize gives inaccurate results return property(fget=fget) - + @apply def width(): def fget(self): @@ -269,7 +269,7 @@ class Document(QWebPage): return property(fget=fget) class EntityDeclarationProcessor(object): - + def __init__(self, html): self.declared_entities = {} for match in re.finditer(r']+)>', html): @@ -281,9 +281,9 @@ class EntityDeclarationProcessor(object): self.processed_html = self.processed_html.replace('&%s;'%key, val) class DocumentView(QWebView): - - DISABLED_BRUSH = QBrush(Qt.lightGray, Qt.Dense5Pattern) - + + DISABLED_BRUSH = QBrush(Qt.lightGray, Qt.Dense5Pattern) + def __init__(self, *args): QWidget.__init__(self, *args) self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)) @@ -299,83 +299,83 @@ class DocumentView(QWebView): self.connect(self.document, SIGNAL('linkClicked(QUrl)'), self.link_clicked) self.connect(self.document, SIGNAL('linkHovered(QString,QString,QString)'), self.link_hovered) self.connect(self.document, SIGNAL('selectionChanged()'), self.selection_changed) - + def reference_mode(self, enable): self._reference_mode = enable self.document.reference_mode(enable) - + def goto(self, ref): self.document.goto(ref) - + def goto_bookmark(self, bm): self.document.goto_bookmark(bm) - + def config(self, parent=None): self.document.do_config(parent) - + def bookmark(self): return self.document.bookmark() - + def selection_changed(self): if self.manager is not None: self.manager.selection_changed(unicode(self.document.selectedText())) - + def set_manager(self, manager): self.manager = manager self.scrollbar = manager.horizontal_scrollbar self.connect(self.scrollbar, SIGNAL('valueChanged(int)'), self.scroll_horizontally) - + def scroll_horizontally(self, amount): self.document.scroll_to(y=self.document.ypos, x=amount) - + def link_hovered(self, link, text, context): link, text = unicode(link), unicode(text) if link: self.setCursor(Qt.PointingHandCursor) else: - self.unsetCursor() - + self.unsetCursor() + def link_clicked(self, url): if self.manager is not None: self.manager.link_clicked(url) - + def sizeHint(self): return self._size_hint - + @apply def scroll_fraction(): def fget(self): return self.document.scroll_fraction return property(fget=fget) - + @apply def hscroll_fraction(): def fget(self): return self.document.hscroll_fraction return property(fget=fget) - + @apply def content_size(): def fget(self): return self.document.width, self.document.height return property(fget=fget) - + def search(self, text): return self.findText(text) - + def path(self): return os.path.abspath(unicode(self.url().toLocalFile())) - + def load_path(self, path, pos=0.0): self.initial_pos = pos - html = open(path, 'rb').read().decode(path.encoding) + html = open(path, 'rb').read().decode(path.encoding, 'replace') html = EntityDeclarationProcessor(html).processed_html self.setHtml(html, QUrl.fromLocalFile(path)) - + def load_started(self): if self.manager is not None: self.manager.load_started() - + def initialize_scrollbar(self): if getattr(self, 'scrollbar', None) is not None: delta = self.document.width - self.size().width() @@ -387,7 +387,7 @@ class DocumentView(QWebView): self.scrollbar.setPageStep(int(delta/10.)) self.scrollbar.blockSignals(False) self.scrollbar.setVisible(delta > 0) - + def load_finished(self, ok): self.document.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff) self.document.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff) @@ -409,8 +409,8 @@ class DocumentView(QWebView): self.document.set_reference_prefix('%d.'%(spine_index+1)) if scrolled: self.manager.scrolled(self.document.scroll_fraction) - - + + @classmethod def test_line(cls, img, y): start = img.pixel(0, y) @@ -418,7 +418,7 @@ class DocumentView(QWebView): if img.pixel(i, y) != start: return False return True - + def find_next_blank_line(self, overlap): img = QImage(self.width(), overlap, QImage.Format_ARGB32) painter = QPainter(img) @@ -428,8 +428,8 @@ class DocumentView(QWebView): if self.test_line(img, i): self.scroll_by(y=i, notify=False) return - self.scroll_by(y=overlap) - + self.scroll_by(y=overlap) + def previous_page(self): if self.document.at_top: if self.manager is not None: @@ -448,12 +448,12 @@ class DocumentView(QWebView): break if self.manager is not None: self.manager.scrolled(self.scroll_fraction) - + def wheel_event(self, down=True): - QWebView.wheelEvent(self, - QWheelEvent(QPoint(100, 100), (-120 if down else 120), + QWebView.wheelEvent(self, + QWheelEvent(QPoint(100, 100), (-120 if down else 120), Qt.NoButton, Qt.NoModifier)) - + def next_page(self): if self.document.at_bottom: if self.manager is not None: @@ -472,14 +472,14 @@ class DocumentView(QWebView): self.find_next_blank_line( self.height() - (self.document.ypos-opos) ) if self.manager is not None: self.manager.scrolled(self.scroll_fraction) - - + + def scroll_by(self, x=0, y=0, notify=True): old_pos = self.document.ypos self.document.scroll_by(x, y) if notify and self.manager is not None and self.document.ypos != old_pos: self.manager.scrolled(self.scroll_fraction) - + def scroll_to(self, pos, notify=True): old_pos = self.document.ypos if isinstance(pos, basestring): @@ -492,30 +492,30 @@ class DocumentView(QWebView): pos*(self.document.height-self.document.window_height)))) if notify and self.manager is not None and self.document.ypos != old_pos: self.manager.scrolled(self.scroll_fraction) - + def multiplier(self): return self.document.mainFrame().textSizeMultiplier() - + def magnify_fonts(self): self.document.mainFrame().setTextSizeMultiplier(self.multiplier()+0.2) return self.document.scroll_fraction - + def shrink_fonts(self): self.document.mainFrame().setTextSizeMultiplier(max(self.multiplier()-0.2, 0)) return self.document.scroll_fraction - + def changeEvent(self, event): if event.type() == event.EnabledChange: self.update() return QWebView.changeEvent(self, event) - + def paintEvent(self, event): painter = QPainter(self) self.document.mainFrame().render(painter, event.region()) if not self.isEnabled(): painter.fillRect(event.region().boundingRect(), self.DISABLED_BRUSH) painter.end() - + def wheelEvent(self, event): if event.delta() < -14: if self.document.at_bottom: @@ -533,7 +533,7 @@ class DocumentView(QWebView): if self.manager is not None: self.manager.scrolled(self.scroll_fraction) return ret - + def keyPressEvent(self, event): key = event.key() if key in [Qt.Key_PageDown, Qt.Key_Space, Qt.Key_Down]: @@ -562,14 +562,14 @@ class DocumentView(QWebView): self.scroll_by(x=15) else: return QWebView.keyPressEvent(self, event) - + def resizeEvent(self, event): ret = QWebView.resizeEvent(self, event) QTimer.singleShot(10, self.initialize_scrollbar) if self.manager is not None: self.manager.viewport_resized(self.scroll_fraction) return ret - + def mouseReleaseEvent(self, ev): opos = self.document.ypos ret = QWebView.mouseReleaseEvent(self, ev) @@ -578,4 +578,4 @@ class DocumentView(QWebView): self.manager.scrolled(self.scroll_fraction) return ret - \ No newline at end of file + From f45e84bbe4aad16309a356976b351ef127108510 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 29 Mar 2009 10:53:55 -0700 Subject: [PATCH 02/10] Fix bug in ebook viewer that could cause it to hang wen finding a bookmark --- src/calibre/gui2/viewer/js.py | 6 +- src/calibre/gui2/viewer/main.py | 158 ++++++++++++++++---------------- 2 files changed, 82 insertions(+), 82 deletions(-) diff --git a/src/calibre/gui2/viewer/js.py b/src/calibre/gui2/viewer/js.py index af5a2f5e80..063731acea 100644 --- a/src/calibre/gui2/viewer/js.py +++ b/src/calibre/gui2/viewer/js.py @@ -18,7 +18,7 @@ function find_enclosing_block(y) { if (min != 0 && min.height() < 200) break; } if (y <= 0) return document.body; - if (min == 0) { return find_enclosing_block(x, y-20); } + if (min == 0) { return find_enclosing_block(y-20); } return min; } @@ -93,7 +93,7 @@ function enter_reference_mode() { } function leave_reference_mode() { - $("p").unbind("mouseenter mouseleave", toggle_reference); + $("p").unbind("mouseenter mouseleave", toggle_reference); } function goto_reference(ref) { @@ -118,4 +118,4 @@ $(document.body).click(function(e) { $(document).ready(enter_reference_mode); -''' \ No newline at end of file +''' diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py index 5360cfd453..b79b5518cf 100644 --- a/src/calibre/gui2/viewer/main.py +++ b/src/calibre/gui2/viewer/main.py @@ -25,7 +25,7 @@ from calibre.gui2.library import SearchBox from calibre.ebooks.metadata import MetaInformation class TOCItem(QStandardItem): - + def __init__(self, toc): QStandardItem.__init__(self, toc.text if toc.text else '') self.abspath = toc.abspath @@ -33,23 +33,23 @@ class TOCItem(QStandardItem): for t in toc: self.appendRow(TOCItem(t)) self.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable) - + @classmethod def type(cls): return QStandardItem.UserType+10 class TOC(QStandardItemModel): - + def __init__(self, toc): QStandardItemModel.__init__(self) for t in toc: self.appendRow(TOCItem(t)) self.setHorizontalHeaderItem(0, QStandardItem(_('Table of Contents'))) - - + + class Worker(Thread): - + def run(self): try: Thread.run(self) @@ -59,7 +59,7 @@ class Worker(Thread): self.traceback = traceback.format_exc() class ProgressIndicator(QWidget): - + def __init__(self, *args): QWidget.__init__(self, *args) self.setGeometry(0, 0, 300, 500) @@ -74,7 +74,7 @@ class ProgressIndicator(QWidget): self.status.font().setBold(True) self.status.font().setPointSize(self.font().pointSize()+6) self.setVisible(False) - + def start(self, msg=''): view = self.parent() pwidth, pheight = view.size().width(), view.size().height() @@ -87,25 +87,25 @@ class ProgressIndicator(QWidget): self.status.setText(msg) self.setVisible(True) self.movie.setPaused(False) - + def stop(self): if self.movie.state() == self.movie.Running: self.movie.setPaused(True) self.setVisible(False) class History(collections.deque): - + def __init__(self, action_back, action_forward): self.action_back = action_back self.action_forward = action_forward collections.deque.__init__(self) self.pos = 0 self.set_actions() - + def set_actions(self): self.action_back.setDisabled(self.pos < 1) self.action_forward.setDisabled(self.pos + 1 >= len(self)) - + def back(self, from_pos): if self.pos - 1 < 0: return None if self.pos == len(self): @@ -114,56 +114,56 @@ class History(collections.deque): self.pos -= 1 self.set_actions() return self[self.pos] - + def forward(self): if self.pos + 1 >= len(self): return None self.pos += 1 self.set_actions() return self[self.pos] - + def add(self, item): while len(self) > self.pos+1: self.pop() self.append(item) self.pos += 1 self.set_actions() - + class Metadata(QLabel): - + def __init__(self, parent): QTextBrowser.__init__(self, parent.centralWidget()) self.view = parent.splitter self.setGeometry(self.view.geometry()) self.setWordWrap(True) self.setVisible(False) - + def show_opf(self, opf): mi = MetaInformation(opf) html = '

%s

%s'%(_('Metadata'), u''.join(mi.to_html())) self.setText(html) - + def setVisible(self, x): self.setGeometry(self.view.geometry()) QLabel.setVisible(self, x) - + def paintEvent(self, ev): p = QPainter(self) p.fillRect(ev.region().boundingRect(), QBrush(QColor(200, 200, 200, 220), Qt.SolidPattern)) p.end() QLabel.paintEvent(self, ev) - - + + class DoubleSpinBox(QDoubleSpinBox): - + def set_value(self, val): self.blockSignals(True) self.setValue(val) self.blockSignals(False) class HelpfulLineEdit(QLineEdit): - + HELP_TEXT = _('Go to...') - + def __init__(self, *args): QLineEdit.__init__(self, *args) self.default_palette = QApplication.palette(self) @@ -172,22 +172,22 @@ class HelpfulLineEdit(QLineEdit): self.connect(self, SIGNAL('editingFinished()'), lambda : self.emit(SIGNAL('goto(PyQt_PyObject)'), unicode(self.text()))) self.clear_to_help_mode() - + def focusInEvent(self, ev): self.setPalette(QApplication.palette(self)) if self.in_help_mode(): self.setText('') return QLineEdit.focusInEvent(self, ev) - + def in_help_mode(self): return unicode(self.text()) == self.HELP_TEXT - + def clear_to_help_mode(self): self.setPalette(self.gray) self.setText(self.HELP_TEXT) - + class EbookViewer(MainWindow, Ui_EbookViewer): - + def __init__(self, pathtoebook=None): MainWindow.__init__(self, None) self.setupUi(self) @@ -222,14 +222,14 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.action_quit = QAction(self) self.addAction(self.action_quit) self.action_quit.setShortcut(Qt.CTRL+Qt.Key_Q) - self.connect(self.action_quit, SIGNAL('triggered(bool)'), + self.connect(self.action_quit, SIGNAL('triggered(bool)'), lambda x:QApplication.instance().quit()) self.action_copy.setDisabled(True) self.action_metadata.setCheckable(True) self.action_metadata.setShortcut(Qt.CTRL+Qt.Key_I) self.action_table_of_contents.setCheckable(True) self.action_reference_mode.setCheckable(True) - self.connect(self.action_reference_mode, SIGNAL('triggered(bool)'), + self.connect(self.action_reference_mode, SIGNAL('triggered(bool)'), lambda x: self.view.reference_mode(x)) self.connect(self.action_metadata, SIGNAL('triggered(bool)'), lambda x:self.metadata.setVisible(x)) self.connect(self.action_table_of_contents, SIGNAL('triggered(bool)'), lambda x:self.toc.setVisible(x)) @@ -244,7 +244,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): lambda x:self.view.next_page()) self.connect(self.action_previous_page, SIGNAL('triggered(bool)'), lambda x:self.view.previous_page()) - self.connect(self.action_find_next, SIGNAL('triggered(bool)'), + self.connect(self.action_find_next, SIGNAL('triggered(bool)'), lambda x:self.find(unicode(self.search.text()), True, repeat=True)) self.connect(self.action_full_screen, SIGNAL('triggered(bool)'), self.toggle_fullscreen) @@ -254,12 +254,12 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.connect(self.action_forward, SIGNAL('triggered(bool)'), self.forward) self.connect(self.action_preferences, SIGNAL('triggered(bool)'), lambda x: self.view.config(self)) self.connect(self.pos, SIGNAL('valueChanged(double)'), self.goto_page) - self.connect(self.vertical_scrollbar, SIGNAL('valueChanged(int)'), + self.connect(self.vertical_scrollbar, SIGNAL('valueChanged(int)'), lambda x: self.goto_page(x/100.)) self.connect(self.search, SIGNAL('search(PyQt_PyObject, PyQt_PyObject)'), self.find) self.connect(self.toc, SIGNAL('clicked(QModelIndex)'), self.toc_clicked) self.connect(self.reference, SIGNAL('goto(PyQt_PyObject)'), self.goto) - + self.set_bookmarks([]) if pathtoebook is not None: f = functools.partial(self.load_ebook, pathtoebook) @@ -277,18 +277,18 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.showNormal() else: self.showFullScreen() - + def goto(self, ref): if ref: tokens = ref.split('.') if len(tokens) > 1: - spine_index = int(tokens[0]) -1 + spine_index = int(tokens[0]) -1 if spine_index == self.current_index: self.view.goto(ref) else: self.pending_reference = ref self.load_path(self.iterator.spine[spine_index]) - + def goto_bookmark(self, bm): m = bm[1].split('#') if len(m) > 1: @@ -298,39 +298,39 @@ class EbookViewer(MainWindow, Ui_EbookViewer): else: self.pending_bookmark = bm self.load_path(self.iterator.spine[spine_index]) - + def toc_clicked(self, index): item = self.toc_model.itemFromIndex(index) url = QUrl.fromLocalFile(item.abspath) if item.fragment: url.setFragment(item.fragment) self.link_clicked(url) - + def selection_changed(self, selected_text): self.selected_text = selected_text.strip() self.action_copy.setEnabled(bool(self.selected_text)) - + def copy(self, x): if self.selected_text: QApplication.clipboard().setText(self.selected_text) - + def back(self, x): pos = self.history.back(self.pos.value()) if pos is not None: self.goto_page(pos) - - + + def forward(self, x): pos = self.history.forward() if pos is not None: self.goto_page(pos) - + def goto_start(self): self.goto_page(1) - + def goto_end(self): self.goto_page(self.pos.maximum()) - + def goto_page(self, new_page): if self.current_page is not None: for page in self.iterator.spine: @@ -343,7 +343,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.view.scroll_to(frac) else: self.load_path(page, pos=frac) - + def open_ebook(self, checked): files = choose_files(self, 'ebook viewer open dialog', _('Choose ebook'), @@ -351,19 +351,19 @@ class EbookViewer(MainWindow, Ui_EbookViewer): select_only_single_file=True) if files: self.load_ebook(files[0]) - + def font_size_larger(self, checked): frac = self.view.magnify_fonts() self.action_font_size_larger.setEnabled(self.view.multiplier() < 3) self.action_font_size_smaller.setEnabled(self.view.multiplier() > 0.2) self.set_page_number(frac) - + def font_size_smaller(self, checked): frac = self.view.shrink_fonts() self.action_font_size_larger.setEnabled(self.view.multiplier() < 3) self.action_font_size_smaller.setEnabled(self.view.multiplier() > 0.2) self.set_page_number(frac) - + def bookmark(self, *args): title, ok = QInputDialog.getText(self, _('Add bookmark'), _('Enter title for bookmark:')) title = unicode(title).strip() @@ -372,8 +372,8 @@ class EbookViewer(MainWindow, Ui_EbookViewer): bookmark = '%d#%s'%(self.current_index, pos) self.iterator.add_bookmark((title, bookmark)) self.set_bookmarks(self.iterator.bookmarks) - - + + def find(self, text, refinement, repeat=False): if not text: return @@ -385,18 +385,18 @@ class EbookViewer(MainWindow, Ui_EbookViewer): if self.current_index > 0: index = self.iterator.search(text, 0) if index is None: - info_dialog(self, _('No matches found'), + info_dialog(self, _('No matches found'), _('No matches found for: %s')%text).exec_() return return self.pending_search = text self.load_path(self.iterator.spine[index]) - + def do_search(self, text): self.pending_search = None if self.view.search(text): self.scrolled(self.view.scroll_fraction) - + def keyPressEvent(self, event): if event.key() == Qt.Key_F3: text = unicode(self.search.text()) @@ -405,10 +405,10 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.search.setFocus(Qt.OtherFocusReason) else: return MainWindow.keyPressEvent(self, event) - + def internal_link_clicked(self, frac): self.history.add(self.pos.value()) - + def link_clicked(self, url): path = os.path.abspath(unicode(url.toLocalFile())) frag = None @@ -424,10 +424,10 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.view.scroll_to(frag) else: QDesktopServices.openUrl(url) - + def load_started(self): self.open_progress_indicator(_('Loading flow...')) - + def load_finished(self, ok): self.close_progress_indicator() path = self.view.path() @@ -451,11 +451,11 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.goto_bookmark(self.pending_bookmark) self.pending_bookmark = None return self.current_index - + def load_path(self, path, pos=0.0): self.open_progress_indicator(_('Laying out %s')%self.current_title) self.view.load_path(path, pos=pos) - + def viewport_resized(self, frac): new_page = self.pos.value() if self.current_page is not None: @@ -466,20 +466,20 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.view.scroll_to(frac, notify=False) else: self.set_page_number(frac) - + def close_progress_indicator(self): self.pi.stop() for o in ('tool_bar', 'tool_bar2', 'view', 'horizontal_scrollbar', 'vertical_scrollbar'): getattr(self, o).setEnabled(True) self.unsetCursor() self.view.setFocus(Qt.PopupFocusReason) - + def open_progress_indicator(self, msg=''): self.pi.start(msg) for o in ('tool_bar', 'tool_bar2', 'view', 'horizontal_scrollbar', 'vertical_scrollbar'): getattr(self, o).setEnabled(False) self.setCursor(Qt.BusyCursor) - + def set_bookmarks(self, bookmarks): menu = QMenu() current_page = None @@ -491,7 +491,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.action_bookmark.setMenu(menu) self._menu = menu return current_page - + def save_current_position(self): try: pos = self.view.bookmark() @@ -499,7 +499,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.iterator.add_bookmark(('calibre_current_page_bookmark', bookmark)) except: traceback.print_exc() - + def load_ebook(self, pathtoebook): if self.iterator is not None: self.save_current_position() @@ -515,7 +515,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): if isinstance(worker.exception, DRMError): error_dialog(self, _('DRM Error'), _('

This book is protected by DRM')%'http://wiki.mobileread.com/wiki/DRM').exec_() else: - ConversionErrorDialog(self, _('Could not open ebook'), + ConversionErrorDialog(self, _('Could not open ebook'), _('%s

%s

')%(worker.exception, worker.traceback.replace('\n', '
')), show=True) self.close_progress_indicator() else: @@ -543,37 +543,37 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.goto_bookmark(previous) else: self.next_document() - + def set_vscrollbar_value(self, pagenum): self.vertical_scrollbar.blockSignals(True) self.vertical_scrollbar.setValue(int(pagenum*100)) self.vertical_scrollbar.blockSignals(False) - + def set_page_number(self, frac): if getattr(self, 'current_page', None) is not None: page = self.current_page.start_page + frac*float(self.current_page.pages-1) self.pos.set_value(page) self.set_vscrollbar_value(page) - + def scrolled(self, frac): self.set_page_number(frac) - + def next_document(self): if self.current_index < len(self.iterator.spine) - 1: self.load_path(self.iterator.spine[self.current_index+1]) - + def previous_document(self): if self.current_index > 0: self.load_path(self.iterator.spine[self.current_index-1], pos=1.0) - + def __enter__(self): return self - + def __exit__(self, *args): if self.iterator is not None: self.save_current_position() self.iterator.__exit__(*args) - + def config(defaults=None): desc = _('Options to control the ebook viewer') @@ -581,8 +581,8 @@ def config(defaults=None): c = Config('viewer', desc) else: c = StringConfig(defaults, desc) - - c.add_opt('raise_window', ['--raise-window'], default=False, + + c.add_opt('raise_window', ['--raise-window'], default=False, help=_('If specified, viewer window will try to come to the ' 'front when started.')) return c @@ -592,7 +592,7 @@ def option_parser(): return c.option_parser(usage=_('''\ %prog [options] file -View an ebook. +View an ebook. ''')) @@ -611,7 +611,7 @@ def main(args=sys.argv): if opts.raise_window: main.raise_() with main: - return app.exec_() + return app.exec_() return 0 if __name__ == '__main__': From 551e07031a14d3ec1ecea807fba39d684ade83ad Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 29 Mar 2009 12:18:59 -0700 Subject: [PATCH 03/10] New recipe for La Prensa Nicaragua by Darko Miletic --- src/calibre/gui2/images/news/laprensa_ni.png | Bin 0 -> 638 bytes src/calibre/web/feeds/recipes/__init__.py | 2 +- .../web/feeds/recipes/recipe_laprensa_ni.py | 96 ++++++++++++++++++ 3 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 src/calibre/gui2/images/news/laprensa_ni.png create mode 100644 src/calibre/web/feeds/recipes/recipe_laprensa_ni.py diff --git a/src/calibre/gui2/images/news/laprensa_ni.png b/src/calibre/gui2/images/news/laprensa_ni.png new file mode 100644 index 0000000000000000000000000000000000000000..226edd4308c55a2b4e464aaa80efc09cef584c16 GIT binary patch literal 638 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b zK-vS0-A-oPfdtD69Mgd`SU*F|v9*U87#Np(x;TbdoW45Ax?dy_^7fs@{r%b2j`}4`r-N^>w!k`tIKEH zB2IVIT0hyWEZNTKeLelr5fA6biJMO}-!-}|nyf0g{bW%UeJmMpWR#k&+4T7Di4ot)ZYV)D(M@tRV?`i;ld&N^0;V|-d< zMVR)J)<-9QTb|z~xBYtY8`JAIBF$UMwoVgg@X`#`mh@3R_;nM5kkQS}EECUN=I86T zD*oj>J)5=N*Y?5VXxY>AR)i=zPFW!?+x~nn>wKG|O+5D(wRoqq{Jilr?O)69UY%zr zmfl^p_%++D{-*MFJ=@#Ii-os5=A6FtbeP|UY>vD+mnC!}TiNg0eSPcptEbs@$(d%& zhc6n==JY&0eI@huTB`%A92E9Cx^nLn=zqyHO}}3H$IK}TeZsrk<=%$zf2t*}5hck*sfi`2x+y?{!N|bCQrEy(*T^!&(9+7#)XLOY z+rYrez~E4wye~{cZhlH;S|zFmV}lT&I#UZPBLj$r#Z7C@05vdpy85}Sb4q9e0O2 Date: Sun, 29 Mar 2009 15:41:35 -0700 Subject: [PATCH 04/10] Fix #2177 (Google ePub TOC) --- src/calibre/ebooks/metadata/opf2.py | 1 + src/calibre/ebooks/metadata/toc.py | 72 ++++++++++++++--------------- 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/calibre/ebooks/metadata/opf2.py b/src/calibre/ebooks/metadata/opf2.py index 0e6bf0b4bf..952978fc36 100644 --- a/src/calibre/ebooks/metadata/opf2.py +++ b/src/calibre/ebooks/metadata/opf2.py @@ -508,6 +508,7 @@ class OPF(object): toc.partition('#')[0], toc.partition('#')[-1] self.toc.read_html_toc(toc) except: + raise pass diff --git a/src/calibre/ebooks/metadata/toc.py b/src/calibre/ebooks/metadata/toc.py index e4f9161ebb..839c966271 100644 --- a/src/calibre/ebooks/metadata/toc.py +++ b/src/calibre/ebooks/metadata/toc.py @@ -1,7 +1,7 @@ #!/usr/bin/env python __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal ' -import os, glob +import os, glob, re from urlparse import urlparse from urllib import unquote @@ -10,17 +10,17 @@ from calibre.ebooks.BeautifulSoup import BeautifulStoneSoup, BeautifulSoup from calibre.ebooks.chardet import xml_to_unicode class NCXSoup(BeautifulStoneSoup): - + NESTABLE_TAGS = {'navpoint':[]} - + def __init__(self, raw): - BeautifulStoneSoup.__init__(self, raw, + BeautifulStoneSoup.__init__(self, raw, convertEntities=BeautifulSoup.HTML_ENTITIES, selfClosingTags=['meta', 'content']) class TOC(list): - - def __init__(self, href=None, fragment=None, text=None, parent=None, play_order=0, + + def __init__(self, href=None, fragment=None, text=None, parent=None, play_order=0, base_path=os.getcwd(), type='unknown'): self.href = href self.fragment = fragment @@ -31,7 +31,7 @@ class TOC(list): self.base_path = base_path self.play_order = play_order self.type = type - + def __str__(self): lines = ['TOC: %s#%s'%(self.href, self.fragment)] for child in self: @@ -39,10 +39,10 @@ class TOC(list): for l in c: lines.append('\t'+l) return '\n'.join(lines) - + def count(self, type): return len([i for i in self.flat() if i.type == type]) - + def purge(self, types, max=0): remove = [] for entry in self.flat(): @@ -54,23 +54,23 @@ class TOC(list): continue entry.parent.remove(entry) return remove - + def remove(self, entry): list.remove(self, entry) entry.parent = None - + def add_item(self, href, fragment, text, play_order=None, type='unknown'): if play_order is None: play_order = (self[-1].play_order if len(self) else self.play_order) + 1 self.append(TOC(href=href, fragment=fragment, text=text, parent=self, base_path=self.base_path, play_order=play_order, type=type)) return self[-1] - + def top_level_items(self): for item in self: if item.text is not None: yield item - + def depth(self): depth = 1 for obj in self: @@ -78,14 +78,14 @@ class TOC(list): if c > depth - 1: depth = c + 1 return depth - + def flat(self): 'Depth first iteration over the tree rooted at self' yield self for obj in self: for i in obj.flat(): yield i - + @apply def abspath(): doc='Return the file this toc entry points to as a absolute path to a file on the system.' @@ -96,9 +96,9 @@ class TOC(list): if not os.path.isabs(path): path = os.path.join(self.base_path, path) return path - - return property(fget=fget, doc=doc) - + + return property(fget=fget, doc=doc) + def read_from_opf(self, opfreader): toc = opfreader.soup.find('spine', toc=True) if toc is not None: @@ -111,7 +111,7 @@ class TOC(list): if 'toc' in item.href().lower(): toc = item.href() break - + if toc is not None: if toc.lower() not in ('ncx', 'ncxtoc'): toc = urlparse(unquote(toc))[2] @@ -123,7 +123,7 @@ class TOC(list): bn = os.path.basename(toc) bn = bn.replace('_top.htm', '_toc.htm') # Bug in BAEN OPF files toc = os.path.join(os.path.dirname(toc), bn) - + self.read_html_toc(toc) except: print 'WARNING: Could not read Table of Contents. Continuing anyway.' @@ -141,43 +141,43 @@ class TOC(list): if m: toc = m[0] self.read_ncx_toc(toc) - + def read_ncx_toc(self, toc): self.base_path = os.path.dirname(toc) soup = NCXSoup(xml_to_unicode(open(toc, 'rb').read())[0]) - + def process_navpoint(np, dest): play_order = np.get('playOrder', None) if play_order is None: play_order = int(np.get('playorder', 1)) href = fragment = text = None - nl = np.find('navlabel') + nl = np.find(re.compile('navlabel')) if nl is not None: text = u'' - for txt in nl.findAll('text'): + for txt in nl.findAll(re.compile('text')): text += ''.join([unicode(s) for s in txt.findAll(text=True)]) - content = np.find('content') + content = np.find(re.compile('content')) if content is None or not content.has_key('src') or not txt: return - + purl = urlparse(unquote(content['src'])) href, fragment = purl[2], purl[5] nd = dest.add_item(href, fragment, text) nd.play_order = play_order - + for c in np: - if getattr(c, 'name', None) == 'navpoint': + if 'navpoint' in getattr(c, 'name', ''): process_navpoint(c, nd) - - nm = soup.find('navmap') + + nm = soup.find(re.compile('navmap')) if nm is None: raise ValueError('NCX files must have a element.') - + for elem in nm: - if getattr(elem, 'name', None) == 'navpoint': + if 'navpoint' in getattr(elem, 'name', ''): process_navpoint(elem, self) - - + + def read_html_toc(self, toc): self.base_path = os.path.dirname(toc) soup = BeautifulSoup(open(toc, 'rb').read(), convertEntities=BeautifulSoup.HTML_ENTITIES) @@ -191,13 +191,13 @@ class TOC(list): else: fragment = fragment.strip() href = href.strip() - + txt = ''.join([unicode(s).strip() for s in a.findAll(text=True)]) add = True for i in self.flat(): if i.href == href and i.fragment == fragment: add = False - break + break if add: self.add_item(href, fragment, txt) From 2ca9cbfa64c76280340d0133d99aa591012492b2 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 29 Mar 2009 23:32:55 -0700 Subject: [PATCH 05/10] IGN:... --- session.vim | 2 +- src/calibre/ebooks/metadata/opf2.py | 3 --- src/calibre/ebooks/oeb/base.py | 5 ++++- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/session.vim b/session.vim index 9d326c5822..f33590c838 100644 --- a/session.vim +++ b/session.vim @@ -1,5 +1,5 @@ " Project wide builtins -let g:pyflakes_builtins += ["dynamic_property"] +let g:pyflakes_builtins += ["dynamic_property", "__"] python << EOFPY import os diff --git a/src/calibre/ebooks/metadata/opf2.py b/src/calibre/ebooks/metadata/opf2.py index 952978fc36..dd3128edef 100644 --- a/src/calibre/ebooks/metadata/opf2.py +++ b/src/calibre/ebooks/metadata/opf2.py @@ -508,11 +508,8 @@ class OPF(object): toc.partition('#')[0], toc.partition('#')[-1] self.toc.read_html_toc(toc) except: - raise pass - - def get_text(self, elem): return u''.join(self.CONTENT(elem) or self.TEXT(elem)) diff --git a/src/calibre/ebooks/oeb/base.py b/src/calibre/ebooks/oeb/base.py index 940b124d88..f7f02f7660 100644 --- a/src/calibre/ebooks/oeb/base.py +++ b/src/calibre/ebooks/oeb/base.py @@ -201,6 +201,9 @@ def urlnormalize(href): class OEBError(Exception): pass +class NotHTML(OEBError): + pass + class FauxLogger(object): def __getattr__(self, name): @@ -538,7 +541,7 @@ class Manifest(object): data = etree.fromstring(data, parser=RECOVER_PARSER) # Force into the XHTML namespace if barename(data.tag) != 'html': - raise OEBError( + raise NotHTML( 'File %r does not appear to be (X)HTML' % self.href) elif not namespace(data.tag): data.attrib['xmlns'] = XHTML_NS From 0fbd15a76d6ddaa9bb8b96a0814ef471f99f23b2 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 30 Mar 2009 00:05:01 -0700 Subject: [PATCH 06/10] Fix #2182 (I would like larger margins) --- src/calibre/gui2/dialogs/lrf_single.ui | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/calibre/gui2/dialogs/lrf_single.ui b/src/calibre/gui2/dialogs/lrf_single.ui index 271f8e7059..87c7382770 100644 --- a/src/calibre/gui2/dialogs/lrf_single.ui +++ b/src/calibre/gui2/dialogs/lrf_single.ui @@ -727,7 +727,7 @@ px - 200 + 250 20 @@ -750,7 +750,7 @@ px - 200 + 250 20 @@ -773,7 +773,7 @@ px - 200 + 250 10 @@ -796,7 +796,7 @@ px - 200 + 250 0 From 51fa4e639e892b82ae70fd22a4f05a465f416650 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 31 Mar 2009 12:30:38 -0700 Subject: [PATCH 07/10] Fix #2186 (Remove eMail button does not work) --- src/calibre/gui2/dialogs/config.py | 8 +- src/calibre/gui2/lrf_renderer/document.py | 186 +++++++++++----------- src/calibre/www/apps/feedjack/views.py | 3 +- src/calibre/www/publish.sh | 2 +- upload.py | 7 + 5 files changed, 110 insertions(+), 96 deletions(-) diff --git a/src/calibre/gui2/dialogs/config.py b/src/calibre/gui2/dialogs/config.py index 91bc988a22..a2c77187b5 100644 --- a/src/calibre/gui2/dialogs/config.py +++ b/src/calibre/gui2/dialogs/config.py @@ -263,7 +263,7 @@ class EmailAccounts(QAbstractTableModel): def remove(self, index): if index.isValid(): - row = self.index.row() + row = index.row() account = self.account_order[row] self.accounts.pop(account) self.account_order = sorted(self.accounts.keys()) @@ -425,6 +425,8 @@ class ConfigDialog(QDialog, Ui_Dialog): self.email_view.resizeColumnsToContents() self.connect(self.test_email_button, SIGNAL('clicked(bool)'), self.test_email) + self.connect(self.email_remove, SIGNAL('clicked()'), + self.remove_email_account) def add_email_account(self, checked): index = self._email_accounts.add() @@ -432,6 +434,10 @@ class ConfigDialog(QDialog, Ui_Dialog): self.email_view.resizeColumnsToContents() self.email_view.edit(index) + def remove_email_account(self, *args): + idx = self.email_view.currentIndex() + self._email_accounts.remove(idx) + def create_gmail_relay(self, *args): self.relay_username.setText('@gmail.com') self.relay_password.setText('') diff --git a/src/calibre/gui2/lrf_renderer/document.py b/src/calibre/gui2/lrf_renderer/document.py index 76c94d23f1..d9874513d6 100644 --- a/src/calibre/gui2/lrf_renderer/document.py +++ b/src/calibre/gui2/lrf_renderer/document.py @@ -6,7 +6,7 @@ from PyQt4.QtCore import Qt, QByteArray, SIGNAL from PyQt4.QtGui import QGraphicsRectItem, QGraphicsScene, QPen, \ QBrush, QColor, QFontDatabase, \ QGraphicsItem, QGraphicsLineItem - + from calibre.gui2.lrf_renderer.text import TextBlock, FontLoader, COLOR, PixmapItem @@ -25,17 +25,17 @@ class Pen(QPen): class ContentObject(object): - + has_content = True - + def reset(self): self.has_content = True class RuledLine(QGraphicsLineItem, ContentObject): - + map = {'solid': Qt.SolidLine, 'dashed': Qt.DashLine, 'dotted': Qt.DotLine, 'double': Qt.DashDotLine} - + def __init__(self, rl): QGraphicsLineItem.__init__(self, 0, 0, rl.linelength, 0) ContentObject.__init__(self) @@ -43,7 +43,7 @@ class RuledLine(QGraphicsLineItem, ContentObject): class ImageBlock(PixmapItem, ContentObject): - + def __init__(self, obj): ContentObject.__init__(self) x0, y0, x1, y1 = obj.attrs['x0'], obj.attrs['y0'], obj.attrs['x1'], obj.attrs['y1'] @@ -51,26 +51,26 @@ class ImageBlock(PixmapItem, ContentObject): data, encoding = refstream.stream, refstream.encoding PixmapItem.__init__(self, data, encoding, x0, y0, x1, y1, xsize, ysize) self.block_id = obj.id - + def object_factory(container, obj, respect_max_y=False): if hasattr(obj, 'name'): if obj.name.endswith('TextBlock'): - + return TextBlock(obj, container.font_loader, respect_max_y, container.text_width, - container.logger, container.opts, container.ruby_tags, + container.logger, container.opts, container.ruby_tags, container.link_activated) elif obj.name.endswith('ImageBlock'): return ImageBlock(obj) elif isinstance(obj, _RuledLine): return RuledLine(obj) elif isinstance(obj, __Canvas): - return Canvas(container.font_loader, obj, container.logger, container.opts, - container.ruby_tags, container.link_activated) - return None + return Canvas(container.font_loader, obj, container.logger, container.opts, + container.ruby_tags, container.link_activated) + return None class _Canvas(QGraphicsRectItem): - + def __init__(self, font_loader, logger, opts, width=0, height=0, parent=None, x=0, y=0): QGraphicsRectItem.__init__(self, x, y, width, height, parent) self.font_loader, self.logger, self.opts = font_loader, logger, opts @@ -79,7 +79,7 @@ class _Canvas(QGraphicsRectItem): pen = QPen() pen.setStyle(Qt.NoPen) self.setPen(pen) - + def layout_block(self, block, x, y): if isinstance(block, TextBlock): self.layout_text_block(block, x, y) @@ -89,17 +89,17 @@ class _Canvas(QGraphicsRectItem): self.layout_image_block(block, x, y) elif isinstance(block, Canvas): self.layout_canvas(block, x, y) - + def layout_canvas(self, canvas, x, y): if canvas.max_y + y > self.max_y and y > 0: self.is_full = True - return + return canvas.setParentItem(self) canvas.setPos(x, y) canvas.has_content = False canvas.put_objects() self.current_y += canvas.max_y - + def layout_text_block(self, block, x, y): textwidth = block.bs.blockwidth - block.bs.sidemargin if block.max_y == 0 or not block.lines: # Empty block skipping @@ -128,15 +128,15 @@ class _Canvas(QGraphicsRectItem): line = block.peek() self.current_y = y self.is_full = not block_consumed - + def layout_ruled_line(self, rl, x, y): br = rl.boundingRect() rl.setParentItem(self) rl.setPos(x, y+1) self.current_y = y + br.height() + 1 self.is_full = y > self.max_y-5 - rl.has_content = False - + rl.has_content = False + def layout_image_block(self, ib, x, y): mw, mh = self.max_x - x, self.max_y - y if self.current_y + ib.height > self.max_y-y and self.current_y > 5: @@ -161,8 +161,8 @@ class _Canvas(QGraphicsRectItem): print print ib.block_id, ib.has_content, self.is_full print self.current_y, self.max_y, y, br.height() - print - + print + def search(self, phrase): matches = [] for child in self.children(): @@ -174,11 +174,11 @@ class _Canvas(QGraphicsRectItem): else: matches.append(res) return matches - - - + + + class Canvas(_Canvas, ContentObject): - + def __init__(self, font_loader, canvas, logger, opts, ruby_tags, link_activated, width=0, height=0): if hasattr(canvas, 'canvaswidth'): width, height = canvas.canvaswidth, canvas.canvasheight @@ -198,11 +198,11 @@ class Canvas(_Canvas, ContentObject): item = object_factory(self, obj, respect_max_y=True) if item: self.items.append((item, po.x1, po.y1)) - + def put_objects(self): for block, x, y in self.items: self.layout_block(block, x, y) - + def layout_block(self, block, x, y): block.reset() _Canvas.layout_block(self, block, x, y) @@ -212,17 +212,17 @@ class Header(Canvas): Canvas.__init__(self, font_loader, header, logger, opts, ruby_tags, link_activated, page_style.textwidth, page_style.headheight) if opts.visual_debug: - self.setPen(QPen(Qt.blue, 1, Qt.DashLine)) + self.setPen(QPen(Qt.blue, 1, Qt.DashLine)) class Footer(Canvas): def __init__(self, font_loader, footer, page_style, logger, opts, ruby_tags, link_activated): Canvas.__init__(self, font_loader, footer, logger, opts, ruby_tags, link_activated, page_style.textwidth, page_style.footheight) if opts.visual_debug: - self.setPen(QPen(Qt.blue, 1, Qt.DashLine)) + self.setPen(QPen(Qt.blue, 1, Qt.DashLine)) class Screen(_Canvas): - + def __init__(self, font_loader, chapter, odd, logger, opts, ruby_tags, link_activated): self.logger, self.opts = logger, opts page_style = chapter.style @@ -231,11 +231,11 @@ class Screen(_Canvas): self.content_x = 0 + sidemargin self.text_width = page_style.textwidth self.header_y = page_style.topmargin - + self.text_y = self.header_y + page_style.headheight + page_style.headsep self.text_height = page_style.textheight self.footer_y = self.text_y + self.text_height + (page_style.footspace - page_style.footheight) - + _Canvas.__init__(self, font_loader, logger, opts, width=width, height=self.footer_y+page_style.footheight) if opts.visual_debug: self.setPen(QPen(Qt.red, 1, Qt.SolidLine)) @@ -256,57 +256,57 @@ class Screen(_Canvas): if footer: footer = Footer(font_loader, footer, page_style, logger, opts, ruby_tags, link_activated) self.layout_canvas(footer, self.content_x, self.header_y) - + self.page = None - + def set_page(self, page): if self.page is not None and self.page.scene(): - self.scene().removeItem(self.page) + self.scene().removeItem(self.page) self.page = page self.page.setPos(self.content_x, self.text_y) self.scene().addItem(self.page) - + def remove(self): if self.scene(): if self.page is not None and self.page.scene(): self.scene().removeItem(self.page) self.scene().removeItem(self) - - + + class Page(_Canvas): - + def __init__(self, font_loader, logger, opts, width, height): _Canvas.__init__(self, font_loader, logger, opts, width, height) if opts.visual_debug: self.setPen(QPen(Qt.cyan, 1, Qt.DashLine)) - + def id(self): for child in self.children(): if hasattr(child, 'block_id'): return child.block_id - + def add_block(self, block): self.layout_block(block, 0, self.current_y) - - - + + + class Chapter(object): - + num_of_pages = property(fget=lambda self: len(self.pages)) - + def __init__(self, oddscreen, evenscreen, pages, object_to_page_map): self.oddscreen, self.evenscreen, self.pages, self.object_to_page_map = \ oddscreen, evenscreen, pages, object_to_page_map - + def page_of_object(self, id): return self.object_to_page_map[id] - + def page(self, num): return self.pages[num-1] - + def screen(self, odd): return self.oddscreen if odd else self.evenscreen - + def search(self, phrase): pages = [] for i in range(len(self.pages)): @@ -314,36 +314,36 @@ class Chapter(object): if matches: pages.append([i, matches]) return pages - + class History(collections.deque): - + def __init__(self): collections.deque.__init__(self) self.pos = 0 - + def back(self): if self.pos - 1 < 0: return None self.pos -= 1 return self[self.pos] - + def forward(self): if self.pos + 1 >= len(self): return None self.pos += 1 return self[self.pos] - + def add(self, item): while len(self) > self.pos+1: self.pop() self.append(item) self.pos += 1 - - + + class Document(QGraphicsScene): - + num_of_pages = property(fget=lambda self: sum(self.chapter_layout)) - + def __init__(self, logger, opts): QGraphicsScene.__init__(self) self.logger, self.opts = logger, opts @@ -358,23 +358,23 @@ class Document(QGraphicsScene): self.last_search = iter([]) if not opts.white_background: self.setBackgroundBrush(QBrush(QColor(0xee, 0xee, 0xee))) - + def page_of(self, oid): for chapter in self.chapters: if oid in chapter.object_to_page_map: return chapter.object_to_page_map[oid] - + def get_page_num(self, chapterid, objid): cnum = self.chapter_map[chapterid] page = self.chapters[cnum].object_to_page_map[objid] return sum(self.chapter_layout[:cnum])+page - + def add_to_history(self): page = self.chapter_page(self.current_page)[1] page_id = page.id() if page_id is not None: self.history.add(page_id) - + def link_activated(self, objid, on_creation=None): if on_creation is None: cid, oid = self.link_map[objid] @@ -385,30 +385,30 @@ class Document(QGraphicsScene): else: jb = self.objects[objid] self.link_map[objid] = (jb.refpage, jb.refobj) - - + + def back(self): oid = self.history.back() if oid is not None: page = self.page_of(oid) self.show_page(page) - + def forward(self): oid = self.history.forward() if oid is not None: page = self.page_of(oid) self.show_page(page) - - + + def load_fonts(self, lrf, load_substitutions=True): font_map = {} - + for font in lrf.font_map: fdata = QByteArray(lrf.font_map[font].data) id = QFontDatabase.addApplicationFontFromData(fdata) if id != -1: font_map[font] = [str(i) for i in QFontDatabase.applicationFontFamilies(id)][0] - + if load_substitutions: from calibre.ebooks.lrf.fonts.liberation import LiberationMono_BoldItalic QFontDatabase.addApplicationFontFromData(QByteArray(LiberationMono_BoldItalic.font_data)) @@ -434,10 +434,10 @@ class Document(QGraphicsScene): QFontDatabase.addApplicationFontFromData(QByteArray(LiberationSerif_BoldItalic.font_data)) from calibre.ebooks.lrf.fonts.liberation import LiberationSans_Regular QFontDatabase.addApplicationFontFromData(QByteArray(LiberationSans_Regular.font_data)) - + self.font_loader = FontLoader(font_map, self.dpi) - - + + def render_chapter(self, chapter, lrf): oddscreen, evenscreen = Screen(self.font_loader, chapter, True, self.logger, self.opts, self.ruby_tags, self.link_activated), \ Screen(self.font_loader, chapter, False, self.logger, self.opts, self.ruby_tags, self.link_activated) @@ -459,36 +459,36 @@ class Document(QGraphicsScene): if current_page: pages.append(current_page) self.chapters.append(Chapter(oddscreen, evenscreen, pages, object_to_page_map)) - self.chapter_map[chapter.id] = len(self.chapters)-1 - - + self.chapter_map[chapter.id] = len(self.chapters)-1 + + def render(self, lrf, load_substitutions=True): self.dpi = lrf.device_info.dpi/10. self.ruby_tags = dict(**lrf.ruby_tags) self.load_fonts(lrf, load_substitutions) self.objects = lrf.objects - + num_chaps = 0 for pt in lrf.page_trees: for chapter in pt: num_chaps += 1 self.emit(SIGNAL('chapter_rendered(int)'), num_chaps) - + for pt in lrf.page_trees: for chapter in pt: self.render_chapter(chapter, lrf) - + self.emit(SIGNAL('chapter_rendered(int)'), -1) self.chapter_layout = [i.num_of_pages for i in self.chapters] self.objects = None - + def chapter_page(self, num): for chapter in self.chapters: if num <= chapter.num_of_pages: break num -= chapter.num_of_pages return chapter, chapter.page(num) - + def show_page(self, num): if num < 1 or num > self.num_of_pages or num == self.current_page: return @@ -496,33 +496,33 @@ class Document(QGraphicsScene): self.current_page = num chapter, page = self.chapter_page(num) screen = chapter.screen(odd) - + if self.current_screen is not None and self.current_screen is not screen: self.current_screen.remove() self.current_screen = screen if self.current_screen.scene() is None: self.addItem(self.current_screen) - + self.current_screen.set_page(page) self.emit(SIGNAL('page_changed(PyQt_PyObject)'), self.current_page) - - + + def next(self): self.next_by(1) - + def previous(self): self.previous_by(1) - + def next_by(self, num): self.show_page(self.current_page + num) - + def previous_by(self, num): self.show_page(self.current_page - num) - + def show_page_at_percent(self, p): num = self.num_of_pages*(p/100.) self.show_page(num) - + def search(self, phrase): if not phrase: return @@ -534,7 +534,7 @@ class Document(QGraphicsScene): matches += cmatches self.last_search = itertools.cycle(matches) self.next_match() - + def next_match(self): page_num = self.last_search.next()[0] if self.current_page == page_num: @@ -542,4 +542,4 @@ class Document(QGraphicsScene): else: self.add_to_history() self.show_page(page_num) - + diff --git a/src/calibre/www/apps/feedjack/views.py b/src/calibre/www/apps/feedjack/views.py index c1f31eb908..27b5dc0783 100644 --- a/src/calibre/www/apps/feedjack/views.py +++ b/src/calibre/www/apps/feedjack/views.py @@ -26,7 +26,8 @@ def initview(request): 5. The feeds for the site (ids) """ - site_id, cachekey = fjlib.getcurrentsite(request.META['HTTP_HOST'], \ + site_id, cachekey = fjlib.getcurrentsite(request.META.get('HTTP_HOST', + 'planet.calibre-ebook.com'), \ request.META.get('REQUEST_URI', request.META.get('PATH_INFO', '/')), \ request.META['QUERY_STRING']) response = fjcache.cache_get(site_id, cachekey) diff --git a/src/calibre/www/publish.sh b/src/calibre/www/publish.sh index c78f0a1d89..8882a8b7ea 100755 --- a/src/calibre/www/publish.sh +++ b/src/calibre/www/publish.sh @@ -1,4 +1,4 @@ #!/bin/sh -ssh divok "cd /usr/local/calibre && bzr pull" +ssh divok "cd /usr/local/calibre && bzr up" ssh divok /etc/init.d/apache2 graceful diff --git a/upload.py b/upload.py index 814d124523..b2fc81c8b6 100644 --- a/upload.py +++ b/upload.py @@ -667,9 +667,16 @@ class stage3(OptionlessCommand): def misc(cls): check_call('ssh divok rm -f %s/calibre-\*.tar.gz'%DOWNLOADS, shell=True) check_call('scp dist/calibre-*.tar.gz divok:%s/'%DOWNLOADS, shell=True) + check_call('gpg --armor --detach-sign dist/calibre-*.tar.gz', + shell=True) + check_call('scp dist/calibre-*.tar.gz.asc divok:%s/signatures/'%DOWNLOADS, + shell=True) check_call('''rm -rf dist/* build/*''', shell=True) check_call('ssh divok bzr update /var/www/calibre.kovidgoyal.net/calibre/', shell=True) + check_call('ssh divok bzr update /usr/local/calibre', + shell=True) + def run(self): OptionlessCommand.run(self) From 957a5546f3483e75b064ad33c51cd986fc10a072 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 31 Mar 2009 13:04:57 -0700 Subject: [PATCH 08/10] version 0.5.4 --- src/calibre/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/constants.py b/src/calibre/constants.py index 817452d558..9d9fc7310a 100644 --- a/src/calibre/constants.py +++ b/src/calibre/constants.py @@ -2,7 +2,7 @@ __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' __docformat__ = 'restructuredtext en' __appname__ = 'calibre' -__version__ = '0.5.3' +__version__ = '0.5.4' __author__ = "Kovid Goyal " ''' Various run time constants. From 8c164652a0e88605f3d5c22e300732df8426ccb8 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 31 Mar 2009 13:07:20 -0700 Subject: [PATCH 09/10] IGN:Tag release From a45cc97f903fc31678214c2a17f09a805df428e3 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 31 Mar 2009 18:43:18 -0700 Subject: [PATCH 10/10] IGN:... --- src/calibre/www/templates/feedjack/default/post_list.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/www/templates/feedjack/default/post_list.html b/src/calibre/www/templates/feedjack/default/post_list.html index 25ecb152b0..8aaa427a33 100644 --- a/src/calibre/www/templates/feedjack/default/post_list.html +++ b/src/calibre/www/templates/feedjack/default/post_list.html @@ -52,7 +52,7 @@
- {{ item.feed.title|safe }} + {{ item.feed.name|safe }}