Like other things posted here without notices to the contrary, this
code is in the public domain.

This is a relatively responsive pager program for text files, much
like 'more' or 'less', but in a GUI, so it zooms in and out with the +
and - keys.

It's written in Python with PyQt.

#!/usr/bin/python
import qt, sys, time, qd

class mailviewer(qt.QWidget):
    def __init__(self, filename, parent=None):
        qt.QWidget.__init__(self, parent, None,
                            qt.Qt.WStaticContents | qt.Qt.WRepaintNoErase)
        self.fontSize = 10
        self.setFont()
        self.setEraseColor(self.white)
        self.setFocusPolicy(qt.QWidget.StrongFocus)
        self.file = file(filename)
        self.filePos = 0
        self.prevPoses = []
        self.startTime = time.time()
    def setFont(self):
        # to get this font name, I used this to select from the dialog box:
        # self.font, ok = qt.QFontDialog.getFont(self.font)
        # It's Palatino.
        self.font = qt.QFont('Urw Palladio l', self.fontSize)
    def adjustFontSize(self, delta):
        self.fontSize += delta
        self.setFont()
        self.update()
    def pageUp(self):
        if self.prevPoses:
            self.filePos = self.prevPoses.pop()
            self.update()
    def pageDown(self):
        self.prevPoses.append(self.filePos)
        self.filePos = self.newPos
        self.update()
    def keyPressEvent(self, ev):
        self.startTime = time.time()
        key = ev.key()
        if key in [qt.Qt.Key_Plus, qt.Qt.Key_Equal]:
            self.adjustFontSize(delta = +2)
        elif key in [qt.Qt.Key_Minus]:
            self.adjustFontSize(delta = -2)
        elif key in [qt.Qt.Key_Next, qt.Qt.Key_Space]:
            self.pageDown()
        elif key in [qt.Qt.Key_Prior, qt.Qt.Key_Backspace]:
            self.pageUp()
        else:
            self.startTime = None
            ev.ignore()
            return
        ev.accept()
    def lineReader(self):
        self.file.seek(self.filePos)
        return iter(self.file)
    def paintEvent(self, ev):
        if self.startTime is None: self.startTime = time.time()
        pix = qt.QPixmap(self.size())
        pix.fill(self, 0, 0)
        
        pa = qt.QPainter(pix)
        pa.setFont(self.font)
        linespacing = pa.fontMetrics().lineSpacing()
        y = linespacing
        lines = self.lineReader()
        height = self.height()
        try:
            self.newPos = self.filePos
            while y < height + linespacing:
                rawline = lines.next()
                self.newPos += len(rawline)
                pa.drawText(10, y, qd.chomp(qd.untabify(rawline)))
                y += linespacing
        except StopIteration:
            pass  # ran out of lines!
        pa.end()
        npa = qt.QPainter(self)
        npa.drawPixmap(0, 0, pix)
        npa.setFont(qt.QFont('Helvetica', 10))
        npa.setPen(self.darkGray)
        npa.drawText(self.width() - 40, npa.fontMetrics().lineSpacing(),
                     str(time.time() - self.startTime))

if __name__ == '__main__':
    a = qt.QApplication(sys.argv)
    w = mailviewer(sys.argv[1])
    a.setMainWidget (w)
    w.show()
    w.setFocus()
    a.exec_loop()

Here's qd.py, which it depends on:
def chomp(text):
    while text[-1:] in ['\r', '\n']: text = text[:-1]
    return text

assert chomp('a\n') == 'a'
assert chomp('\n') == ''
assert chomp('') == ''

def untabify(text):
    def dumb_tab_exp(char):
        if char != '\t': return char
        return '    '
    return ''.join(map(dumb_tab_exp, text))

Reply via email to