logViewer.py
3.78 KB
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
"""Provides functionality to view the NVDA log.
"""
import codecs
import wx
import globalVars
import gui
#: The singleton instance of the log viewer UI.
logViewer = None
class LogViewer(wx.Frame):
"""The NVDA log viewer GUI.
"""
def __init__(self, parent):
# Translators: The title of the NVDA log viewer window.
super(LogViewer, self).__init__(parent, wx.ID_ANY, _("NVDA Log Viewer"))
self.Bind(wx.EVT_ACTIVATE, self.onActivate)
self.Bind(wx.EVT_CLOSE, self.onClose)
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.outputCtrl = wx.TextCtrl(self, wx.ID_ANY, size=(500, 500), style=wx.TE_MULTILINE | wx.TE_READONLY|wx.TE_RICH)
self.outputCtrl.Bind(wx.EVT_KEY_DOWN, self.onOutputKeyDown)
mainSizer.Add(self.outputCtrl, proportion=1, flag=wx.EXPAND)
self.SetSizer(mainSizer)
mainSizer.Fit(self)
menuBar = wx.MenuBar()
menu = wx.Menu()
# Translators: The label for a menu item in NVDA log viewer to refresh log messages.
item = menu.Append(wx.ID_ANY, _("Refresh F5"))
self.Bind(wx.EVT_MENU, self.refresh, item)
# Translators: The label for a menu item in NVDA log viewer to save log file.
item = menu.Append(wx.ID_SAVEAS, _("Save &as... Ctrl+S"))
self.Bind(wx.EVT_MENU, self.onSaveAsCommand, item)
menu.AppendSeparator()
item = menu.Append(wx.ID_EXIT, _("E&xit"))
self.Bind(wx.EVT_MENU, self.onClose, item)
# Translators: The title of a menu in NVDA Log Viewer.
menuBar.Append(menu, _("Log"))
self.SetMenuBar(menuBar)
self._lastFilePos = 0
self.refresh()
self.outputCtrl.SetFocus()
def refresh(self, evt=None):
pos = self.outputCtrl.GetInsertionPoint()
# Append new text to the output control which has been written to the log file since the last refresh.
try:
f = codecs.open(globalVars.appArgs.logFileName, "r", encoding="UTF-8")
f.seek(self._lastFilePos)
self.outputCtrl.AppendText(f.read())
self._lastFilePos = f.tell()
self.outputCtrl.SetInsertionPoint(pos)
f.close()
except IOError:
pass
def onActivate(self, evt):
if evt.GetActive():
self.refresh()
evt.Skip()
def onClose(self, evt):
self.Destroy()
def onSaveAsCommand(self, evt):
# Translators: Label of a menu item in NVDA Log Viewer.
filename = wx.FileSelector(_("Save As"), default_filename="nvda.log", flags=wx.SAVE | wx.OVERWRITE_PROMPT, parent=self)
if not filename:
return
try:
# codecs.open() forces binary mode, which is bad under Windows because line endings won't be converted to crlf automatically.
# Therefore, do the encoding manually.
file(filename, "w").write(self.outputCtrl.GetValue().encode("UTF-8"))
except (IOError, OSError), e:
# Translators: Dialog text presented when NVDA cannot save a log file.
gui.messageBox(_("Error saving log: %s") % e.strerror, _("Error"), style=wx.OK | wx.ICON_ERROR, parent=self)
def onOutputKeyDown(self, evt):
key = evt.GetKeyCode()
# #3763: WX 3 no longer passes escape via evt_char in richEdit controls. Therefore evt_key_down must be used.
if key == wx.WXK_ESCAPE:
self.Close()
return
evt.Skip()
def activate():
"""Activate the log viewer.
If the log viewer has not already been created and opened, this will create and open it.
Otherwise, it will be brought to the foreground if possible.
"""
global logViewer
if globalVars.appArgs.secure:
# The log might expose sensitive information and the Save As dialog in the Log Viewer is a security risk.
return
if not logViewer:
logViewer = LogViewer(gui.mainFrame)
logViewer.Raise()
# There is a MAXIMIZE style which can be used on the frame at construction, but it doesn't seem to work the first time it is shown,
# probably because it was in the background.
# Therefore, explicitly maximise it here.
# This also ensures that it will be maximized whenever it is activated, even if the user restored/minimised it.
logViewer.Maximize()
logViewer.Show()