diff --git a/src/calibre/gui2/viewer/config.ui b/src/calibre/gui2/viewer/config.ui index 3158241f28..f876b87fc3 100644 --- a/src/calibre/gui2/viewer/config.ui +++ b/src/calibre/gui2/viewer/config.ui @@ -255,7 +255,10 @@ - + + + Set the maximum width that the book's text and pictures will take when in fullscreen mode. This allows you to read the book text without it becoming too wide. + px @@ -270,10 +273,10 @@ - Maximum &view width: + Maximum text width in &fullscreen: - max_view_width + max_fs_width @@ -350,7 +353,7 @@ serif_family sans_family mono_family - max_view_width + max_fs_width opt_remember_window_size buttonBox diff --git a/src/calibre/gui2/viewer/documentview.py b/src/calibre/gui2/viewer/documentview.py index 2f520c1912..7999458004 100644 --- a/src/calibre/gui2/viewer/documentview.py +++ b/src/calibre/gui2/viewer/documentview.py @@ -12,7 +12,7 @@ from PyQt4.Qt import (QSize, QSizePolicy, QUrl, SIGNAL, Qt, QTimer, QPainter, QPalette, QBrush, QFontDatabase, QDialog, QColor, QPoint, QImage, QRegion, QVariant, QIcon, QFont, pyqtSignature, QAction, QByteArray, QMenu, - pyqtSignal, QSwipeGesture) + pyqtSignal, QSwipeGesture, QApplication) from PyQt4.QtWebKit import QWebPage, QWebView, QWebSettings from calibre.utils.config import Config, StringConfig @@ -46,8 +46,10 @@ def config(defaults=None): help=_('Remember last used window size')) c.add_opt('user_css', default='', help=_('Set the user CSS stylesheet. This can be used to customize the look of all books.')) - c.add_opt('max_view_width', default=6000, - help=_('Maximum width of the viewer window, in pixels.')) + c.add_opt('max_fs_width', default=800, + help=_("Set the maximum width that the book's text and pictures will take" + " when in fullscreen mode. This allows you to read the book text" + " without it becoming too wide.")) c.add_opt('fit_images', default=True, help=_('Resize images larger than the viewer window to fit inside it')) c.add_opt('hyphenate', default=False, help=_('Hyphenate text')) @@ -101,7 +103,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.')) - self.max_view_width.setValue(opts.max_view_width) + self.max_fs_width.setValue(opts.max_fs_width) with zipfile.ZipFile(P('viewer/hyphenate/patterns.zip', allow_user_override=False), 'r') as zf: pats = [x.split('.')[0].replace('-', '_') for x in zf.namelist()] @@ -144,7 +146,7 @@ class ConfigDialog(QDialog, Ui_Dialog): c.set('user_css', unicode(self.css.toPlainText())) c.set('remember_window_size', self.opt_remember_window_size.isChecked()) c.set('fit_images', self.opt_fit_images.isChecked()) - c.set('max_view_width', int(self.max_view_width.value())) + c.set('max_fs_width', int(self.max_fs_width.value())) c.set('hyphenate', self.hyphenate.isChecked()) c.set('remember_current_page', self.opt_remember_current_page.isChecked()) c.set('wheel_flips_pages', self.opt_wheel_flips_pages.isChecked()) @@ -192,6 +194,8 @@ class Document(QWebPage): # {{{ self.loaded_javascript = False self.js_loader = JavaScriptLoader( dynamic_coffeescript=self.debug_javascript) + self.initial_left_margin = self.initial_right_margin = u'' + self.in_fullscreen_mode = False self.setLinkDelegationPolicy(self.DelegateAllLinks) self.scroll_marks = [] @@ -239,6 +243,9 @@ class Document(QWebPage): # {{{ self.enable_page_flip = self.page_flip_duration > 0.1 self.font_magnification_step = opts.font_magnification_step self.wheel_flips_pages = opts.wheel_flips_pages + screen_width = QApplication.desktop().screenGeometry().width() + # Leave some space for the scrollbar and some border + self.max_fs_width = min(opts.max_fs_width, screen_width-50) def fit_images(self): if self.do_fit_images: @@ -274,6 +281,30 @@ class Document(QWebPage): # {{{ self.set_bottom_padding(0) self.fit_images() self.init_hyphenate() + self.initial_left_margin = unicode(self.javascript( + 'document.body.style.marginLeft').toString()) + self.initial_right_margin = unicode(self.javascript( + 'document.body.style.marginRight').toString()) + if self.in_fullscreen_mode: + self.switch_to_fullscreen_mode() + + def switch_to_fullscreen_mode(self): + self.in_fullscreen_mode = True + self.javascript(''' + var s = document.body.style; + s.maxWidth = "%dpx"; + s.marginLeft = "auto"; + s.marginRight = "auto"; + '''%self.max_fs_width) + + def switch_to_window_mode(self): + self.in_fullscreen_mode = False + self.javascript(''' + var s = document.body.style; + s.maxWidth = "none"; + s.marginLeft = "%s"; + s.marginRight = "%s"; + '''%(self.initial_left_margin, self.initial_right_margin)) @pyqtSignature("QString") def debug(self, msg): @@ -581,8 +612,8 @@ class DocumentView(QWebView): # {{{ def config(self, parent=None): self.document.do_config(parent) - if self.manager is not None: - self.manager.set_max_width() + if self.document.in_fullscreen_mode: + self.document.switch_to_fullscreen_mode() self.setFocus(Qt.OtherFocusReason) def bookmark(self): @@ -602,6 +633,9 @@ class DocumentView(QWebView): # {{{ menu.insertAction(list(menu.actions())[0], self.search_action) menu.addSeparator() menu.addAction(self.goto_location_action) + if self.document.in_fullscreen_mode and self.manager is not None: + menu.addSeparator() + menu.addAction(self.manager.toggle_toolbar_action) menu.exec_(ev.globalPos()) def lookup(self, *args): diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py index a83c5d12c0..c1cb89aeb6 100644 --- a/src/calibre/gui2/viewer/main.py +++ b/src/calibre/gui2/viewer/main.py @@ -6,10 +6,10 @@ from functools import partial from threading import Thread from PyQt4.Qt import (QApplication, Qt, QIcon, QTimer, SIGNAL, QByteArray, - QDoubleSpinBox, QLabel, QTextBrowser, - QPainter, QBrush, QColor, QStandardItemModel, QPalette, - QStandardItem, QUrl, QRegExpValidator, QRegExp, QLineEdit, - QToolButton, QMenu, QInputDialog, QAction, QKeySequence) + QSize, QDoubleSpinBox, QLabel, QTextBrowser, QPropertyAnimation, + QPainter, QBrush, QColor, QStandardItemModel, QPalette, QStandardItem, + QUrl, QRegExpValidator, QRegExp, QLineEdit, QToolButton, QMenu, + QInputDialog, QAction, QKeySequence) from calibre.gui2.viewer.main_ui import Ui_EbookViewer from calibre.gui2.viewer.printing import Printing @@ -55,8 +55,6 @@ class TOC(QStandardItemModel): self.appendRow(TOCItem(t)) self.setHorizontalHeaderItem(0, QStandardItem(_('Table of Contents'))) - - class Worker(Thread): def run(self): @@ -292,6 +290,37 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.tool_bar2.setContextMenuPolicy(Qt.PreventContextMenu) self.tool_bar.widgetForAction(self.action_bookmark).setPopupMode(QToolButton.MenuButtonPopup) self.action_full_screen.setCheckable(True) + self.full_screen_label = QLabel(''' +
+

%s

+

%s

+

%s

+
+ '''%(_('Full screen mode'), + _('Right click to show controls'), + _('Press Esc to quit')), + self) + self.full_screen_label.setVisible(False) + self.full_screen_label.setStyleSheet(''' + QLabel { + text-align: center; + background-color: white; + color: black; + border-width: 1px; + border-style: solid; + border-radius: 20px; + } + ''') + self.toggle_toolbar_action = QAction(_('Show/hide controls'), self) + self.toggle_toolbar_action.triggered.connect(self.toggle_toolbars) + self.addAction(self.toggle_toolbar_action) + self.full_screen_label_anim = QPropertyAnimation( + self.full_screen_label, 'size') + self.esc_full_screen_action = a = QAction(self) + self.addAction(a) + a.setShortcut(Qt.Key_Escape) + a.setEnabled(False) + a.triggered.connect(self.action_full_screen.trigger) self.print_menu = QMenu() self.print_menu.addAction(QIcon(I('print-preview.png')), _('Print Preview')) @@ -299,7 +328,6 @@ class EbookViewer(MainWindow, Ui_EbookViewer): 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.set_max_width() ca = self.view.copy_action ca.setShortcut(QKeySequence.Copy) self.addAction(ca) @@ -313,6 +341,13 @@ class EbookViewer(MainWindow, Ui_EbookViewer): w = self.tool_bar.widgetForAction(self.action_open_ebook) w.setPopupMode(QToolButton.MenuButtonPopup) + for x in ('tool_bar', 'tool_bar2'): + x = getattr(self, x) + for action in x.actions(): + # So that the keyboard shortcuts for these actions will + # continue to function even when the toolbars are hidden + self.addAction(action) + self.restore_state() def set_toc_visible(self, yes): @@ -339,12 +374,17 @@ class EbookViewer(MainWindow, Ui_EbookViewer): def closeEvent(self, e): if self.isFullScreen(): - self.showNormal() + self.action_full_screen.trigger() e.ignore() return self.save_state() return MainWindow.closeEvent(self, e) + def toggle_toolbars(self): + for x in ('tool_bar', 'tool_bar2'): + x = getattr(self, x) + x.setVisible(not x.isVisible()) + def save_state(self): state = bytearray(self.saveState(self.STATE_VERSION)) vprefs['viewer_toolbar_state'] = state @@ -386,11 +426,6 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self._lookup = None self.dictionary_view.setHtml(html) - def set_max_width(self): - from calibre.gui2.viewer.documentview import config - c = config().parse() - self.frame.setMaximumWidth(c.max_view_width) - def get_remember_current_page_opt(self): from calibre.gui2.viewer.documentview import config c = config().parse() @@ -405,6 +440,46 @@ class EbookViewer(MainWindow, Ui_EbookViewer): else: self.showFullScreen() + def showFullScreen(self): + self.tool_bar.setVisible(False) + self.tool_bar2.setVisible(False) + self._original_frame_margins = ( + self.centralwidget.layout().contentsMargins(), + self.frame.layout().contentsMargins()) + self.frame.layout().setContentsMargins(0, 0, 0, 0) + self.centralwidget.layout().setContentsMargins(0, 0, 0, 0) + + super(EbookViewer, self).showFullScreen() + QTimer.singleShot(10, self.show_full_screen_label) + + def show_full_screen_label(self): + f = self.full_screen_label + self.esc_full_screen_action.setEnabled(True) + f.setVisible(True) + height = 200 + width = int(0.7*self.view.width()) + f.resize(width, height) + f.move((self.view.width() - width)//2, (self.view.height()-height)//2) + a = self.full_screen_label_anim + a.setDuration(500) + a.setStartValue(QSize(width, 0)) + a.setEndValue(QSize(width, height)) + a.start() + QTimer.singleShot(2750, self.full_screen_label.hide) + self.view.document.switch_to_fullscreen_mode() + + def showNormal(self): + self.esc_full_screen_action.setEnabled(False) + self.tool_bar.setVisible(True) + self.tool_bar2.setVisible(True) + self.full_screen_label.setVisible(False) + if hasattr(self, '_original_frame_margins'): + om = self._original_frame_margins + self.centralwidget.layout().setContentsMargins(om[0]) + self.frame.layout().setContentsMargins(om[1]) + super(EbookViewer, self).showNormal() + self.view.document.switch_to_window_mode() + def goto(self, ref): if ref: tokens = ref.split('.') diff --git a/src/calibre/gui2/viewer/main.ui b/src/calibre/gui2/viewer/main.ui index 3137ad2e07..659a534fa8 100644 --- a/src/calibre/gui2/viewer/main.ui +++ b/src/calibre/gui2/viewer/main.ui @@ -284,6 +284,9 @@ Toggle full screen + + Toggle full screen (F11) +