source: sasview/src/sas/guiframe/gui_statusbar.py @ 8d302cd

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 8d302cd was b3efb7d, checked in by krzywon, 10 years ago

Modified data loading error messages to be much more specific and
include information in the console log about the specific errors
generated.

The cansas reader is now loading non-standard units (ie counts), but
shows a specific error message about the issue.

  • Property mode set to 100644
File size: 14.3 KB
RevLine 
[010c251]1import wx
[804a7db]2import sys
[010c251]3from wx import StatusBar as wxStatusB
4from wx.lib import newevent
[2d98490]5import wx.richtext
[79492222]6from sas.guiframe.gui_style import GUIFRAME_ICON
[caf273b]7
8# Number of fields on the status bar
[010c251]9NB_FIELDS = 4
10#position of the status bar's fields
11ICON_POSITION = 0
12MSG_POSITION  = 1
13GAUGE_POSITION  = 2
14CONSOLE_POSITION  = 3
15BUTTON_SIZE = 40
[caf273b]16STATUS_BAR_ICON_SIZE = 12
[2d98490]17CONSOLE_WIDTH = 500
[199fdec]18CONSOLE_HEIGHT = 300
[804a7db]19if sys.platform.count("win32") > 0:
20    FONT_VARIANT = 0
21else:
22    FONT_VARIANT = 1
[010c251]23
[b50b057]24GREEN = wx.Colour(95, 190, 95)
25YELLOW = wx.Colour(247, 214, 49)
26RED = wx.Colour(234, 89, 78)
27
[010c251]28class ConsolePanel(wx.Panel):
29    """
30    """
31    def __init__(self, parent, *args, **kwargs):
32        """
33        """
34        wx.Panel.__init__(self, parent=parent, *args, **kwargs)
35        self.parent = parent
36        self.sizer = wx.BoxSizer(wx.VERTICAL)
[2d98490]37       
38        self.msg_txt = wx.richtext.RichTextCtrl(self, size=(CONSOLE_WIDTH-40,
39                                                CONSOLE_HEIGHT-60),
40                                   style=wx.VSCROLL|wx.HSCROLL|wx.NO_BORDER)
41       
[010c251]42        self.msg_txt.SetEditable(False)
43        self.msg_txt.SetValue('No message available')
44        self.sizer.Add(self.msg_txt, 1, wx.EXPAND|wx.ALL, 10)
45        self.SetSizer(self.sizer)
46       
[2d98490]47    def set_message(self, status="", event=None):
[010c251]48        """
49        """
[2d98490]50        status = str(status)
51        if status.strip() == "":
52            return
53        color = (0, 0, 0) #black
54        icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_INFORMATION,
[caf273b]55                                             wx.ART_TOOLBAR)
[2d98490]56        if hasattr(event, "info"):
57            icon_type = event.info.lower()
58            if icon_type == "warning":
59                color = (0, 0, 255) # blue
60                icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_WARNING,
[caf273b]61                                                     wx.ART_TOOLBAR)
[2d98490]62            if icon_type == "error":
63                color = (255, 0, 0) # red
64                icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_ERROR, 
65                                                     wx.ART_TOOLBAR)
66            if icon_type == "info":
67                icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_INFORMATION,
68                                                     wx.ART_TOOLBAR)
69        self.msg_txt.Newline()
70        self.msg_txt.WriteBitmap(icon_bmp)
71        self.msg_txt.BeginTextColour(color)
72        self.msg_txt.WriteText("\t")
73        self.msg_txt.AppendText(status)
74        self.msg_txt.EndTextColour()
75       
[010c251]76       
77class Console(wx.Frame):
78    """
79    """
80    def __init__(self, parent=None, status="", *args, **kwds):
81        kwds["size"] = (CONSOLE_WIDTH, CONSOLE_HEIGHT)
82        kwds["title"] = "Console"
83        wx.Frame.__init__(self, parent=parent, *args, **kwds)
[804a7db]84        self.SetWindowVariant(FONT_VARIANT)
[010c251]85        self.panel = ConsolePanel(self)
86        self.panel.set_message(status=status)
[bfa73ca]87        wx.EVT_CLOSE(self, self.Close)
[783940c]88       
[010c251]89    def set_multiple_messages(self, messages=[]):
90        """
91        """
92        if messages:
93            for status in messages:
[2d98490]94                self.panel.set_message(status=status)
[010c251]95               
[2d98490]96    def set_message(self, status, event=None):
[bfa73ca]97        """
98        """
[2d98490]99        self.panel.set_message(status=str(status), event=event)
[bfa73ca]100       
101    def Close(self, event):
[010c251]102        """
103        """
[bfa73ca]104        self.Hide()
[010c251]105       
106class StatusBar(wxStatusB):
107    """
[6e4d543]108        Application status bar
[010c251]109    """
[6e4d543]110    def __init__(self, parent, id):
111        wxStatusB.__init__(self, parent, id)
[010c251]112        self.parent = parent
113        self.parent.SetStatusBarPane(MSG_POSITION)
[6e4d543]114
[010c251]115        #Layout of status bar
[caf273b]116        width = STATUS_BAR_ICON_SIZE
117        height = STATUS_BAR_ICON_SIZE
[010c251]118        self.SetFieldsCount(NB_FIELDS) 
[6e4d543]119        # Leave some space for the resize handle in the last field
[beda555]120        console_btn_width = 80
121        self.SetStatusWidths([width+4, -2, -1, width+console_btn_width])
[b716dd8]122        self.SetMinHeight(height)
[6e4d543]123       
[010c251]124        #display default message
125        self.msg_position = MSG_POSITION
[6e4d543]126       
127        # Create progress bar
[804a7db]128        gauge_width = 5 * width
129        self.gauge = wx.Gauge(self, size=(gauge_width, height),
[010c251]130                               style=wx.GA_HORIZONTAL)
131        self.gauge.Hide()
[6e4d543]132       
133        # Create status bar icon reflecting the type of status
134        # for the last message
[8001331]135        self.status_color = wx.StaticText(self, id=wx.NewId(), label="   ", size=wx.Size(15,15))
[1d4e2e7]136        self.status_color.SetBackgroundColour(GREEN)
[7e44299]137        self.status_color.SetForegroundColour(GREEN)
[beda555]138
[6e4d543]139        # Create the button used to show the console dialog
[b50b057]140        self.console_button = wx.Button(self, wx.NewId(), "Console", 
[f330d67]141                                 size=(console_btn_width, -1))
[b50b057]142        font = self.console_button.GetFont()
[caf8dd4]143        _, pixel_h = font.GetPixelSize()
144        font.SetPixelSize(wx.Size(0,int(pixel_h*0.9)))
[b50b057]145        self.console_button.SetFont(font)
146        self.console_button.SetToolTipString("History of status bar messages")
147        self.console_button.Bind(wx.EVT_BUTTON, self._onMonitor,
148                                id=self.console_button.GetId())
[bfa73ca]149       
[010c251]150        self.reposition()
151        ## Current progress value of the bar
152        self.nb_start = 0
153        self.nb_progress = 0
154        self.nb_stop = 0
155        self.frame = None
156        self.list_msg = []
[bfa73ca]157        self.frame = Console(parent=self)
[07dd0b4]158        if hasattr(self.frame, "IsIconized"):
159            if not self.frame.IsIconized():
160                try:
161                    icon = self.parent.GetIcon()
162                    self.frame.SetIcon(icon)
163                except:
164                    try:
165                        FRAME_ICON = wx.Icon(GUIFRAME_ICON.FRAME_ICON_PATH,
166                                              wx.BITMAP_TYPE_ICON)
167                        self.frame.SetIcon(FRAME_ICON)
168                    except:
169                        pass
[bfa73ca]170        self.frame.set_multiple_messages(self.list_msg)
171        self.frame.Hide()
[caf273b]172        self.progress = 0
173        self.timer = wx.Timer(self, -1)
174        self.timer_stop = wx.Timer(self, -1)
[010c251]175        self.thread = None
176        self.Bind(wx.EVT_TIMER, self._on_time, self.timer) 
177        self.Bind(wx.EVT_TIMER, self._on_time_stop, self.timer_stop) 
178        self.Bind(wx.EVT_SIZE, self.OnSize)
179        self.Bind(wx.EVT_IDLE, self.OnIdle)
180       
181    def reposition(self):
182        """
[b716dd8]183            Place the various fields in their proper position
[010c251]184        """
185        rect = self.GetFieldRect(GAUGE_POSITION)
[6e4d543]186        self.gauge.SetPosition((rect.x, rect.y))
[010c251]187        rect = self.GetFieldRect(ICON_POSITION)
[1d4e2e7]188        self.status_color.SetPosition((rect.x, rect.y))
[010c251]189        rect = self.GetFieldRect(CONSOLE_POSITION)
[b50b057]190        self.console_button.SetPosition((rect.x, rect.y))
[010c251]191        self.sizeChanged = False
192       
193    def OnIdle(self, event):
194        """
195        """
196        if self.sizeChanged:
197            self.reposition()
198           
199    def OnSize(self, evt):
200        """
201        """
202        self.reposition() 
203        self.sizeChanged = True
204       
205    def get_msg_position(self):
206        """
207        """
208        return self.msg_position
209   
[2d98490]210    def SetStatusText(self, text="", number=MSG_POSITION, event=None):
[010c251]211        """
212        """
[0e29289]213        wxStatusB.SetStatusText(self, text.split('\n',1)[0], number)
[010c251]214        self.list_msg.append(text)
[1d4e2e7]215        self.status_color.SetBackgroundColour(GREEN)
[7e44299]216        self.status_color.SetForegroundColour(GREEN)
[caf273b]217
[bfa73ca]218        if self.frame is not None :
[2d98490]219            self.frame.set_message(status=text, event=event)
[bfa73ca]220       
[010c251]221    def PopStatusText(self, *args, **kwds):
222        """
223        Override status bar
224        """
225        wxStatusB.PopStatusText(self, field=MSG_POSITION)
[986da97]226       
[010c251]227    def PushStatusText(self, *args, **kwds):
228        """
[3fc01c5]229        PushStatusText
[010c251]230        """
[3fc01c5]231        text = "PushStatusText: What is this string?"
232        wxStatusB.PushStatusText(self, field=MSG_POSITION, string=text)
[010c251]233       
234    def enable_clear_gauge(self):
235        """
236        clear the progress bar
237        """
[940aca7]238        flag = True
239        # Why we do this?
240        #if (self.nb_start <= self.nb_stop) or \
241        #    (self.nb_progress <= self.nb_stop):
242        #    flag = True
[010c251]243        return flag
244   
245    def _on_time_stop(self, evt): 
246        """
247        Clear the progress bar
248       
249        :param evt: wx.EVT_TIMER
250 
251        """ 
252        count = 0
253        while(count <= 100):
254            count += 1
255        self.timer_stop.Stop() 
256        self.clear_gauge(msg="")
257        self.nb_progress = 0 
258        self.nb_start = 0 
259        self.nb_stop = 0
260       
261    def _on_time(self, evt): 
262        """
263        Update the progress bar while the timer is running
264       
265        :param evt: wx.EVT_TIMER
266 
267        """ 
268        # Check stop flag that can be set from non main thread
269        if self.timer.IsRunning(): 
270            self.gauge.Pulse()
271   
272    def clear_gauge(self, msg=""):
273        """
274        Hide the gauge
275        """
276        self.progress = 0
277        self.gauge.SetValue(0)
278        self.gauge.Hide() 
279         
280    def set_icon(self, event):
281        """
[2d98490]282        Display icons related to the type of message sent to the statusbar
283        when available. No icon is displayed if the message is empty
[010c251]284        """
[2d98490]285        if hasattr(event, "status"):
[07dd0b4]286            status = str(event.status)
[2d98490]287            if status.strip() == "":
288                return
289        else:
290            return
[010c251]291        if not hasattr(event, "info"):
292            return 
[6e4d543]293       
[b716dd8]294        # Get the size of the button images
[caf273b]295        height = STATUS_BAR_ICON_SIZE
[6e4d543]296       
[010c251]297        msg = event.info.lower()
298        if msg == "warning":
[1d4e2e7]299            self.status_color.SetBackgroundColour(YELLOW)
[7e44299]300            self.status_color.SetForegroundColour(YELLOW)
[6e4d543]301        elif msg == "error":
[1d4e2e7]302            self.status_color.SetBackgroundColour(RED)
[7e44299]303            self.status_color.SetForegroundColour(RED)
[6e4d543]304        else:
[1d4e2e7]305            self.status_color.SetBackgroundColour(GREEN)
[7e44299]306            self.status_color.SetForegroundColour(GREEN)
[010c251]307   
[7d89e50]308    def set_dialog(self, event):
309        """
310        Display dialogbox
311        """
312        if not hasattr(event, "info"):
313            return 
314        msg = event.info.lower()
315        if msg == "error":
316            e_msg = "Error(s) Occurred:\n"
[b3efb7d]317            e_msg += "\t" + event.status + "\n\n"
318            e_msg += "Further information might be available in "
319            e_msg += "the Console log (bottom right corner)."
[7d89e50]320            wx.MessageBox(e_msg, style=wx.ICON_ERROR)
321
[010c251]322    def set_message(self, event):
323        """
324        display received message on the statusbar
325        """
326        if hasattr(event, "status"):
[2d98490]327            self.SetStatusText(text=str(event.status), event=event)
[bfa73ca]328       
[010c251]329    def set_gauge(self, event):
330        """
331        change the state of the gauge according the state of the current job
332        """
333        if not hasattr(event, "type"):
334            return
335        type = event.type
336        self.gauge.Show(True)
337        if type.lower() == "start":
338            self.nb_start += 1
339            #self.timer.Stop()
[804a7db]340            self.progress += 5
[010c251]341            self.gauge.SetValue(int(self.progress)) 
[804a7db]342            self.progress += 5
[010c251]343            if self.progress < self.gauge.GetRange() - 20:
344                self.gauge.SetValue(int(self.progress)) 
345        if type.lower() == "progress":
346            self.nb_progress += 1
347            self.timer.Start(1)
348            self.gauge.Pulse()
349        if type.lower() == "update":
[804a7db]350            self.progress += 5
[010c251]351            if self.progress < self.gauge.GetRange()- 20:
352                self.gauge.SetValue(int(self.progress))   
353        if type.lower() == "stop":
354            self.nb_stop += 1
355            self.gauge.Show(True)
356            if self.enable_clear_gauge():
357                self.timer.Stop()
358                self.progress = 0
[3c965fd]359                self.gauge.SetValue(100) 
[804a7db]360                self.timer_stop.Start(5) 
[010c251]361                   
362    def set_status(self, event):
363        """
364        Update the status bar .
365       
366        :param type: type of message send.
367            type  must be in ["start","progress","update","stop"]
368        :param msg: the message itself  as string
369        :param thread: if updatting using a thread status
370       
371        """
372        self.set_message(event=event)
373        self.set_icon(event=event)
374        self.set_gauge(event=event)
[7d89e50]375        # dialog on error
376        self.set_dialog(event=event)
377       
[010c251]378    def _onMonitor(self, event):
379        """
380        Pop up a frame with messages sent to the status bar
381        """
[96683dc]382        self.frame.Show(False)
[010c251]383        self.frame.Show(True)
384       
385       
[7a955a9]386class SPageStatusbar(wxStatusB):
387    def __init__(self, parent, timeout=None, *args, **kwds):
388        wxStatusB.__init__(self, parent, *args, **kwds)
389        self.SetFieldsCount(1) 
390        self.timeout = timeout
[43cc1ad2]391        width, height = parent.GetSizeTuple()
392        self.gauge = wx.Gauge(self, style=wx.GA_HORIZONTAL, 
393                              size=(width, height/10))
[7a955a9]394        rect = self.GetFieldRect(0)
395        self.gauge.SetPosition((rect.x , rect.y ))
396        if self.timeout is not None:
397            self.gauge.SetRange(int(self.timeout))
398        self.timer = wx.Timer(self, -1) 
399        self.Bind(wx.EVT_TIMER, self._on_time, self.timer) 
400        self.timer.Start(1)
401        self.pos = 0
402       
403    def _on_time(self, evt): 
404        """
405        Update the progress bar while the timer is running
406       
407        :param evt: wx.EVT_TIMER
408 
409        """ 
410        # Check stop flag that can be set from non main thread
411        if self.timeout is None and self.timer.IsRunning(): 
412            self.gauge.Pulse()
413           
414       
[010c251]415if __name__ == "__main__":
416    app = wx.PySimpleApp()
417    frame = wx.Frame(None, wx.ID_ANY, 'test frame')
[7a955a9]418    #statusBar = StatusBar(frame, wx.ID_ANY)
419    statusBar = SPageStatusbar(frame)
[010c251]420    frame.SetStatusBar(statusBar)
421    frame.Show(True)
[7a955a9]422    #event = MessageEvent()
423    #event.type = "progress"
424    #event.status  = "statusbar...."
425    #event.info = "error"
426    #statusBar.set_status(event=event)
[010c251]427    app.MainLoop()
428
Note: See TracBrowser for help on using the repository browser.