CHANGES: update v4.4.2 release notes draft for #1368
[git-cola.git] / cola / widgets / log.py
blobe0ffe9410a6a47bdaa31a191b8674d399b3bc7c7
1 import time
3 from qtpy import QtGui
4 from qtpy import QtWidgets
5 from qtpy.QtCore import Qt
6 from qtpy.QtCore import Signal
8 from .. import core
9 from .. import qtutils
10 from ..i18n import N_
11 from . import defs
12 from . import text
13 from . import standard
16 class LogWidget(QtWidgets.QFrame):
17 """A simple dialog to display command logs."""
19 channel = Signal(object)
21 def __init__(self, context, parent=None, output=None):
22 QtWidgets.QFrame.__init__(self, parent)
24 self.output_text = text.VimTextEdit(context, parent=self)
25 self.highlighter = LogSyntaxHighlighter(self.output_text.document())
26 if output:
27 self.set_output(output)
28 self.main_layout = qtutils.vbox(defs.no_margin, defs.spacing, self.output_text)
29 self.setLayout(self.main_layout)
30 self.channel.connect(self.append, type=Qt.QueuedConnection)
31 self.log(N_('Right-click links to open:'))
32 self.log(' Documentation: https://git-cola.readthedocs.io/en/latest/')
33 self.log(
34 ' Keyboard Shortcuts: '
35 'https://git-cola.gitlab.io/share/doc/git-cola/hotkeys.html\n'
38 def clear(self):
39 self.output_text.clear()
41 def set_output(self, output):
42 self.output_text.set_value(output)
44 def log_status(self, status, out, err=None):
45 msg = []
46 if out:
47 msg.append(out)
48 if err:
49 msg.append(err)
50 if status:
51 msg.append(N_('exit code %s') % status)
52 self.log('\n'.join(msg))
54 def append(self, msg):
55 """Append to the end of the log message"""
56 if not msg:
57 return
58 msg = core.decode(msg)
59 cursor = self.output_text.textCursor()
60 cursor.movePosition(cursor.End)
61 text_widget = self.output_text
62 # NOTE: the ': ' colon-SP-SP suffix is for the syntax highlighter
63 prefix = core.decode(time.strftime('%Y-%m-%d %H:%M:%S: ')) # ISO-8601
64 for line in msg.split('\n'):
65 cursor.insertText(prefix + line + '\n')
66 cursor.movePosition(cursor.End)
67 text_widget.setTextCursor(cursor)
69 def log(self, msg):
70 """Add output to the log window"""
71 # Funnel through a Qt queued to allow thread-safe logging from
72 # asynchronous QRunnables, filesystem notification, etc.
73 self.channel.emit(msg)
76 class LogSyntaxHighlighter(QtGui.QSyntaxHighlighter):
77 """Implements the log syntax highlighting"""
79 def __init__(self, doc):
80 QtGui.QSyntaxHighlighter.__init__(self, doc)
81 palette = QtGui.QPalette()
82 QPalette = QtGui.QPalette
83 self.disabled_color = palette.color(QPalette.Disabled, QPalette.Text)
85 def highlightBlock(self, block_text):
86 end = block_text.find(': ')
87 if end > 0:
88 self.setFormat(0, end + 1, self.disabled_color)
91 class RemoteMessage(standard.Dialog):
92 """Provides a dialog to display remote messages"""
94 def __init__(self, context, message, parent=None):
95 standard.Dialog.__init__(self, parent=parent)
96 self.context = context
97 self.model = context.model
99 self.setWindowTitle(N_('Remote Messages'))
100 if parent is not None:
101 self.setWindowModality(Qt.WindowModal)
103 self.text = text.VimTextEdit(context, parent=self)
104 self.text.set_value(message)
105 # Set a monospace font, as some remote git messages include ASCII art
106 self.text.setFont(qtutils.default_monospace_font())
108 self.close_button = qtutils.close_button()
109 self.close_button.setDefault(True)
111 self.bottom_layout = qtutils.hbox(
112 defs.no_margin, defs.button_spacing, qtutils.STRETCH, self.close_button
115 self.main_layout = qtutils.vbox(
116 defs.no_margin, defs.spacing, self.text, self.bottom_layout
118 self.setLayout(self.main_layout)
120 qtutils.connect_button(self.close_button, self.close)
122 self.resize(defs.scale(720), defs.scale(400))
125 def show_remote_messages(context):
126 """Return a closure for the `result` callback from RunTask.start()"""
128 def show_remote_messages_callback(result):
129 """Display the asynchronous "result" when remote tasks complete"""
130 _, out, err = result
131 output = '\n\n'.join(x for x in (out, err) if x)
132 if output:
133 message = N_('Right-click links to open:') + '\n\n' + output
134 else:
135 message = output
137 # Display a window if the remote sent a message
138 if message:
139 view = RemoteMessage(context, message, parent=context.view)
140 view.show()
141 view.exec_()
143 return show_remote_messages_callback