-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathprogress.py
More file actions
160 lines (118 loc) · 5.81 KB
/
Copy pathprogress.py
File metadata and controls
160 lines (118 loc) · 5.81 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
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
"""
Defines a context manager for long running processes. It does the following:
- changes the cursor to a timer
- displays text to indicate what is running in the status bar (if window has one)
- displays a dialog with a traceback if an error occurs
"""
import wx
import traceback
from PYME.misc.exceptions import UserError
_package_info = '''python-microscopy={pyme_version}
python={python_version}, platform={platform}
numpy={numpy_version}, wx={wx_version}'''
def get_package_versions():
import sys
import PYME.version
import numpy as np
# TODO - get other package versions?
return _package_info.format(pyme_version=PYME.version.detailed_version(),
python_version='.'.join([str(n) for n in sys.version_info[:3]]), platform=sys.platform,
numpy_version=np.version.version, wx_version=wx.version())
error_msg = ''' Error whilst running {description}
==============================================
{pkgversions}
Traceback
=========
{traceback}
'''
class TracebackDialog(wx.Dialog):
def __init__(self, parent, description, exc_type, exc_val, exc_tb):
wx.Dialog.__init__(self, parent, title='Error whilst %s' % description)
vsizer = wx.BoxSizer(wx.VERTICAL)
hsizer=wx.BoxSizer(wx.HORIZONTAL)
s_b = wx.StaticBitmap(self)
s_b.SetIcon(wx.ArtProvider.GetIcon(wx.ART_ERROR, client=wx.ART_MESSAGE_BOX, size=(32,32)))
hsizer.Add(s_b, 0, wx.ALL|wx.ALIGN_CENTRE_VERTICAL, 2)
hsizer.Add(wx.StaticText(self, label='%s(%s)' %(exc_type.__name__, exc_val)),0, wx.ALL|wx.ALIGN_CENTRE_VERTICAL, 2 )
vsizer.Add(hsizer, 0, wx.ALL, 2)
#print(exc_tb)
tb = ''.join(traceback.format_exception(exc_type, exc_val, exc_tb))
#print(tb, type(tb))
self.err_text=wx.TextCtrl(self, value=error_msg.format(description=description, pkgversions=get_package_versions(), traceback=tb),
size=(500,300), style=wx.TE_MULTILINE|wx.TE_READONLY)
vsizer.Add(self.err_text, 0, wx.ALL|wx.EXPAND, 15)
vsizer.Add(wx.StaticText(self, label='Copy and paste the above message into an email or issue when\n reporting a bug'),0, wx.ALL, 5)
btnsizer = wx.StdDialogButtonSizer()
copy_btn = wx.Button(self, label="Copy")
copy_btn.Bind(wx.EVT_BUTTON, self.on_copy)
btnsizer.Add(copy_btn, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL,5)
btn = wx.Button(self, wx.ID_OK)
btn.SetDefault()
btnsizer.AddButton(btn)
btnsizer.Realize()
vsizer.Add(btnsizer, 0, wx.ALL|wx.EXPAND, 2)
self.SetSizerAndFit(vsizer)
def on_copy(self, event):
self.data = wx.TextDataObject()
self.data.SetText(self.err_text.GetValue())
if wx.TheClipboard.Open():
wx.TheClipboard.SetData(self.data)
wx.TheClipboard.Close()
else:
wx.MessageBox("Unable to open the clipboard","Error")
class UserErrorDialog(wx.Dialog):
def __init__(self, parent, description, exc_type, exc_val, exc_tb):
wx.Dialog.__init__(self, parent, title='Error whilst %s' % description)
vsizer = wx.BoxSizer(wx.VERTICAL)
hsizer = wx.BoxSizer(wx.HORIZONTAL)
s_b = wx.StaticBitmap(self)
s_b.SetIcon(wx.ArtProvider.GetIcon(wx.ART_ERROR, client=wx.ART_MESSAGE_BOX, size=(32, 32)))
hsizer.Add(s_b, 0, wx.ALL | wx.ALIGN_CENTRE_VERTICAL, 2)
hsizer.Add(wx.StaticText(self, label='%s' % exc_val), 1,
wx.ALL | wx.ALIGN_CENTRE_VERTICAL|wx.EXPAND, 2)
vsizer.Add(hsizer, 0, wx.ALL, 2)
btnsizer = wx.StdDialogButtonSizer()
btn = wx.Button(self, wx.ID_OK)
btn.SetDefault()
btnsizer.AddButton(btn)
btnsizer.Realize()
vsizer.Add(btnsizer, 0, wx.ALL | wx.EXPAND, 2)
self.SetSizerAndFit(vsizer)
def show_traceback_dialog(parent, description, exc_type, exc_val, exc_tb):
if exc_type is UserError:
dlg = UserErrorDialog(parent, description, exc_type, exc_val, exc_tb)
else:
dlg = TracebackDialog(parent, description, exc_type, exc_val, exc_tb)
dlg.ShowModal()
dlg.Destroy()
class ComputationInProgress(object):
"""
Context manager for wrapping long-running tasks in the GUI - indicates that something is happening and display a
dialog showing the error on failure
"""
def __init__(self, window, short_description):
self.window = window # type: wx.Window
self.description = short_description
def __enter__(self):
self._old_cursor = self.window.GetCursor()
self.window.SetCursor(wx.Cursor(wx.CURSOR_WAIT))
if hasattr(self.window, 'SetStatus'):
# at present, only VisGUI has SetStatus - possibly rename...
self.window.SetStatus('%s ... in progress' % self.description)
def __exit__(self, exc_type, exc_val, exc_tb):
self.window.SetCursor(self._old_cursor)
if exc_type:
show_traceback_dialog(self.window, self.description, exc_type, exc_val, exc_tb)
if hasattr(self.window, 'SetStatus'):
self.window.SetStatus('%s ... [FAILED]' % self.description)
else:
if hasattr(self.window, 'SetStatus'):
self.window.SetStatus('%s ... [COMPLETE]' % self.description)
def managed(fcn, window, description):
""" wrap a function in a context manager - used to wrap menu items"""
def func(*args, **kwargs):
with ComputationInProgress(window, description):
return fcn(*args, **kwargs)
return func
class SlowComputation(object):
""" Pops up a dialog with a launches a computation in a separate thread """