From 6d0b2ec5536e02124bad8cbc0ca47116c011cae9 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 6 May 2012 23:10:25 +0530 Subject: [PATCH] Cleanup ebook viewer code --- src/calibre/gui2/viewer/main.py | 159 +++++++++++++------------------- src/calibre/gui2/viewer/toc.py | 39 ++++++++ 2 files changed, 105 insertions(+), 93 deletions(-) create mode 100644 src/calibre/gui2/viewer/toc.py diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py index c22603cee5..2e4a2f8924 100644 --- a/src/calibre/gui2/viewer/main.py +++ b/src/calibre/gui2/viewer/main.py @@ -1,23 +1,23 @@ -from __future__ import with_statement __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal ' -import traceback, os, sys, functools, collections, re + +import traceback, os, sys, functools, collections, textwrap from functools import partial from threading import Thread -from PyQt4.Qt import (QApplication, Qt, QIcon, QTimer, SIGNAL, QByteArray, - QSize, QDoubleSpinBox, QLabel, QTextBrowser, QPropertyAnimation, - QPainter, QBrush, QColor, QStandardItemModel, QPalette, QStandardItem, - QUrl, QRegExpValidator, QRegExp, QLineEdit, QToolButton, QMenu, - QInputDialog, QAction, QKeySequence) +from PyQt4.Qt import (QApplication, Qt, QIcon, QTimer, QByteArray, QSize, + QDoubleSpinBox, QLabel, QTextBrowser, QPropertyAnimation, QPainter, + QBrush, QColor, pyqtSignal, QUrl, QRegExpValidator, QRegExp, QLineEdit, + QToolButton, QMenu, QInputDialog, QAction, QKeySequence, QModelIndex) from calibre.gui2.viewer.main_ui import Ui_EbookViewer from calibre.gui2.viewer.printing import Printing from calibre.gui2.viewer.bookmarkmanager import BookmarkManager +from calibre.gui2.viewer.toc import TOC from calibre.gui2.widgets import ProgressIndicator from calibre.gui2.main_window import MainWindow -from calibre.gui2 import Application, ORG_NAME, APP_UID, choose_files, \ - info_dialog, error_dialog, open_url, available_height +from calibre.gui2 import (Application, ORG_NAME, APP_UID, choose_files, + info_dialog, error_dialog, open_url, available_height) from calibre.ebooks.oeb.iterator import EbookIterator from calibre.ebooks import DRMError from calibre.constants import islinux, isbsd, isosx, filesystem_encoding @@ -31,31 +31,6 @@ from calibre.ptempfile import reset_base_dir vprefs = JSONConfig('viewer') -class TOCItem(QStandardItem): - - def __init__(self, toc): - text = toc.text - if text: - text = re.sub(r'\s', ' ', text) - QStandardItem.__init__(self, text if text else '') - self.abspath = toc.abspath - self.fragment = toc.fragment - 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): @@ -142,31 +117,22 @@ class DoubleSpinBox(QDoubleSpinBox): ' [{0:.0%}]'.format(float(val)/self.maximum())) self.blockSignals(False) -class HelpfulLineEdit(QLineEdit): +class Reference(QLineEdit): - HELP_TEXT = _('Go to...') + goto = pyqtSignal(object) def __init__(self, *args): QLineEdit.__init__(self, *args) - self.default_palette = QApplication.palette(self) - self.gray = QPalette(self.default_palette) - self.gray.setBrush(QPalette.Text, QBrush(QColor('gray'))) - self.connect(self, SIGNAL('editingFinished()'), - lambda : self.emit(SIGNAL('goto(PyQt_PyObject)'), unicode(self.text()))) - self.clear_to_help_mode() + self.setValidator(QRegExpValidator(QRegExp(r'\d+\.\d+'), self)) + self.setToolTip(textwrap.fill('

'+_( + 'Go to a reference. To get reference numbers, use the reference ' + 'mode, by clicking the reference mode button in the toolbar.'))) + if hasattr(self, 'setPlaceholderText'): + self.setPlaceholderText(_('Go to...')) + self.editingFinished.connect(self.editing_finished) - 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) + def editing_finished(self): + self.goto.emit(unicode(self.text())) class RecentAction(QAction): @@ -207,9 +173,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.pos.setMinimum(1.) self.pos.setMinimumWidth(150) self.tool_bar2.insertWidget(self.action_find_next, self.pos) - self.reference = HelpfulLineEdit() - self.reference.setValidator(QRegExpValidator(QRegExp(r'\d+\.\d+'), self.reference)) - self.reference.setToolTip(_('Go to a reference. To get reference numbers, use the reference mode.')) + self.reference = Reference() self.tool_bar2.insertSeparator(self.action_find_next) self.tool_bar2.insertWidget(self.action_find_next, self.reference) self.tool_bar2.insertSeparator(self.action_find_next) @@ -233,8 +197,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): if isosx: qs += [Qt.CTRL+Qt.Key_W] self.action_quit.setShortcuts(qs) - self.connect(self.action_quit, SIGNAL('triggered(bool)'), - lambda x:QApplication.instance().quit()) + self.action_quit.triggered.connect(self.quit) self.action_focus_search = QAction(self) self.addAction(self.action_focus_search) self.action_focus_search.setShortcuts([Qt.Key_Slash, @@ -247,42 +210,34 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.action_table_of_contents.setCheckable(True) self.toc.setMinimumWidth(80) self.action_reference_mode.setCheckable(True) - 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.action_reference_mode.triggered[bool].connect(self.view.reference_mode) + self.action_metadata.triggered[bool].connect(self.metadata.setVisible) self.action_table_of_contents.toggled[bool].connect(self.set_toc_visible) - self.connect(self.action_copy, SIGNAL('triggered(bool)'), self.copy) + self.action_copy.triggered[bool].connect(self.copy) self.action_font_size_larger.triggered.connect(self.font_size_larger) self.action_font_size_smaller.triggered.connect(self.font_size_smaller) - self.connect(self.action_open_ebook, SIGNAL('triggered(bool)'), - self.open_ebook) - self.connect(self.action_next_page, SIGNAL('triggered(bool)'), - 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)'), - lambda x:self.find(unicode(self.search.text()), repeat=True)) - self.connect(self.action_find_previous, SIGNAL('triggered(bool)'), - lambda x:self.find(unicode(self.search.text()), - repeat=True, backwards=True)) - - self.connect(self.action_full_screen, SIGNAL('triggered(bool)'), - self.toggle_fullscreen) + self.action_open_ebook.triggered[bool].connect(self.open_ebook) + self.action_next_page.triggered.connect(self.view.next_page) + self.action_previous_page.triggered.connect(self.view.previous_page) + self.action_find_next.triggered.connect(self.find_next) + self.action_find_previous.triggered.connect(self.find_previous) + self.action_full_screen.triggered[bool].connect(self.toggle_fullscreen) self.action_full_screen.setShortcuts([Qt.Key_F11, Qt.CTRL+Qt.SHIFT+Qt.Key_F]) self.action_full_screen.setToolTip(_('Toggle full screen (%s)') % _(' or ').join([unicode(x.toString(x.NativeText)) for x in self.action_full_screen.shortcuts()])) - self.connect(self.action_back, SIGNAL('triggered(bool)'), self.back) - self.connect(self.action_bookmark, SIGNAL('triggered(bool)'), self.bookmark) - 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.action_back.triggered[bool].connect(self.back) + self.action_forward.triggered[bool].connect(self.forward) + self.action_bookmark.triggered[bool].connect(self.bookmark) + self.action_preferences.triggered.connect(lambda : + self.view.config(self)) self.pos.editingFinished.connect(self.goto_page_num) - self.connect(self.vertical_scrollbar, SIGNAL('valueChanged(int)'), - lambda x: self.goto_page(x/100.)) + self.vertical_scrollbar.valueChanged[int].connect(lambda + x:self.goto_page(x/100.)) self.search.search.connect(self.find) self.search.focus_to_library.connect(lambda: self.view.setFocus(Qt.OtherFocusReason)) - self.connect(self.toc, SIGNAL('clicked(QModelIndex)'), self.toc_clicked) - self.connect(self.reference, SIGNAL('goto(PyQt_PyObject)'), self.goto) + self.toc.clicked[QModelIndex].connect(self.toc_clicked) + self.reference.goto.connect(self.goto) self.bookmarks_menu = QMenu() self.action_bookmark.setMenu(self.bookmarks_menu) @@ -335,8 +290,8 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.print_menu.addAction(QIcon(I('print-preview.png')), _('Print Preview')) self.action_print.setMenu(self.print_menu) self.tool_bar.widgetForAction(self.action_print).setPopupMode(QToolButton.MenuButtonPopup) - self.connect(self.action_print, SIGNAL("triggered(bool)"), partial(self.print_book, preview=False)) - self.connect(self.print_menu.actions()[0], SIGNAL("triggered(bool)"), partial(self.print_book, preview=True)) + self.action_print.triggered.connect(self.print_book) + self.print_menu.actions()[0].triggered.connect(self.print_preview) ca = self.view.copy_action ca.setShortcut(QKeySequence.Copy) self.addAction(ca) @@ -381,13 +336,22 @@ class EbookViewer(MainWindow, Ui_EbookViewer): m.addAction(RecentAction(path, m)) count += 1 - def closeEvent(self, e): + def shutdown(self): if self.isFullScreen(): self.action_full_screen.trigger() - e.ignore() - return + return False self.save_state() - return MainWindow.closeEvent(self, e) + return True + + def quit(self): + if self.shutdown(): + QApplication.instance().quit() + + def closeEvent(self, e): + if self.shutdown(): + return MainWindow.closeEvent(self, e) + else: + e.ignore() def toggle_toolbars(self): for x in ('tool_bar', 'tool_bar2'): @@ -440,8 +404,11 @@ class EbookViewer(MainWindow, Ui_EbookViewer): c = config().parse() return c.remember_current_page - def print_book(self, preview): - Printing(self.iterator.spine, preview) + def print_book(self): + Printing(self.iterator.spine, False) + + def print_preview(self): + Printing(self.iterator.spine, True) def toggle_fullscreen(self, x): if self.isFullScreen(): @@ -629,6 +596,12 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.pending_search_dir = 'backwards' if backwards else 'forwards' self.load_path(self.iterator.spine[index]) + def find_next(self): + self.find(unicode(self.search.text()), repeat=True) + + def find_previous(self): + self.find(unicode(self.search.text()), repeat=True, backwards=True) + def do_search(self, text, backwards): self.pending_search = None self.pending_search_dir = None diff --git a/src/calibre/gui2/viewer/toc.py b/src/calibre/gui2/viewer/toc.py new file mode 100644 index 0000000000..dd14eb604a --- /dev/null +++ b/src/calibre/gui2/viewer/toc.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import (unicode_literals, division, absolute_import, + print_function) + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import re + +from PyQt4.Qt import QStandardItem, QStandardItemModel, Qt + +class TOCItem(QStandardItem): + + def __init__(self, toc): + text = toc.text + if text: + text = re.sub(r'\s', ' ', text) + QStandardItem.__init__(self, text if text else '') + self.abspath = toc.abspath + self.fragment = toc.fragment + 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'))) + +