# -*- coding: utf-8 -*-

# Copyright (c) 2002 - 2006 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing the printer functionality.
"""

from qt import *
from qtext import QextScintilla

from KdeQt.KQPrinter import KQPrinter

import Preferences

class Printer(KQPrinter):
    """ 
    Class implementing the QextScintillaPrinter with a header.
    """
    def __init__(self, mode = KQPrinter.ScreenResolution):
        """
        Constructor
        
        @param mode mode of the printer (KQPrinter....)
        """
        KQPrinter.__init__(self, mode)
        
        self.wrap = QextScintilla.WrapWord
        self.mag = 0
        
        self.setMagnification(Preferences.getPrinter("Magnification"))
        if Preferences.getPrinter("ColorMode"):
            self.setColorMode(KQPrinter.Color)
        else:
            self.setColorMode(KQPrinter.GrayScale)
        if Preferences.getPrinter("FirstPageFirst"):
            self.setPageOrder(KQPrinter.FirstPageFirst)
        else:
            self.setPageOrder(KQPrinter.LastPageFirst)
        self.setPrinterName(Preferences.getPrinter("PrinterName"))
        self.time = QTime.currentTime().toString(Qt.LocalDate)
        self.date = QDate.currentDate().toString(Qt.LocalDate)
        self.headerFont = Preferences.getPrinter("HeaderFont")
        
    def formatPage(self, painter, drawing, area, pagenr):
        """
        Private method to generate a header line.
        
        @param painter the paint canvas (QPainter)
        @param drawing flag indicating that something should be drawn
        @param area the drawing area (QRectangle)
        @param pagenr the page number (int)
        """
        fn = self.docName()
        
        header = qApp.translate('Printer', '%1 - Printed on %2, %3 - Page %4')\
            .arg(fn)\
            .arg(self.date)\
            .arg(self.time)\
            .arg(pagenr)
            
        font = painter.font()   # save the current font
        pen = painter.pen()     # save current pen
        painter.setFont(self.headerFont)    # set our header font
        painter.setPen(Qt.black)            # set color
        if drawing:
            painter.drawText(area.right() - painter.fontMetrics().width(header),
                area.top() + painter.fontMetrics().ascent(), header)
        area.setTop(area.top() + painter.fontMetrics().height()+5)
        painter.setFont(font)   # reset the font
        painter.setPen(pen)
        
    def printRange(self, qsb, _from = -1, _to = -1):
        """
        Public method to print a range of text.
        
        @param qsb reference to a QextScintilla instance
        @param _from start line of print range (integer)
        @param _to end line of print range (integer)
        @return flag indicating success (boolean)
        """
        # sanity check
        if qsb is None:
            return 0
            
        # setup the printing area
        metrics = QPaintDeviceMetrics(self)
        def_area = QRect()
        
        def_area.setX(0)
        def_area.setY(0)
        def_area.setWidth(metrics.width())
        def_area.setHeight(metrics.height())
        
        # get the page range
        pgFrom = self.fromPage()
        pgTo = self.toPage()
        
        # find the position range
        endPos = qsb.SendScintilla(QextScintilla.SCI_GETLENGTH)
        if _from > 0:
            startPos = qsb.SendScintilla(QextScintilla.SCI_POSITIONFROMLINE, _from)
        else:
            startPos = 0
            
        if _to >= 0:
            toPos = qsb.SendScintilla(QextScintilla.SCI_POSITIONFROMLINE, _to + 1)
            
            if endPos > toPos:
                endPos = toPos
                
        if startPos >= endPos:
            return 0
            
        painter = QPainter(self)
        reverse = self.pageOrder() == KQPrinter.LastPageFirst
        needNewPage = 0
        
        qsb.SendScintilla(QextScintilla.SCI_SETPRINTMAGNIFICATION, self.mag)
        qsb.SendScintilla(QextScintilla.SCI_SETPRINTWRAPMODE, self.wrap)
        
        for i in range(self.numCopies()):
            # if we are printing in reverse page order then remember the
            # start position of each page
            pageStarts = []
            
            currPage = 1
            pos = startPos
            
            while pos < endPos:
                # see if we have finished the requested page range
                if pgTo > 0 and pgTo < currPage:
                    break
                    
                # see if we are going to render this page, or just see
                # how much would fit onto it
                render = 0
                
                if pgFrom == 0 or pgFrom <= currPage:
                    if reverse:
                        pageStarts.append(pos)
                    else:
                        render = 1
                        if needNewPage:
                            if not self.newPage():
                                return 0
                        else:
                            needNewPage = 1
                            
                area = QRect(def_area)
                
                self.formatPage(painter, render, area, currPage)
                pos = qsb.SendScintilla(QextScintilla.SCI_FORMATRANGE, render, painter, area, pos, endPos)
                
                currPage += 1
                
            # all done if we are printing in normal page order
            if not reverse:
                continue
                
            # now go through each page on the stack and really print it
            while pageStarts:
                currPage -= 1
                
                ePos = pos
                pos = pageStarts.pop()
                
                if needNewPage:
                    if not self.newPage():
                        return 0
                else:
                    needNewPage = 1
                    
                area = QRect(def_area)
                
                self.formatPage(painter, 1, area, currPage)
                qsb.SendScintilla(QextScintilla.SCI_FORMATRANGE, 1, painter, area, pos, ePos)
                
        return 1
        
    def magnification(self):
        """
        Public method to retrieve the print magnification.
        
        @return print magnification (integer)
        """
        return self.mag
        
    def setMagnification(self, magnification):
        """
        Public slot to set the print magnification.
        
        @param magnification print magnification to be set (integer)
        """
        self.mag = magnification
        
    def wrapMode(self):
        """
        Public method to retrieve the print wrap mode.
        
        @return print wrap mod (QextScintilla.WrapMode)
        """
        return self.wrap
        
    def setWrapMode(self, wmode):
        """
        Public slot to set the print wrap mode.
        
        @param wmode print wrap mode to be set (QextScintilla.WrapMode)
        """
        self.wrap = wmode
