these are the sources I am using and that show this problem in various
versions of Linux.

--- program-wx.py (the entry point) ---
#!/usr/bin/python2.6
# -*- coding: utf-8 -*-
#***********************************************************************
#*   
#***********************************************************************
#* Project    : various
#*  
#* $Id: asc.py 7726 2009-08-17 09:44:05Z Mario $
#*
#* initial programmer :  Mario Frasca
#* initial date       :  20090819
#**********************************************************************

__revision__ = "$Rev: 7726 $"[6:-2]

import wx, os, program_wxglade, logging, threading
import the_program
import nens.swx

log = logging.getLogger('nens.lcm.wx')
log.setLevel(logging.DEBUG)

class RunningDialog(program_wxglade.RunningDialog):
    def __init__(self, *args, **kwargs):
        program_wxglade.RunningDialog.__init__(self, *args, **kwargs)

        self.handler = nens.swx.TextCtrlHandler(self.text_ctrl_logging, 
level=logging.DEBUG)
        logging.getLogger('').addHandler(self.handler)
        self.count = 0

    def OnIdle(self, event):
        self.gauge.Pulse()
        pass

    def OnThreadStart(self, thread):
        self.handler.ClearWindow()
        log.debug('starting LCM - binding events')
        for i in [self.GetParent().button_configure,
                  self.GetParent().button_defaults,
                  self.GetParent().button_run]:
            i.Disable()
        
        pass

    def OnThreadEnd(self, thread):
        log.debug('LCM ended - unbinding events')
        self.gauge.SetValue(0)
        for i in [self.GetParent().button_configure,
                  self.GetParent().button_defaults,
                  self.GetParent().button_run]:
            i.Enable()

class ClosableWindow:
    def __init__(self, *argv, **kwargs):
        self.button_close.Bind(wx.EVT_BUTTON, self.onExit)

    def onExit(self, event):
        self.Close(True)  # Close this frame.

class LCMDialog(program_wxglade.LCMDialog, ClosableWindow):
    def __init__(self, *argv, **kwargs):
        program_wxglade.LCMDialog.__init__(self, *argv, **kwargs)
        ClosableWindow.__init__(self, *argv, **kwargs)
        self.button_run.Bind(wx.EVT_BUTTON, self.OnRun)
        self.running_dialog = RunningDialog(parent=self)
        
    def OnRun(self, event):
        self.running_dialog.Show()
        mainThread = nens.swx.MainThread(
            dialog = self.running_dialog,
            target = the_program.main,
            args = (None, [self.text_ctrl_name_configuration.GetValue()])
            )
        mainThread.start()

    def chooseConfiguration(self, event):
        dialog = wx.FileDialog(self, message="choose configuration file", 
defaultDir=os.getcwd(),
                               wildcard="Windows *.ini|*.ini|All files 
(*.*)|*.*")
        if dialog.ShowModal() == wx.ID_OK:
            self.text_ctrl_name_configuration.SetValue(dialog.GetPath())
        dialog.Destroy()

    def onExit(self, event):
        self.Close(True)  # Close this frame.
        exit() # and exit

class ConfigDialog(program_wxglade.ConfigDialog, ClosableWindow):
    pass

class DefaultsDialog(program_wxglade.DefaultsDialog):
    pass

if __name__ == "__main__":
    import gettext
    gettext.install("app") # replace with the appropriate catalog name

    app = wx.PySimpleApp(0)
    wx.InitAllImageHandlers()
    program_dialog = LCMDialog(None, -1, "")
    app.SetTopWindow(program_dialog)
    program_dialog.Show()
    app.MainLoop()
--- end ---

--- program_wxglade.py (the interface) ---
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# generated by wxGlade 0.6.3 on Tue Aug 25 10:57:18 2009

import wx
import wx.grid

# begin wxGlade: extracode
# end wxGlade



class LCMDialog(wx.Dialog):
    def __init__(self, *args, **kwds):
        # begin wxGlade: LCMDialog.__init__
        kwds["style"] = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.THICK_FRAME
        wx.Dialog.__init__(self, *args, **kwds)
        self.vbox_33_copy_staticbox = wx.StaticBox(self, -1, _("current 
configuration file"))
        self.button_configure = wx.Button(self, -1, _("configure"))
        self.button_defaults = wx.Button(self, -1, _("defaults"))
        self.button_new_actions = wx.Button(self, -1, _("new actions"))
        self.button_run = wx.Button(self, -1, _("run"))
        self.button_close = wx.Button(self, -1, _("close"))
        self.text_ctrl_name_configuration = wx.TextCtrl(self, -1, "")
        self.button_choose = wx.Button(self, -1, _("..."))
        self.label_1 = wx.StaticText(self, -1, _("last log and next run hints"))
        self.text_ctrl_2 = wx.TextCtrl(self, -1, "", 
style=wx.TE_MULTILINE|wx.HSCROLL)
        self.text_ctrl_3 = wx.TextCtrl(self, -1, "", 
style=wx.TE_MULTILINE|wx.HSCROLL)
        self.label_2 = wx.StaticText(self, -1, _("idle"))

        self.__set_properties()
        self.__do_layout()
        # end wxGlade

    def __set_properties(self):
        # begin wxGlade: LCMDialog.__set_properties
        self.SetTitle(_("LCM : Lizard Configuration Manager"))
        self.SetSize((534, 370))
        self.text_ctrl_name_configuration.SetMinSize((0, 24))
        self.button_choose.SetMinSize((24, 24))
        self.label_2.Enable(False)
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: LCMDialog.__do_layout
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
        vbox_33_copy = wx.StaticBoxSizer(self.vbox_33_copy_staticbox, 
wx.VERTICAL)
        hbox_311_copy = wx.BoxSizer(wx.HORIZONTAL)
        sizer_2 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_2.Add(self.button_configure, 0, 0, 0)
        sizer_2.Add((10, 20), 0, wx.EXPAND, 0)
        sizer_2.Add(self.button_defaults, 0, 0, 0)
        sizer_2.Add((10, 20), 0, wx.EXPAND, 0)
        sizer_2.Add(self.button_new_actions, 0, 0, 0)
        sizer_2.Add((10, 20), 0, wx.EXPAND, 0)
        sizer_2.Add(self.button_run, 0, 0, 0)
        sizer_2.Add((20, 20), 1, wx.EXPAND, 0)
        sizer_2.Add(self.button_close, 0, 0, 0)
        sizer_1.Add(sizer_2, 0, wx.EXPAND, 0)
        hbox_311_copy.Add(self.text_ctrl_name_configuration, 3, 0, 0)
        hbox_311_copy.Add(self.button_choose, 0, 0, 0)
        vbox_33_copy.Add(hbox_311_copy, 0, wx.EXPAND, 0)
        sizer_1.Add(vbox_33_copy, 0, wx.EXPAND, 0)
        sizer_1.Add(self.label_1, 0, 0, 0)
        sizer_3.Add(self.text_ctrl_2, 2, wx.EXPAND, 0)
        sizer_3.Add(self.text_ctrl_3, 1, wx.EXPAND, 0)
        sizer_1.Add(sizer_3, 1, wx.EXPAND, 0)
        sizer_1.Add(self.label_2, 0, wx.ALL, 2)
        self.SetSizer(sizer_1)
        self.Layout()
        # end wxGlade

# end of class LCMDialog


class ConfigDialog(wx.Dialog):
    def __init__(self, *args, **kwds):
        # begin wxGlade: ConfigDialog.__init__
        kwds["style"] = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.THICK_FRAME
        wx.Dialog.__init__(self, *args, **kwds)
        self.vbox_33_staticbox = wx.StaticBox(self, -1, _("other settings"))
        self.vbox_23_staticbox = wx.StaticBox(self, -1, _("base directories"))
        self.button_revert = wx.Button(self, -1, _("revert"))
        self.button_save = wx.Button(self, -1, _("save"))
        self.button_close = wx.Button(self, -1, _("close"))
        self.label_configuration = wx.StaticText(self, -1, _("configuration"))
        self.text_ctrl_configuration = wx.TextCtrl(self, -1, "")
        self.button_configuration_choose = wx.Button(self, -1, _("..."))
        self.label_locations = wx.StaticText(self, -1, _("locations"))
        self.text_ctrl_locations = wx.TextCtrl(self, -1, "")
        self.button_locations_choose = wx.Button(self, -1, _("..."))
        self.label_lp_pairs = wx.StaticText(self, -1, _("lp pairs"))
        self.text_ctrl_lp_pairs = wx.TextCtrl(self, -1, "")
        self.button_lp_pairs_choose = wx.Button(self, -1, _("..."))
        self.label_output = wx.StaticText(self, -1, _("output"))
        self.text_ctrl_output = wx.TextCtrl(self, -1, "")
        self.button_output_choose = wx.Button(self, -1, _("..."))
        self.label_status_dir = wx.StaticText(self, -1, _("status dir"))
        self.text_ctrl_status_dir = wx.TextCtrl(self, -1, "")
        self.button_status_dir_choose = wx.Button(self, -1, _("..."))
        self.label_loglevel = wx.StaticText(self, -1, _("logging level"))
        self.choice_loglevel = wx.Choice(self, -1, choices=[_("NOTSET"), 
_("DEBUG"), _("INFO"), _("WARNING"), _("ERROR")])

        self.__set_properties()
        self.__do_layout()
        # end wxGlade

    def __set_properties(self):
        # begin wxGlade: ConfigDialog.__set_properties
        self.SetTitle(_("config.ini editor"))
        self.label_configuration.SetMinSize((90, 16))
        self.text_ctrl_configuration.SetMinSize((0, 24))
        self.button_configuration_choose.SetMinSize((24, 24))
        self.label_locations.SetMinSize((90, 16))
        self.text_ctrl_locations.SetMinSize((0, 24))
        self.button_locations_choose.SetMinSize((24, 24))
        self.label_lp_pairs.SetMinSize((90, 16))
        self.text_ctrl_lp_pairs.SetMinSize((0, 24))
        self.button_lp_pairs_choose.SetMinSize((24, 24))
        self.label_output.SetMinSize((90, 16))
        self.text_ctrl_output.SetMinSize((0, 24))
        self.button_output_choose.SetMinSize((24, 24))
        self.label_status_dir.SetMinSize((90, 16))
        self.text_ctrl_status_dir.SetMinSize((0, 24))
        self.button_status_dir_choose.SetMinSize((24, 24))
        self.label_loglevel.SetMinSize((90, 16))
        self.choice_loglevel.SetSelection(0)
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: ConfigDialog.__do_layout
        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox_33 = wx.StaticBoxSizer(self.vbox_33_staticbox, wx.VERTICAL)
        hbox_311 = wx.BoxSizer(wx.HORIZONTAL)
        vbox_23 = wx.StaticBoxSizer(self.vbox_23_staticbox, wx.VERTICAL)
        hbox_255 = wx.BoxSizer(wx.HORIZONTAL)
        hbox_245 = wx.BoxSizer(wx.HORIZONTAL)
        hbox_235 = wx.BoxSizer(wx.HORIZONTAL)
        hbox_225 = wx.BoxSizer(wx.HORIZONTAL)
        hbox_215 = wx.BoxSizer(wx.HORIZONTAL)
        hbox_13 = wx.BoxSizer(wx.HORIZONTAL)
        hbox_13.Add(self.button_revert, 0, 0, 0)
        hbox_13.Add((10, 20), 0, wx.EXPAND, 0)
        hbox_13.Add(self.button_save, 0, 0, 0)
        hbox_13.Add((20, 20), 1, wx.EXPAND, 0)
        hbox_13.Add(self.button_close, 0, 0, 0)
        vbox.Add(hbox_13, 0, wx.EXPAND, 0)
        hbox_215.Add(self.label_configuration, 0, 0, 0)
        hbox_215.Add(self.text_ctrl_configuration, 3, 0, 0)
        hbox_215.Add(self.button_configuration_choose, 0, 0, 0)
        vbox_23.Add(hbox_215, 0, wx.EXPAND, 0)
        hbox_225.Add(self.label_locations, 0, 0, 0)
        hbox_225.Add(self.text_ctrl_locations, 3, 0, 0)
        hbox_225.Add(self.button_locations_choose, 0, 0, 0)
        vbox_23.Add(hbox_225, 0, wx.EXPAND, 0)
        hbox_235.Add(self.label_lp_pairs, 0, 0, 0)
        hbox_235.Add(self.text_ctrl_lp_pairs, 3, 0, 0)
        hbox_235.Add(self.button_lp_pairs_choose, 0, 0, 0)
        vbox_23.Add(hbox_235, 0, wx.EXPAND, 0)
        hbox_245.Add(self.label_output, 0, 0, 0)
        hbox_245.Add(self.text_ctrl_output, 3, 0, 0)
        hbox_245.Add(self.button_output_choose, 0, 0, 0)
        vbox_23.Add(hbox_245, 0, wx.EXPAND, 0)
        hbox_255.Add(self.label_status_dir, 0, 0, 0)
        hbox_255.Add(self.text_ctrl_status_dir, 3, 0, 0)
        hbox_255.Add(self.button_status_dir_choose, 0, 0, 0)
        vbox_23.Add(hbox_255, 0, wx.EXPAND, 0)
        vbox.Add(vbox_23, 0, wx.EXPAND, 0)
        hbox_311.Add(self.label_loglevel, 0, 0, 0)
        hbox_311.Add(self.choice_loglevel, 1, wx.EXPAND, 0)
        vbox_33.Add(hbox_311, 0, wx.EXPAND, 0)
        vbox.Add(vbox_33, 1, wx.EXPAND, 0)
        self.SetSizer(vbox)
        vbox.Fit(self)
        self.Layout()
        # end wxGlade

# end of class ConfigDialog


class DefaultsDialog(wx.Dialog):
    def __init__(self, *args, **kwds):
        # begin wxGlade: DefaultsDialog.__init__
        kwds["style"] = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.THICK_FRAME
        wx.Dialog.__init__(self, *args, **kwds)
        self.grid_1 = wx.grid.Grid(self, -1, size=(1, 1))

        self.__set_properties()
        self.__do_layout()
        # end wxGlade

    def __set_properties(self):
        # begin wxGlade: DefaultsDialog.__set_properties
        self.SetTitle(_("defaults editor"))
        self.SetSize((544, 255))
        self.grid_1.CreateGrid(1, 3)
        self.grid_1.EnableGridLines(0)
        self.grid_1.EnableDragColSize(0)
        self.grid_1.EnableDragRowSize(0)
        self.grid_1.SetSelectionMode(wx.grid.Grid.wxGridSelectRows)
        self.grid_1.SetColLabelValue(0, _("par. id"))
        self.grid_1.SetColSize(0, 4)
        self.grid_1.SetColLabelValue(1, _("softmax"))
        self.grid_1.SetColLabelValue(2, _("softmin"))
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: DefaultsDialog.__do_layout
        sizer_8 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_8.Add(self.grid_1, 1, wx.EXPAND, 0)
        self.SetSizer(sizer_8)
        self.Layout()
        # end wxGlade

# end of class DefaultsDialog


class RunningDialog(wx.Dialog):
    def __init__(self, *args, **kwds):
        # begin wxGlade: RunningDialog.__init__
        kwds["style"] = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.THICK_FRAME
        wx.Dialog.__init__(self, *args, **kwds)
        self.text_ctrl_logging = wx.TextCtrl(self, -1, "", 
style=wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL|wx.TE_RICH)
        self.gauge = wx.Gauge(self, -1, 250)

        self.__set_properties()
        self.__do_layout()
        # end wxGlade

    def __set_properties(self):
        # begin wxGlade: RunningDialog.__set_properties
        self.SetTitle(_("console"))
        self.SetSize((600, 300))
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: RunningDialog.__do_layout
        sizer_4 = wx.BoxSizer(wx.VERTICAL)
        sizer_4.Add(self.text_ctrl_logging, 1, wx.EXPAND, 0)
        sizer_4.Add(self.gauge, 0, wx.EXPAND, 0)
        self.SetSizer(sizer_4)
        self.Layout()
        # end wxGlade

# end of class RunningDialog


if __name__ == "__main__":
    import gettext
    gettext.install("app") # replace with the appropriate catalog name

    app = wx.PySimpleApp(0)
    wx.InitAllImageHandlers()
    dialog_lcm = LCMDialog(None, -1, "")
    app.SetTopWindow(dialog_lcm)
    dialog_lcm.Show()
    app.MainLoop()
--- end ---

--- the_program.py ---
# just for the sake of testing...

def main(options, args):
    import time
    for i in range(33):
        log.warning('this is warning #%d' % i)
        for j in range(10):
            log.info('and this is informational message #%d' % j)
        time.sleep(0.1)
--- end ---

--- wsx (my library) --
#***********************************************************************
#* Library    : for the lazy interface builder
#*               
#* Project    : various
#*  
#* $Id: gp.py 7710 2009-08-17 08:14:18Z Mario $
#*
#* initial programmer :  Mario Frasca
#* initial date       :  2009-08-20
#**********************************************************************

__revision__ = "$Rev: 7710 $"[6:-2]

import logging, wx, threading
log = logging.getLogger('nens.swx')
log.setLevel(logging.INFO)

class TextCtrlHandler(logging.Handler):
    '''emits formatted records to a wx.TextCtrl widget

    the widget must be...
    style=wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL|wx.TE_RICH

    logging records will be gray (DEBUG), black (INFO) or red (WARNING/ERROR).

    changing the content of the widget once you have given it to this
    object will crash your program.  you may wipe it clean using the
    ClearWindow method.

    NB: this object can crash your Linux program
    '''

    def __init__(self, widget, **kwargs):
        logging.Handler.__init__(self, **kwargs)
        self.widget = widget
        self.semaphore = threading.Semaphore()

    def emit(self, record):
        if record.levelno >= logging.WARNING:
            styleForLevel = wx.TextAttr("red")
        elif record.levelno >= logging.INFO:
            styleForLevel = wx.TextAttr("black")
        else:
            styleForLevel = wx.TextAttr("grey")
        self.semaphore.acquire()
        self.widget.SetDefaultStyle(styleForLevel)

        self.widget.AppendText(self.format(record))
        self.widget.AppendText('\n')
        self.semaphore.release()

    def ClearWindow(self):
        "empty the owned widget"
        self.semaphore.acquire()
        self.widget.SetValue('')
        self.semaphore.release()
        

class MainThread(threading.Thread):
    '''Thread class taking care of disabling/enabling the convert and
    close buttons...

    a dialog box may be given and its OnThreadStart and OnThreadEnd
    methods will be called when the thread is actually run.'''
    
    def __init__(self, dialog=None, *args, **kwargs):
        self.dialog = dialog
        threading.Thread.__init__(self, *args, **kwargs)
        
    def run(self, *args, **kwargs):
        try:
            #print "self.dialog.OnThreadStart(self)"
            self.dialog.OnThreadStart(self)
        except Exception, e:
            #print e
            pass

        try:
            #print "threading.Thread.run(self, *args, **kwargs)"
            threading.Thread.run(self, *args, **kwargs)
        except:
            import traceback
            log.error("a serious error occurred in the main thread (INFO 
follows)")
            log.info(traceback.format_exc())

        try:
            #print "self.dialog.OnThreadEnd(self)"
            self.dialog.OnThreadEnd(self)
        except Exception, e:
            #print e
            pass
--- end ---

-- 
Windows: A thirty-two bit extension to a sixteen-bit graphical shell to an
eight-bit operating system originally coded for a four-bit microprocessor,
sold by a two-bit company that can't stand one bit of competition.



-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to