problem with GetToolTip

Hello all,

Happy New Year !

I've got a class derived from wx.TextCtrl providing
AutoCompletion and lots of other nifty features.

  http://gitorious.org/gnumed/gnumed/blobs/master/gnumed/gnumed/client/wxpython/gmPhraseWheel.py

I am now adding dynamic tooltips which change with what has
currently been selected. For that I am attempting to
determine whether a tooltip has been pre-set from elsewhere
with self.ToolTip. This fails on me with:

2011-01-04 12:28:57 ERROR gm.ui (/home/ncq/Projekte/gm-git/gnumed/gnumed/Gnumed/wxpython/gmHorstSpace.py::__load_plugins() #127): failed to load plugin gmDataMiningPlugin
Traceback (most recent call last):
  File "/home/ncq/Projekte/gm-git/gnumed/gnumed/Gnumed/wxpython/gmHorstSpace.py", line 121, in __load_plugins
    plugin.register()
  File "/home/ncq/Projekte/gm-git/gnumed/gnumed/Gnumed/wxpython/gmPlugin.py", line 79, in register
    widget = self.GetWidget(nb)
  File "/home/ncq/Projekte/gm-git/gnumed/gnumed/Gnumed/wxpython/gui/gmDataMiningPlugin.py", line 25, in GetWidget
    self._widget = gmDataMiningWidgets.cDataMiningPnl(parent, -1)
  File "/home/ncq/Projekte/gm-git/gnumed/gnumed/Gnumed/wxpython/gmDataMiningWidgets.py", line 141, in __init__
    wxgDataMiningPnl.wxgDataMiningPnl.__init__(self, *args, **kwargs)
  File "/home/ncq/Projekte/gm-git/gnumed/gnumed/Gnumed/wxGladeWidgets/wxgDataMiningPnl.py", line 18, in __init__
    self._PRW_report_name = gmPhraseWheel.cPhraseWheel(self.splitter_top_panel, -1, "", style=wx.NO_BORDER)
  File "/home/ncq/Projekte/gm-git/gnumed/gnumed/Gnumed/wxpython/gmPhraseWheel.py", line 235, in __init__
    self.data = None
  File "/home/ncq/Projekte/gm-git/gnumed/gnumed/Gnumed/wxpython/gmPhraseWheel.py", line 720, in _set_data
    data_tt = self.__get_data_tooltip()
  File "/home/ncq/Projekte/gm-git/gnumed/gnumed/Gnumed/wxpython/gmPhraseWheel.py", line 695, in __get_data_tooltip
    if self.ToolTip is None:
  File "/usr/lib/python2.6/dist-packages/wx-2.8-gtk2-unicode/wx/_core.py", line 10467, in GetToolTip
    return _core_.Window_GetToolTip(*args, **kwargs)
TypeError: in method 'Window_GetToolTip', expected argument 1 of type 'wxWindow const *'

I do not understand why because the following snippet works
as expected:

import wx

class PRW(wx.TextCtrl):
  def print_tt(self):
    if self.ToolTip is None:
      print "no tooltip"
    print self.ToolTip

app = wx.App()
prw = PRW(None, -1)
prw.SetToolTipString('abc')
prw.print_tt()

The code in question goes like this:

class cPhraseWheel(wx.TextCtrl):

  def __init__ (self, parent=None, id=-1, value='', *args, **kwargs):

    self.__static_tt = None
    self.data = None

    wx.TextCtrl.__init__(self, parent, id, **kwargs)

···

#--------------------------------------------------------
  def __get_data_tooltip(self):
    """Calculate dynamic tooltip part based on data item.

    - called via ._set_data() each time property .data (-> .__data) is set
    - hence also called the first time data is set
    - the static tooltip can be set any number of ways before that
    - only when data is first set does the dynamic part become relevent
    - hence it is sufficient to remember the static part when .data is
      set for the first time
    """
    if self.__static_tt is None:
      if self.ToolTip is None: **** here comes the exception ****
        self.__static_tt = u''
      else:
        self.__static_tt = self.ToolTip.Tip

    return self._get_data_tooltip()
  #--------------------------------------------------------
  def _get_data_tooltip(self):
    # by default do not support dynamic tooltip parts
    return None
  #--------------------------------------------------------
  # properties
  #--------------------------------------------------------
  def _get_data(self):
    return self.__data

  def _set_data(self, data):
    self.__data = data

    data_tt = self.__get_data_tooltip()
    if data_tt is None:
      return

    if self.__static_tt == u'':
      tt = data_tt
    else:
      if data_tt.strip() == u'':
        tt = self.__static_tt
      else:
        tt = u'%s\n\n--------------------------------\n\n%s' % (
          data_tt,
          self.__static_tt
        )
    self.SetToolTipString(tt)

  data = property(_get_data, _set_data)

Can anyone see what I am doing wrong ?

[ isinstance(self, wx.Window) returns True, of course ]

Karsten
--
GPG key ID E4071346 @ wwwkeys.pgp.net
E167 67FD A291 2BEA 73BD 4537 78B9 A9F9 E407 1346

The code in question goes like this:

class cPhraseWheel(wx.TextCtrl):

  def __init__ (self, parent=None, id=-1, value='', *args, **kwargs):

    self.__static_tt = None
    self.data = None

    wx.TextCtrl.__init__(self, parent, id, **kwargs)

  #--------------------------------------------------------
  def __get_data_tooltip(self):
    """Calculate dynamic tooltip part based on data item.

    - called via ._set_data() each time property .data (-> .__data) is set
    - hence also called the first time data is set
    - the static tooltip can be set any number of ways before that
    - only when data is first set does the dynamic part become relevent
    - hence it is sufficient to remember the static part when .data is
      set for the first time
    """
    if self.__static_tt is None:
      if self.ToolTip is None: **** here comes the exception ****
        self.__static_tt = u''
      else:
        self.__static_tt = self.ToolTip.Tip

    return self._get_data_tooltip()
  #--------------------------------------------------------
  def _get_data_tooltip(self):
    # by default do not support dynamic tooltip parts
    return None
  #--------------------------------------------------------
  # properties
  #--------------------------------------------------------
  def _get_data(self):
    return self.__data

  def _set_data(self, data):
    self.__data = data

    data_tt = self.__get_data_tooltip()
    if data_tt is None:
      return

    if self.__static_tt == u'':
      tt = data_tt
    else:
      if data_tt.strip() == u'':
        tt = self.__static_tt
      else:
        tt = u'%s\n\n--------------------------------\n\n%s' % (
          data_tt,
          self.__static_tt
        )
    self.SetToolTipString(tt)

  data = property(_get_data, _set_data)

One interesting observation is that when I move the tooltip
setting outside of the property setter (by means of
wx.CallAfter) it works as expected ...

   def _set_data(self, data):
     self.__data = data
    wx.CallAfter(self.__reset_tooltip)

   data = property(_get_data, _set_data)

  def __reset_tooltip(self):
     data_tt = self.__get_data_tooltip()
     if data_tt is None:
       return

     if self.__static_tt == u'':
       tt = data_tt
     else:
       if data_tt.strip() == u'':
         tt = self.__static_tt
       else:
         tt = u'%s\n\n--------------------------------\n\n%s' % (
           data_tt,
           self.__static_tt
         )
     self.SetToolTipString(tt)

Karsten

···

--
GPG key ID E4071346 @ wwwkeys.pgp.net
E167 67FD A291 2BEA 73BD 4537 78B9 A9F9 E407 1346

At the time the self.ToolTip property is evaluated the wx.TextCtrl.__init__ has not yet been called, so as far as the C++ wrapper code is concerned self is not a wx.TextCtrl (or a wx.Window) yet.

···

On 1/4/11 3:45 AM, Karsten Hilbert wrote:

Hello all,

Happy New Year !

I've got a class derived from wx.TextCtrl providing
AutoCompletion and lots of other nifty features.

  http://gitorious.org/gnumed/gnumed/blobs/master/gnumed/gnumed/client/wxpython/gmPhraseWheel.py

I am now adding dynamic tooltips which change with what has
currently been selected. For that I am attempting to
determine whether a tooltip has been pre-set from elsewhere
with self.ToolTip. This fails on me with:

2011-01-04 12:28:57 ERROR gm.ui (/home/ncq/Projekte/gm-git/gnumed/gnumed/Gnumed/wxpython/gmHorstSpace.py::__load_plugins() #127): failed to load plugin gmDataMiningPlugin
Traceback (most recent call last):
   File "/home/ncq/Projekte/gm-git/gnumed/gnumed/Gnumed/wxpython/gmHorstSpace.py", line 121, in __load_plugins
     plugin.register()
   File "/home/ncq/Projekte/gm-git/gnumed/gnumed/Gnumed/wxpython/gmPlugin.py", line 79, in register
     widget = self.GetWidget(nb)
   File "/home/ncq/Projekte/gm-git/gnumed/gnumed/Gnumed/wxpython/gui/gmDataMiningPlugin.py", line 25, in GetWidget
     self._widget = gmDataMiningWidgets.cDataMiningPnl(parent, -1)
   File "/home/ncq/Projekte/gm-git/gnumed/gnumed/Gnumed/wxpython/gmDataMiningWidgets.py", line 141, in __init__
     wxgDataMiningPnl.wxgDataMiningPnl.__init__(self, *args, **kwargs)
   File "/home/ncq/Projekte/gm-git/gnumed/gnumed/Gnumed/wxGladeWidgets/wxgDataMiningPnl.py", line 18, in __init__
     self._PRW_report_name = gmPhraseWheel.cPhraseWheel(self.splitter_top_panel, -1, "", style=wx.NO_BORDER)
   File "/home/ncq/Projekte/gm-git/gnumed/gnumed/Gnumed/wxpython/gmPhraseWheel.py", line 235, in __init__
     self.data = None
   File "/home/ncq/Projekte/gm-git/gnumed/gnumed/Gnumed/wxpython/gmPhraseWheel.py", line 720, in _set_data
     data_tt = self.__get_data_tooltip()
   File "/home/ncq/Projekte/gm-git/gnumed/gnumed/Gnumed/wxpython/gmPhraseWheel.py", line 695, in __get_data_tooltip
     if self.ToolTip is None:
   File "/usr/lib/python2.6/dist-packages/wx-2.8-gtk2-unicode/wx/_core.py", line 10467, in GetToolTip
     return _core_.Window_GetToolTip(*args, **kwargs)
TypeError: in method 'Window_GetToolTip', expected argument 1 of type 'wxWindow const *'

Can anyone see what I am doing wrong ?

[ isinstance(self, wx.Window) returns True, of course ]

--
Robin Dunn
Software Craftsman

That surely explains why it works when delaying the first
access to .ToolTip beyond __init__().

Karsten

···

On Tue, Jan 04, 2011 at 04:11:14PM -0800, Robin Dunn wrote:

>TypeError: in method 'Window_GetToolTip', expected argument 1 of type 'wxWindow const *'

>
>Can anyone see what I am doing wrong ?
>
>[ isinstance(self, wx.Window) returns True, of course ]

At the time the self.ToolTip property is evaluated the
wx.TextCtrl.__init__ has not yet been called, so as far as the C++
wrapper code is concerned self is not a wx.TextCtrl (or a wx.Window)
yet.

--
GPG key ID E4071346 @ wwwkeys.pgp.net
E167 67FD A291 2BEA 73BD 4537 78B9 A9F9 E407 1346