mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Cleanup ebook viewer code
This commit is contained in:
parent
f5ad1f38ba
commit
6d0b2ec553
@ -1,23 +1,23 @@
|
||||
from __future__ import with_statement
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
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('<p>'+_(
|
||||
'Go to a reference. To get reference numbers, use the <i>reference '
|
||||
'mode</i>, 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
|
||||
|
39
src/calibre/gui2/viewer/toc.py
Normal file
39
src/calibre/gui2/viewer/toc.py
Normal file
@ -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 <kovid@kovidgoyal.net>'
|
||||
__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')))
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user