[wxPython] wxHTML and catching EVT_CHAR

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[wxPython] wxHTML and catching EVT_CHAR

Stuart Stanley

I have been trying to get my html window (or the frame that holds it,
I am not picky here :) to catch the EVT_CHAR event.  I have had very
little luck.  The whole thing is pretty close to the demo, except the
parent is a frame instead of a panel.

I have tried doing the following:
        o setting focus in the Frame or the html window.  No affect.
        o making a frame with a window inside that.  I can now catch the
                event in the HTML window, but the there is nothing on
                the screen (inside the window).
        o tried running without any embedded widgets in the html.

I have included the code below.  It's a little icky, since this was my
first stab at the html code.  Any clues would helpfull!


import sys, os

from wxPython.wx import *
from wxPython.html import *
import re
import wxPython.lib.wxpTag
import tempfile

class MyHtmlWindow(wxHtmlWindow):
        def __init__(self, parent, id, resource_map):
                wxHtmlWindow.__init__(self, parent, id)
                self._resource_map = resource_map
                EVT_CHAR(self, self._OnChar)

        def _OnChar(self, event):
                print "html event", event

        def LoadPage(self, fname):
                """
                Grab virtual and do string subs on the target file...
                """
                f2n = tempfile.mktemp()+".html"
                f1 = open(fname, "r")
                strdata = f1.read()
                f1.close()
                # XXX ${} inside another ${} is undefined!
                for x in self._resource_map:
                        strdata = x[0].sub(x[1], strdata)
                f2 = open(f2n, "w")
                f2.write(strdata)
                f2.close()
                wxHtmlWindow.LoadPage(self, f2n)

#
# ARGH.  Nasty hack alert.  We need to tie back our checkpoint item to
# the class instance, but the information gets lost in the html tag
# generation.  One would think a FindByID() would do the trick, but it
# returns a wxWindow, NOT the derived class we are using. fark.  So, we
# go hack city here and move the list of box information outside the class
# into module global land.  That way the main app can search for us.  Yuck.
# To make matters worse, the items may be "out of scope" and thus not
# valid.  Because of this, you still need to do the window search to
# make sure everything is valid and THEN reference this for the actual
# ptr!

_my_CheckPoint_panels = {}
class _my_CheckPoint(wxPanel):
        box_list = {}
        def __init__(self, parent, size, label, id, choices, text, comment =
None):
                # Note, overide label with text.  I am keeping them
                # as seperate params "just in case".
                label = text
                if self.box_list.has_key(id):
                        # object already exists!
                        if comment:
                                comment_text = self.box_list[id][1]
                        else:
                                comment_text = ""
                        radio_setting = self.box_list[id][0]
                else:
                        comment_text = ""
                        radio_setting = 0

                wxPanel.__init__(self, parent, id, style = wxSIMPLE_BORDER,
                        size = size)
                box = wxBoxSizer(wxVERTICAL)
                self._radio = wxRadioBox(self, -1, label, LIST = choices,
                        style = wxRA_SPECIFY_ROWS )
                EVT_RADIOBOX(self, self._radio.GetId(), self.OnRadioChange)
                self._radio.SetSelection(radio_setting)
                box.Add(self._radio, 0, wxGROW)

                self._has_comment = comment
                self._label = label

                if comment:
                        self._comment = wxTextCtrl(self, -1,
                                value = comment_text )
                        bbox = wxBoxSizer(wxHORIZONTAL)
                        self._static = wxStaticText(self, -1, "Comment:")
                        bbox.Add(self._static, 0, wxALIGN_LEFT )
                        bbox.Add(self._comment, 1, wxGROW)
                        box.Add(bbox, 1, wxGROW)
                        cs = self._comment.GetSizeTuple()
                        EVT_TEXT(self, self._comment.GetId(),
                                self.OnCommentChange)
                else:
                        cs = (0,0)
                self.SetSizer(box)
                self.SetAutoLayout(true)
                rs = self._radio.GetSizeTuple()
                ns = ( cs[0], cs[1] + rs[1] )
                self.SetSize(ns)
                self._id = id
                self.box_list[id] = [radio_setting, comment_text]
                _my_CheckPoint_panels[id] = self

        def IsReportable(self):
                if self._has_comment:
                        return 1
                return 0

        def GetLabel(self):
                return self._label

        def OnRadioChange(self, event):
                self.box_list[self._id][0] = self._radio.GetSelection()

        def OnCommentChange(self, event):
                self.box_list[self._id][1] = self._comment.GetValue()

        def GetRadioSelection(self):
                return self._radio.GetSelection()

        def GetRadioStringSelection(self):
                return self._radio.GetStringSelection()

        def GetCommentValue(self):
                return self._comment.GetValue()

        def SetRadioSelection(self, value):
                self._radio.SetSelection(value)
                self.OnRadioChange(None)

class manualTestFrame(wxFrame):
        def __init__(self, parent, title, base_name, resources, tet):
                wxFrame.__init__(self, parent, -1, title, wxDefaultPosition,
                        wxSize(800,500), style = wxWANTS_CHARS)
#class manualTestFrame(wxFrame):
# def __init__(self, parent, title, base_name, resources, tet):
# wxFrame.__init__(self, parent, -1, title, wxDefaultPosition,
# wxSize(800,500), style = wxWANTS_CHARS)
# self.SetAutoLayout(true)
# self._window = manualTestWindow(self, title, base_name,
# resources, tet)

#class manualTestWindow(wxWindow):
# def __init__(self, parent, title, base_name, resources, tet):
# wxWindow.__init__(self, parent, -1, wxDefaultPosition,
# style = wxWANTS_CHARS)
                # save tet.
                self._tet = tet
                #  Ok, read in the first file, with button parsing
                self._base_string, self._steps_data = \
                        self._parse_button_file(base_name, resources)

                # our resources are a key list ({"x":y}) style.  We want
                # to turn this in re compiles so that we can just blast
                # anything we load.
                cres = []
                for key in resources.keys():
                        srch = "\$\{"+key+"\}"
                        cres.append((re.compile(srch), resources[key]))
                self._resources = cres

                # Make html area
                self._html = MyHtmlWindow(self, -1, self._resources)
# self._html.SetRelatedFrame(parent, title)
                self._html.SetRelatedFrame(self, title)
                self._html.SetRelatedStatusBar(0)

                self._box = wxBoxSizer(wxVERTICAL)
                self._box.Add(self._html, 1, wxGROW)

                subbox = wxBoxSizer(wxHORIZONTAL)
                base_bid = NewId()
                back_bid = NewId()
                forward_bid = NewId()
                done_bid = NewId()
                pass_all_bid = NewId()
                fail_all_bid = NewId()
                abort_bid = NewId()

                EVT_CLOSE(self, self._OnClose)
                EVT_CHAR(self, self._OnChar)
                btn = wxButton(self, base_bid, "Home")
                EVT_BUTTON(self, base_bid, self.OnBackToBase)
                subbox.Add(btn, 1, wxGROW | wxALL, 2)

                btn = wxButton(self, back_bid, "Back")
                EVT_BUTTON(self, back_bid, self.OnBack)
                subbox.Add(btn, 1, wxGROW | wxALL, 2)

                btn = wxButton(self, forward_bid, "Forward")
                EVT_BUTTON(self, forward_bid, self.OnForward)
                subbox.Add(btn, 1, wxGROW | wxALL, 2)

                btn = wxButton(self, done_bid, "Done")
                EVT_BUTTON(self, done_bid, self.OnDone)
                subbox.Add(btn, 1, wxGROW | wxALL, 2)

                btn = wxButton(self, pass_all_bid, "Pass rest")
                EVT_BUTTON(self, pass_all_bid, self.OnPassAll)
                subbox.Add(btn, 1, wxGROW | wxALL, 2)

                btn = wxButton(self, fail_all_bid, "Fail rest")
                EVT_BUTTON(self, fail_all_bid, self.OnFailAll)
                subbox.Add(btn, 1, wxGROW | wxALL, 2)

                btn = wxButton(self, abort_bid, "Abort")
                EVT_BUTTON(self, abort_bid, self.OnAbort)
                subbox.Add(btn, 1, wxGROW | wxALL, 2)

                self._box.Add(subbox, 0, wxGROW)
                self.SetSizer(self._box)
                self.SetAutoLayout(true)
                fname = tempfile.mktemp()+".html"
                self._base_tmp_fname = fname
                ffile = open(fname, "w" )
                ffile.write(self._base_string)
                ffile.close()
                self._OpenFile(fname)
                self._tet_written = 0
                self.SetFocus()

        def OnCharHook(self, event):
                # Gotta a character.  We care about up arrow, down
                # arrow, pageup, pagedown, home and end.
                print event
        def _OnChar(self, event):
                # Gotta a character.  We care about up arrow, down
                # arrow, pageup, pagedown, home and end.
                print event

        def _OnClose(self, event):
                if not self._tet_written:
                        self._DoAbort()
                self.Destroy()

        def _OpenFile(self, fname):
                self._html.LoadPage(fname)

        def OnBackToBase(self, event):
                self._OpenFile(self._base_tmp_fname )

        def OnBack(self, event):
                if not self._html.HistoryBack():
                        wxMessageBox("No more items in history!")
               
        def OnForward(self, event):
                if not self._html.HistoryForward():
                        wxMessageBox("No more items in history!")

        def OnDone(self, event):
                tried = 0
                fnd = 0
                unfin = 0
                items = []
                for x in self._steps_data:
                        tried = tried + 1
                        win = self.FindWindowById(x["id"])
                        if win:
                                win = _my_CheckPoint_panels[x["id"]]
                                items.append(win)
                                if win.IsReportable() and
win.GetRadioSelection() == 0:
                                        unfin = unfin + 1
                                fnd = fnd + 1
                if fnd != tried:
                        dlg = wxMessageDialog(self,
                                'This can only done from the Home window',
                                'Not at home', wxOK | wxICON_INFORMATION)
                        dlg.ShowModal()
                        dlg.Destroy()
                        return

                if unfin > 0:
                        dlg = wxMessageDialog(self,
                                'There are %d unfinished test purposes. \nAre
you sure you want to do this?'%(unfin),
                                'Not done yet.', wxYES_NO | wxICON_QUESTION)
                        res = dlg.ShowModal()
                        dlg.Destroy()
                        if res == wxID_NO:
                                return

                for x in items:
                        if x.IsReportable():
                                ds = x.GetCommentValue()
                                self._tet.tp_start(x.GetLabel())
                                res = x.GetRadioSelection()
                                if res == 1:
                                        # pass!
                                        self._tet.tp_end(ds,
                                                self._tet.results.Pass)
                                elif res == 2:
                                        # fail
                                        self._tet.tp_end(ds,
                                                self._tet.results.Fail)
                                else:
                                        # untested
                                        self._tet.tp_end(ds,
                                                self._tet.results.Untested)
                self._tet_written = 1
                self.Close()
                       
                       
        def _sweep_for_all(self, setto):
                tried = 0
                fnd = 0
                for x in self._steps_data:
                        tried = tried + 1
                        win = self.FindWindowById(x["id"])
                        if win:
                                win = _my_CheckPoint_panels[x["id"]]
                                if win.GetRadioSelection() == 0:
                                        win.SetRadioSelection(x[setto])
                                fnd = fnd + 1

                if fnd != tried:
                        dlg = wxMessageDialog(self,
                                'This can only done from the Home window',
                                'Not at home', wxOK | wxICON_INFORMATION)
                        dlg.ShowModal()
                        dlg.Destroy()
                else:
                        self.OnDone(None)

        def OnPassAll(self, event):
                self._sweep_for_all("change_to_pass")

        def OnFailAll(self, event):
                self._sweep_for_all("change_to_fail")
               
        def _DoAbort(self):
                items = []
                for x in self._steps_data:
                        win = self.FindWindowById(x["id"])
                        if win:
                                win = _my_CheckPoint_panels[x["id"]]
                                if win.IsReportable():
                                        items.append(win)

                for x in items:
                        ds = x.GetCommentValue()
                        self._tet.tp_start(x.GetLabel())
                        self._tet.tp_end(ds, self._tet.results.Abort)
                self._tet_written = 1
                       
        def OnAbort(self, event):
                dlg = wxMessageDialog(self,
                        'Are you sure you want to abort?',
                        'To be or not to be.', wxYES_NO | wxICON_QUESTION)
                res = dlg.ShowModal()
                dlg.Destroy()
                if res == wxID_NO:
                        return
                self._DoAbort()
                self.Close()

        def _make_test(self, text):
                """
                Build up a "test" entry element.  This means making
                a radio buttin that holds a "pass", "fail", "untested".
                """
                our_id = NewId()
                cstr = "['Untested', 'Pass', 'Fail']"
                vstr = 'value="%d"' % ( our_id )
                tstr = 'value="%s"' % ( text )
                estr = '<center><wxp module="manualtest" class="_my_CheckPoint"
width="100%">' + \
                        '<param name="label" value="TET test purpose">' + \
                        '<param name="id" ' + vstr + '>' + \
                        '<param name="choices" value="'+cstr+'">' + \
                        '<param name="comment" value="true">' + \
                        '<param name="text" ' + tstr + '>' + \
                        '</wxp></center>'
                element = { "id":our_id, "change_to_pass":1,
"change_to_fail":2}
                return element, estr

        def _make_setup(self, text):
                """
                Build up a "step" entry element.  This means making
                a radio button that has untested and tested.
                ID
                """
                our_id = NewId()
                tstr = 'value="%s"' % ( text )
                cstr = "['Not done', 'Done']"
                vstr = 'value="%d"' % ( our_id )
                estr = '<center><wxp module="manualtest" class="_my_CheckPoint"
width="100%">' + \
                        '<param name="label" value="Setup step (not a TP)">' +
\
                        '<param name="id" ' + vstr + '>' + \
                        '<param name="choices" value="'+cstr+'">' + \
                        '<param name="text" ' + tstr + '>' + \
                        '</wxp></center>'
                element = { "id":our_id, "change_to_pass":1,
"change_to_fail":0}
                return element, estr

        def _parse_button_file(self, fname, resources):
                """
                Method to take first level file, locate our special
                take elements for steps in the process and:
                        1) modify the html text to include a widget for
                           this button.
                        2) save off info about this one so we can match
                           it when the button is hit.
                """

                fd = open(fname, "r")
                fdata = fd.read()
               
                steps = []
                bs = ""
                finder = re.compile("\[(TEST):(.*)\]|\[(SETUP):(.*)\]")
                leftover = 0
                m = finder.search(fdata)
                while m:
                        # build info for button
                        fnd = m.groups()
                        if m.group(1):
                                element, estr = self._make_test(m.group(2))
                        else:
                                element, estr = self._make_setup(m.group(4))
                       
                        bs = bs + fdata[leftover:m.start()] + estr
                       
                        leftover = m.end()
                        m = finder.search(fdata, leftover)
                        steps.append(element)

                bs = bs + fdata[leftover:]
                return bs, steps

 On the side of the software box, in the "System | | Stuart Stanley
 Stuart Stanley Requirements" section, it said     | [hidden email]
 "Requires Windows | [hidden email] 95 or      | Lucent Technologies,
 better". So I installed Linux. | Lucent           | Eden Prairie, MN
 Technologies, | Eden Prairie, MN | 612.996.6829   | 612.996.6829



_______________________________________________
wxPython-users maillist  -  [hidden email]
http://starship.python.net/mailman/listinfo/wxpython-users



Reply | Threaded
Open this post in threaded view
|

Re: [wxPython] wxHTML and catching EVT_CHAR

Robin Dunn


>
> I have been trying to get my html window (or the frame that holds it,
> I am not picky here :) to catch the EVT_CHAR event.  I have had very
> little luck.  The whole thing is pretty close to the demo, except the
> parent is a frame instead of a panel.
>
> I have tried doing the following:
> o setting focus in the Frame or the html window.  No affect.
> o making a frame with a window inside that.  I can now catch the
> event in the HTML window, but the there is nothing on
> the screen (inside the window).
> o tried running without any embedded widgets in the html.
>

Did you try creating the wxHtmlWindow with the wxWANTS_CHARS flag?  You might
also try giving the frame an EVT_SET_FOCUS event handler and calling the html
window's SetFocus from within it.

It's hard to tell from the code below (my mailer eats leading tabs!) but
probably the reason the html window didn't show up when it was within another
wxWindow is that other window needs to manage it's size, either with a sizer
or something, or explicitly setting it in an OnSize.  But then if the above
suggestion works you won't need it anyway.

--
Robin Dunn
Software Craftsman
[hidden email]
http://AllDunn.com/robin/
http://AllDunn.com/wxPython/  Check it out!




_______________________________________________
wxPython-users maillist  -  [hidden email]
http://starship.python.net/mailman/listinfo/wxpython-users