Source code for qpageview.sidebarview

# -*- coding: utf-8 -*-
#
# This file is part of the qpageview package.
#
# Copyright (c) 2019 - 2019 by Wilbert Berendsen
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
# See http://www.gnu.org/licenses/ for more information.

"""
SidebarView, a special View with miniatures to use as a sidebar for a View.

Automatically displays all pages in a view in small size, and makes it easier
to browse large documents.

"""

from PyQt5.QtCore import QEvent, QMargins, QRect, Qt
from PyQt5.QtGui import QPainter

from . import constants
from . import layout
from . import selector
from . import view
from . import util



[docs]class SidebarView(selector.SelectorViewMixin, util.LongMousePressMixin, view.View): """A special View with miniatures to use as a sidebar for a View. Automatically displays all pages in a view in small size, and makes it easier to browse large documents. Use setView() to connect a View, and it automatically shows the pages, also when the view is changed. """ MAX_ZOOM = 1.0 pagingOnScrollEnabled = False wheelZoomingEnabled = False firstPageNumber = 1 scrollupdatespersec = 100 autoOrientationEnabled = True def __init__(self, parent=None, **kwds): super().__init__(parent, **kwds) self._view = None self.setOrientation(constants.Vertical) self.pageLayout().spacing = 1 self.pageLayout().setMargins(QMargins(0, 0, 0, 0)) self.pageLayout().setPageMargins(QMargins(4, 4, 4, 20)) self.setLayoutFontHeight() self.currentPageNumberChanged.connect(self.viewport().update)
[docs] def setOrientation(self, orientation): """Reimplemented to also set the corresponding view mode.""" super().setOrientation(orientation) if orientation == constants.Vertical: self.setViewMode(constants.FitWidth) else: self.setViewMode(constants.FitHeight)
[docs] def setLayoutFontHeight(self): """Reads the current font height and reserves enough space in the layout.""" self.pageLayout().pageMargins().setBottom(self.fontMetrics().height()) self.updatePageLayout()
[docs] def setView(self, view): """Connects to a View, or disconnects the current view if view is None.""" if view is not self._view: if self._view: self.currentPageNumberChanged.disconnect(self._view.setCurrentPageNumber) self._view.currentPageNumberChanged.disconnect(self.slotCurrentPageNumberChanged) self._view.pageLayoutUpdated.disconnect(self.slotLayoutUpdated) self.clear() self._view = view if view: self.slotLayoutUpdated() self.setCurrentPageNumber(view.currentPageNumber()) self.currentPageNumberChanged.connect(view.setCurrentPageNumber) view.currentPageNumberChanged.connect(self.slotCurrentPageNumberChanged) view.pageLayoutUpdated.connect(self.slotLayoutUpdated)
[docs] def slotLayoutUpdated(self): """Called when the layout of the connected view is updated.""" self.pageLayout()[:] = (p.copy(self) for p in self._view.pageLayout()) self.pageLayout().rotation = self._view.pageLayout().rotation self.updatePageLayout()
[docs] def slotCurrentPageNumberChanged(self, num): """Called when the page number in the connected view changes. Does not scroll but updates the current page mark in our View. """ self._currentPageNumber = num self.viewport().update()
[docs] def paintEvent(self, ev): """Reimplemented to print page numbers and a selection box.""" painter = QPainter(self.viewport()) layout = self.pageLayout() for p, rect in self.pagesToPaint(ev.rect(), painter): ## draw selection background on current page if p is self.currentPage(): bg = rect + layout.pageMargins() painter.fillRect(bg, self.palette().highlight()) painter.setPen(self.palette().highlightedText().color()) else: painter.setPen(self.palette().text().color()) # draw text textr = QRect(rect.x(), rect.bottom(), rect.width(), layout.pageMargins().bottom()) painter.drawText(textr, Qt.AlignCenter, str(layout.index(p) + self.firstPageNumber)) super().paintEvent(ev)
[docs] def wheelEvent(self, ev): """Reimplemented to page instead of scroll.""" if ev.angleDelta().y() > 0: self.gotoPreviousPage() elif ev.angleDelta().y() < 0: self.gotoNextPage()
[docs] def keyPressEvent(self, ev): """Reimplemented to page instead of scroll.""" if ev.key() in (Qt.Key_PageDown, Qt.Key_Down): self.gotoNextPage() elif ev.key() in (Qt.Key_PageUp, Qt.Key_Up): self.gotoPreviousPage() elif ev.key() == Qt.Key_End: self.setCurrentPageNumber(self.pageCount()) elif ev.key() == Qt.Key_Home: self.setCurrentPageNumber(1) else: super().keyPressEvent(ev)
[docs] def resizeEvent(self, ev): """Reimplemented to auto-change the orientation if desired.""" super().resizeEvent(ev) if self.autoOrientationEnabled: s = ev.size() if s.width() > s.height() and self.orientation() == constants.Vertical: self.setOrientation(constants.Horizontal) elif s.width() < s.height() and self.orientation() == constants.Horizontal: self.setOrientation(constants.Vertical)
[docs] def changeEvent(self, ev): """Reimplemented to set the correct font height for the page numbers.""" super().changeEvent(ev) if ev.type() in (QEvent.ApplicationFontChange, QEvent.FontChange): self.setLayoutFontHeight()