File: log.py

package info (click to toggle)
frescobaldi 2.0.5%2Bds1-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 12,212 kB
  • sloc: python: 31,557; makefile: 47; sh: 3
file content (137 lines) | stat: -rw-r--r-- 4,914 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# This file is part of the Frescobaldi project, http://www.frescobaldi.org/
#
# Copyright (c) 2008 - 2012 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 Log shows the output of a Job.
"""

from __future__ import unicode_literals

import contextlib

from PyQt4.QtCore import *
from PyQt4.QtGui import *

import job
import qutil


class Log(QTextBrowser):
    """Widget displaying output from a Job."""
    def __init__(self, parent=None):
        super(Log, self).__init__(parent)
        self.setOpenLinks(False)
        self.cursor = QTextCursor(self.document())
        self._lasttype = None
        self._formats = self.logformats()
        
    def connectJob(self, job):
        """Gives us the output from the Job (past and upcoming)."""
        for msg, type in job.history():
            self.write(msg, type)
        job.output.connect(self.write)
        
    def textFormat(self, type):
        """Returns a QTextFormat() for the given type."""
        return self._formats[type]

    def write(self, message, type):
        """Writes the given message with the given type to the log.
        
        The keepScrolledDown context manager is used to scroll the log further
        down if it was scrolled down at that moment.
        
        If two messages of a different type are written after each other a newline
        is inserted if otherwise the message would continue on the same line.
        
        """
        with self.keepScrolledDown():
            changed = type != self._lasttype
            self._lasttype = type
            if changed and self.cursor.block().text() and not message.startswith('\n'):
                self.cursor.insertText('\n')
            self.writeMessage(message, type)
    
    def writeMessage(self, message, type):
        """Inserts the given message in the text with the textformat belonging to type."""
        self.cursor.insertText(message, self.textFormat(type))
    
    @contextlib.contextmanager
    def keepScrolledDown(self):
        """Performs a function, ensuring the log stays scrolled down if it was scrolled down on start."""
        vbar = self.verticalScrollBar()
        scrolleddown = vbar.value() == vbar.maximum()
        try:
            yield
        finally:
            if scrolleddown:
                vbar.setValue(vbar.maximum())
    
    def logformats(self):
        """Returns a dictionary with QTextCharFormats for the different types of messages.
        
        Besides the STDOUT, STDERR, NEUTRAL, FAILURE and SUCCESS formats there is also
        a "link" format, that looks basically the same as the output formats, but blueish
        and underlined, to make parts of the output (e.g. filenames) look clickable.
        
        """
        textColor = QApplication.palette().color(QPalette.WindowText)
        successColor = qutil.addcolor(textColor, 0, 128, 0) # more green
        failureColor = qutil.addcolor(textColor, 128, 0, 0) # more red
        linkColor    = qutil.addcolor(textColor, 0, 0, 128) # more blue
        stdoutColor  = qutil.addcolor(textColor, 64, 64, 0) # more purple
        
        s = QSettings()
        s.beginGroup("log")
        outputFont = QFont(s.value("fontfamily", "monospace"))
        outputFont.setPointSizeF(float(s.value("fontsize", 9.0)))
        
        output = QTextCharFormat()
        output.setFont(outputFont)
        
        stdout = QTextCharFormat(output)
        stdout.setForeground(stdoutColor)
        
        stderr = QTextCharFormat(output)
        link   = QTextCharFormat(output)
        link.setForeground(linkColor)
        link.setFontUnderline(True)
        
        status = QTextCharFormat()
        status.setFontWeight(QFont.Bold)
        
        neutral = QTextCharFormat(status)
        
        success = QTextCharFormat(status)
        success.setForeground(successColor)
        
        failure = QTextCharFormat(status)
        failure.setForeground(failureColor)
        
        return {
            job.STDOUT: stdout,
            job.STDERR: stderr,
            job.NEUTRAL: neutral,
            job.SUCCESS: success,
            job.FAILURE: failure,
            'link': link,
        }