Source code for qpageview.diff

# -*- 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.

"""
A Page intended to display the visual difference between other pages.

"""

import itertools

from PyQt5.QtCore import Qt
from PyQt5.QtGui import QColor, QPainter, QPixmap

from . import multipage
from . import page


[docs]class DiffPage(page.ImagePrintPageMixin, multipage.MultiPage): """A Page that shows the difference between sub pages. DiffPage inherits from MultiPage; the pages are to be added in the pages attribute. The first page is considered to be the "default" page, shown the normal way; the others are added in configurable colors and intensity. """ opaquePages = False
[docs] @classmethod def createPages(cls, pageLists, renderer=None, pad=page.BlankPage): """Reimplemented to adapt the page sizes.""" it = itertools.zip_longest(*pageLists) if pad else zip(*pageLists) for pages in it: page = cls(renderer) # copy the dimensions from the first non-blank page for p in pages: if p: page.dpi = p.dpi page.pageWidth = p.pageWidth page.pageHeight = p.pageHeight break # set that dimensions also to blank pages. def padpage(): p = pad() p.dpi = page.dpi p.pageWidth = page.pageWidth p.pageHeight = page.pageHeight return p page.pages[:] = (p if p else padpage() for p in pages) yield page
[docs]class DiffDocument(multipage.MultiPageDocument): """A Document showing the differences between documents, set as sources.""" pageClass = DiffPage
[docs]class DiffRenderer(multipage.MultiPageRenderer): """Renders the pages by calling their own renderer. How the difference is displayed can be configured using this renderer. Up to four different pages can be displayed, the colors to render them are taken from the colors instance variable, which is a list. The alpha channel of each color determines the visiblity of the corresponding sub page. This renderer works best with pages that are mostly black on a white background. """ def __init__(self): # we don't use a cache so no need to call super init self.colors = [ QColor(Qt.black), QColor(Qt.red), QColor(Qt.green), QColor(Qt.blue), ]
[docs] def combine(self, painter, images): """Paint images on the painter. We draw bottom-up, using Darken composition mode, so the lower images remain visible. """ for color, (pos, image) in zip(self.colors, images): # take the alpha component intensity = 255 - color.alpha() if intensity == 255: continue # the image would appear white anyway color = color.rgb() color |= 0x010101 * intensity color |= 0xFF000000 p = QPainter(image) p.setCompositionMode(QPainter.CompositionMode_Lighten) p.fillRect(image.rect(), QColor(color)) p.end() if isinstance(image, QPixmap): painter.drawPixmap(pos, image) else: painter.drawImage(pos, image) painter.setCompositionMode(QPainter.CompositionMode_Darken)
# install a default renderer, so DiffPage can be used directly DiffPage.renderer = DiffRenderer()