mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2026-01-06 03:50:06 +01:00
Merge pull request #239 from RobinD42/propgrid-more-fixes
Lots of propgrid fixes
This commit is contained in:
@@ -3,13 +3,14 @@
|
||||
import sys
|
||||
import time
|
||||
import math
|
||||
import os
|
||||
import os.path
|
||||
|
||||
import wx
|
||||
import wx.adv
|
||||
import wx.propgrid as wxpg
|
||||
|
||||
from six import exec_
|
||||
_ = wx.GetTranslation
|
||||
import wx.propgrid as wxpg
|
||||
|
||||
|
||||
############################################################################
|
||||
@@ -61,12 +62,12 @@ class ValueObject:
|
||||
pass
|
||||
|
||||
|
||||
class IntProperty2(wxpg.PyProperty):
|
||||
class IntProperty2(wxpg.PGProperty):
|
||||
"""\
|
||||
This is a simple re-implementation of wxIntProperty.
|
||||
"""
|
||||
def __init__(self, label, name = wxpg.LABEL_AS_NAME, value=0):
|
||||
wxpg.PyProperty.__init__(self, label, name)
|
||||
def __init__(self, label, name = wxpg.PG_LABEL, value=0):
|
||||
wxpg.PGProperty.__init__(self, label, name)
|
||||
self.SetValue(value)
|
||||
|
||||
def GetClassName(self):
|
||||
@@ -119,11 +120,11 @@ class IntProperty2(wxpg.PyProperty):
|
||||
return (True, value)
|
||||
|
||||
|
||||
class SizeProperty(wxpg.PyProperty):
|
||||
class SizeProperty(wxpg.PGProperty):
|
||||
""" Demonstrates a property with few children.
|
||||
"""
|
||||
def __init__(self, label, name = wxpg.LABEL_AS_NAME, value=wx.Size(0, 0)):
|
||||
wxpg.PyProperty.__init__(self, label, name)
|
||||
def __init__(self, label, name = wxpg.PG_LABEL, value=wx.Size(0, 0)):
|
||||
wxpg.PGProperty.__init__(self, label, name)
|
||||
|
||||
value = self._ConvertValue(value)
|
||||
|
||||
@@ -168,7 +169,7 @@ class SizeProperty(wxpg.PyProperty):
|
||||
return size
|
||||
|
||||
|
||||
class DirsProperty(wxpg.PyArrayStringProperty):
|
||||
class DirsProperty(wxpg.ArrayStringProperty):
|
||||
""" Sample of a custom custom ArrayStringProperty.
|
||||
|
||||
Because currently some of the C++ helpers from wxArrayStringProperty
|
||||
@@ -176,8 +177,8 @@ class DirsProperty(wxpg.PyArrayStringProperty):
|
||||
a bit 'manually'. Which is not too bad since Python has excellent
|
||||
string and list manipulation facilities.
|
||||
"""
|
||||
def __init__(self, label, name = wxpg.LABEL_AS_NAME, value=[]):
|
||||
wxpg.PyArrayStringProperty.__init__(self, label, name, value)
|
||||
def __init__(self, label, name = wxpg.PG_LABEL, value=[]):
|
||||
wxpg.ArrayStringProperty.__init__(self, label, name, value)
|
||||
|
||||
# Set default delimiter
|
||||
self.SetAttribute("Delimiter", ',')
|
||||
@@ -192,8 +193,7 @@ class DirsProperty(wxpg.PyArrayStringProperty):
|
||||
self.GenerateValueAsString()
|
||||
|
||||
def DoSetAttribute(self, name, value):
|
||||
# Proper way to call same method from super class
|
||||
retval = self.CallSuperMethod("DoSetAttribute", name, value)
|
||||
retval = super(DirsProperty, self).DoSetAttribute(name, value)
|
||||
|
||||
#
|
||||
# Must re-generate cached string when delimiter changes
|
||||
@@ -225,7 +225,7 @@ class DirsProperty(wxpg.PyArrayStringProperty):
|
||||
delim = self.GetAttribute("Delimiter")
|
||||
if delim == '"' or delim == "'":
|
||||
# Proper way to call same method from super class
|
||||
return self.CallSuperMethod("StringToValue", text, 0)
|
||||
return super(DirsProperty, self).StringToValue(text, 0)
|
||||
v = [a.strip() for a in text.split(delim)]
|
||||
return (True, v)
|
||||
|
||||
@@ -269,7 +269,7 @@ class PyObjectPropertyValue:
|
||||
return ' - '.join(self.ls)
|
||||
|
||||
|
||||
class PyObjectProperty(wxpg.PyProperty):
|
||||
class PyObjectProperty(wxpg.PGProperty):
|
||||
"""\
|
||||
Another simple example. This time our value is a PyObject.
|
||||
|
||||
@@ -278,8 +278,8 @@ class PyObjectProperty(wxpg.PyProperty):
|
||||
or wxObject based. Dictionary, None, or any user-specified Python
|
||||
class is allowed.
|
||||
"""
|
||||
def __init__(self, label, name = wxpg.LABEL_AS_NAME, value=None):
|
||||
wxpg.PyProperty.__init__(self, label, name)
|
||||
def __init__(self, label, name = wxpg.PG_LABEL, value=None):
|
||||
wxpg.PGProperty.__init__(self, label, name)
|
||||
self.SetValue(value)
|
||||
|
||||
def GetClassName(self):
|
||||
@@ -299,9 +299,9 @@ class PyObjectProperty(wxpg.PyProperty):
|
||||
return (True, v)
|
||||
|
||||
|
||||
class SampleMultiButtonEditor(wxpg.PyTextCtrlEditor):
|
||||
class SampleMultiButtonEditor(wxpg.PGTextCtrlEditor):
|
||||
def __init__(self):
|
||||
wxpg.PyTextCtrlEditor.__init__(self)
|
||||
wxpg.PGTextCtrlEditor.__init__(self)
|
||||
|
||||
def CreateControls(self, propGrid, property, pos, sz):
|
||||
# Create and populate buttons-subwindow
|
||||
@@ -314,7 +314,7 @@ class SampleMultiButtonEditor(wxpg.PyTextCtrlEditor):
|
||||
buttons.AddBitmapButton(wx.ArtProvider.GetBitmap(wx.ART_FOLDER))
|
||||
|
||||
# Create the 'primary' editor control (textctrl in this case)
|
||||
wnd = self.CallSuperMethod("CreateControls",
|
||||
wnd = super(SampleMultiButtonEditor, self).CreateControls(
|
||||
propGrid,
|
||||
property,
|
||||
pos,
|
||||
@@ -340,25 +340,25 @@ class SampleMultiButtonEditor(wxpg.PyTextCtrlEditor):
|
||||
|
||||
if evtId == buttons.GetButtonId(0):
|
||||
# Do something when the first button is pressed
|
||||
wx.LogDebug("First button pressed");
|
||||
wx.LogDebug("First button pressed")
|
||||
return False # Return false since value did not change
|
||||
if evtId == buttons.GetButtonId(1):
|
||||
# Do something when the second button is pressed
|
||||
wx.MessageBox("Second button pressed");
|
||||
wx.MessageBox("Second button pressed")
|
||||
return False # Return false since value did not change
|
||||
if evtId == buttons.GetButtonId(2):
|
||||
# Do something when the third button is pressed
|
||||
wx.MessageBox("Third button pressed");
|
||||
wx.MessageBox("Third button pressed")
|
||||
return False # Return false since value did not change
|
||||
|
||||
return self.CallSuperMethod("OnEvent", propGrid, prop, ctrl, event)
|
||||
return super(SampleMultiButtonEditor, self).OnEvent(propGrid, prop, ctrl, event)
|
||||
|
||||
|
||||
class SingleChoiceDialogAdapter(wxpg.PyEditorDialogAdapter):
|
||||
""" This demonstrates use of wxpg.PyEditorDialogAdapter.
|
||||
class SingleChoiceDialogAdapter(wxpg.PGEditorDialogAdapter):
|
||||
""" This demonstrates use of wxpg.PGEditorDialogAdapter.
|
||||
"""
|
||||
def __init__(self, choices):
|
||||
wxpg.PyEditorDialogAdapter.__init__(self)
|
||||
wxpg.PGEditorDialogAdapter.__init__(self)
|
||||
self.choices = choices
|
||||
|
||||
def DoShowDialog(self, propGrid, property):
|
||||
@@ -371,16 +371,16 @@ class SingleChoiceDialogAdapter(wxpg.PyEditorDialogAdapter):
|
||||
return False;
|
||||
|
||||
|
||||
class SingleChoiceProperty(wxpg.PyStringProperty):
|
||||
def __init__(self, label, name=wxpg.LABEL_AS_NAME, value=''):
|
||||
wxpg.PyStringProperty.__init__(self, label, name, value)
|
||||
class SingleChoiceProperty(wxpg.StringProperty):
|
||||
def __init__(self, label, name=wxpg.PG_LABEL, value=''):
|
||||
wxpg.StringProperty.__init__(self, label, name, value)
|
||||
|
||||
# Prepare choices
|
||||
dialog_choices = []
|
||||
dialog_choices.append("Cat");
|
||||
dialog_choices.append("Dog");
|
||||
dialog_choices.append("Gibbon");
|
||||
dialog_choices.append("Otter");
|
||||
dialog_choices.append("Cat")
|
||||
dialog_choices.append("Dog")
|
||||
dialog_choices.append("Gibbon")
|
||||
dialog_choices.append("Otter")
|
||||
|
||||
self.dialog_choices = dialog_choices
|
||||
|
||||
@@ -393,14 +393,14 @@ class SingleChoiceProperty(wxpg.PyStringProperty):
|
||||
return SingleChoiceDialogAdapter(self.dialog_choices)
|
||||
|
||||
|
||||
class TrivialPropertyEditor(wxpg.PyEditor):
|
||||
class TrivialPropertyEditor(wxpg.PGEditor):
|
||||
"""\
|
||||
This is a simple re-creation of TextCtrlWithButton. Note that it does
|
||||
not take advantage of wx.TextCtrl and wx.Button creation helper functions
|
||||
in wx.PropertyGrid.
|
||||
"""
|
||||
def __init__(self):
|
||||
wxpg.PyEditor.__init__(self)
|
||||
wxpg.PGEditor.__init__(self)
|
||||
|
||||
def CreateControls(self, propgrid, property, pos, sz):
|
||||
""" Create the actual wxPython controls here for editing the
|
||||
@@ -564,12 +564,12 @@ class LargeImagePickerCtrl(wx.Panel):
|
||||
return self.tc.GetLastPosition()
|
||||
|
||||
|
||||
class LargeImageEditor(wxpg.PyEditor):
|
||||
class LargeImageEditor(wxpg.PGEditor):
|
||||
"""\
|
||||
Double-height text-editor with image in front.
|
||||
"""
|
||||
def __init__(self):
|
||||
wxpg.PyEditor.__init__(self)
|
||||
wxpg.PGEditor.__init__(self)
|
||||
|
||||
def CreateControls(self, propgrid, property, pos, sz):
|
||||
try:
|
||||
@@ -723,14 +723,17 @@ class TestPanel( wx.Panel ):
|
||||
pg.Append( wxpg.IntProperty("Int",value=100) )
|
||||
pg.Append( wxpg.FloatProperty("Float",value=100.0) )
|
||||
pg.Append( wxpg.BoolProperty("Bool",value=True) )
|
||||
pg.Append( wxpg.BoolProperty("Bool_with_Checkbox",value=True) )
|
||||
pg.SetPropertyAttribute("Bool_with_Checkbox", "UseCheckbox", True)
|
||||
boolprop = pg.Append( wxpg.BoolProperty("Bool_with_Checkbox",value=True) )
|
||||
pg.SetPropertyAttribute(
|
||||
"Bool_with_Checkbox", # You can find the property by name,
|
||||
#boolprop, # or give the property object itself.
|
||||
"UseCheckbox", True) # The attribute name and value
|
||||
|
||||
pg.Append( wxpg.PropertyCategory("2 - More Properties") )
|
||||
pg.Append( wxpg.LongStringProperty("LongString",
|
||||
value="This is a\\nmulti-line string\\nwith\\ttabs\\nmixed\\tin."))
|
||||
pg.Append( wxpg.DirProperty("Dir",value="C:\\Windows") )
|
||||
pg.Append( wxpg.FileProperty("File",value="C:\\Windows\\system.ini") )
|
||||
value="This is a\nmulti-line string\nwith\ttabs\nmixed\tin."))
|
||||
pg.Append( wxpg.DirProperty("Dir",value=r"C:\Windows") )
|
||||
pg.Append( wxpg.FileProperty("File",value=r"C:\Windows\system.ini") )
|
||||
pg.Append( wxpg.ArrayStringProperty("ArrayString",value=['A','B','C']) )
|
||||
|
||||
pg.Append( wxpg.EnumProperty("Enum","Enum",
|
||||
@@ -763,9 +766,9 @@ class TestPanel( wx.Panel ):
|
||||
|
||||
pg.SetPropertyAttribute( "File", wxpg.PG_FILE_SHOW_FULL_PATH, 0 )
|
||||
pg.SetPropertyAttribute( "File", wxpg.PG_FILE_INITIAL_PATH,
|
||||
"C:\\Program Files\\Internet Explorer" )
|
||||
r"C:\Program Files\Internet Explorer" )
|
||||
pg.SetPropertyAttribute( "Date", wxpg.PG_DATE_PICKER_STYLE,
|
||||
wx.DP_DROPDOWN|wx.DP_SHOWCENTURY )
|
||||
wx.adv.DP_DROPDOWN|wx.adv.DP_SHOWCENTURY )
|
||||
|
||||
pg.Append( wxpg.PropertyCategory("5 - Custom Properties and Editors") )
|
||||
pg.Append( IntProperty2("IntProperty2", value=1024) )
|
||||
@@ -779,8 +782,8 @@ class TestPanel( wx.Panel ):
|
||||
pg.SetPropertyAttribute("Dirs2", "Delimiter", '"')
|
||||
|
||||
# SampleMultiButtonEditor
|
||||
pg.Append( wxpg.LongStringProperty("MultipleButtons") );
|
||||
pg.SetPropertyEditor("MultipleButtons", "SampleMultiButtonEditor");
|
||||
pg.Append( wxpg.LongStringProperty("MultipleButtons") )
|
||||
pg.SetPropertyEditor("MultipleButtons", "SampleMultiButtonEditor")
|
||||
pg.Append( SingleChoiceProperty("SingleChoiceProperty") )
|
||||
|
||||
# Custom editor samples
|
||||
@@ -857,7 +860,7 @@ class TestPanel( wx.Panel ):
|
||||
d = self.pg.GetPropertyValues(inc_attributes=True)
|
||||
|
||||
ss = []
|
||||
for k,v in d.iteritems():
|
||||
for k,v in d.items():
|
||||
v = repr(v)
|
||||
if not v or v[0] != '<':
|
||||
if k.startswith('@'):
|
||||
@@ -865,22 +868,22 @@ class TestPanel( wx.Panel ):
|
||||
else:
|
||||
ss.append('obj.%s = %s'%(k,v))
|
||||
|
||||
dlg = MemoDialog(self,
|
||||
with MemoDialog(self,
|
||||
"Enter Content for Object Used in SetPropertyValues",
|
||||
'\n'.join(ss)) # default_object_content1
|
||||
'\n'.join(ss)) as dlg: # default_object_content1
|
||||
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
import datetime
|
||||
sandbox = {'obj':ValueObject(),
|
||||
'wx':wx,
|
||||
'datetime':datetime}
|
||||
exec_(dlg.tc.GetValue(), sandbox)
|
||||
t_start = time.time()
|
||||
#print(sandbox['obj'].__dict__)
|
||||
self.pg.SetPropertyValues(sandbox['obj'])
|
||||
t_end = time.time()
|
||||
self.log.write('SetPropertyValues finished in %.0fms\n' %
|
||||
((t_end-t_start)*1000.0))
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
import datetime
|
||||
sandbox = {'obj':ValueObject(),
|
||||
'wx':wx,
|
||||
'datetime':datetime}
|
||||
exec_(dlg.tc.GetValue(), sandbox)
|
||||
t_start = time.time()
|
||||
#print(sandbox['obj'].__dict__)
|
||||
self.pg.SetPropertyValues(sandbox['obj'])
|
||||
t_end = time.time()
|
||||
self.log.write('SetPropertyValues finished in %.0fms\n' %
|
||||
((t_end-t_start)*1000.0))
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
@@ -892,10 +895,11 @@ class TestPanel( wx.Panel ):
|
||||
t_end = time.time()
|
||||
self.log.write('GetPropertyValues finished in %.0fms\n' %
|
||||
((t_end-t_start)*1000.0))
|
||||
ss = ['%s: %s'%(k,repr(v)) for k,v in d.iteritems()]
|
||||
dlg = MemoDialog(self,"GetPropertyValues Result",
|
||||
'Contents of resulting dictionary:\n\n'+'\n'.join(ss))
|
||||
dlg.ShowModal()
|
||||
ss = ['%s: %s'%(k,repr(v)) for k,v in d.items()]
|
||||
with MemoDialog(self,"GetPropertyValues Result",
|
||||
'Contents of resulting dictionary:\n\n'+'\n'.join(ss)) as dlg:
|
||||
dlg.ShowModal()
|
||||
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
@@ -907,25 +911,25 @@ class TestPanel( wx.Panel ):
|
||||
t_end = time.time()
|
||||
self.log.write('GetPropertyValues(as_strings=True) finished in %.0fms\n' %
|
||||
((t_end-t_start)*1000.0))
|
||||
ss = ['%s: %s'%(k,repr(v)) for k,v in d.iteritems()]
|
||||
dlg = MemoDialog(self,"GetPropertyValues Result",
|
||||
'Contents of resulting dictionary:\n\n'+'\n'.join(ss))
|
||||
dlg.ShowModal()
|
||||
ss = ['%s: %s'%(k,repr(v)) for k,v in d.items()]
|
||||
with MemoDialog(self,"GetPropertyValues Result",
|
||||
'Contents of resulting dictionary:\n\n'+'\n'.join(ss)) as dlg:
|
||||
dlg.ShowModal()
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
def OnAutoFill(self,event):
|
||||
try:
|
||||
dlg = MemoDialog(self,"Enter Content for Object Used for AutoFill",default_object_content1)
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
sandbox = {'object':ValueObject(),'wx':wx}
|
||||
exec_(dlg.tc.GetValue(), sandbox)
|
||||
t_start = time.time()
|
||||
self.pg.AutoFill(sandbox['object'])
|
||||
t_end = time.time()
|
||||
self.log.write('AutoFill finished in %.0fms\n' %
|
||||
((t_end-t_start)*1000.0))
|
||||
with MemoDialog(self,"Enter Content for Object Used for AutoFill",default_object_content1) as dlg:
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
sandbox = {'object':ValueObject(),'wx':wx}
|
||||
exec_(dlg.tc.GetValue(), sandbox)
|
||||
t_start = time.time()
|
||||
self.pg.AutoFill(sandbox['object'])
|
||||
t_end = time.time()
|
||||
self.log.write('AutoFill finished in %.0fms\n' %
|
||||
((t_end-t_start)*1000.0))
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
@@ -995,7 +999,7 @@ class TestPanel( wx.Panel ):
|
||||
|
||||
|
||||
class MemoDialog(wx.Dialog):
|
||||
"""\
|
||||
"""
|
||||
Dialog for multi-line text editing.
|
||||
"""
|
||||
def __init__(self,parent=None,title="",text="",pos=None,size=(500,500)):
|
||||
|
||||
@@ -2557,6 +2557,7 @@
|
||||
"PGArrayEditorDialog":"wx.propgrid.",
|
||||
"PGArrayStringEditorDialog":"wx.propgrid.",
|
||||
"PGAttributeStorage":"wx.propgrid.",
|
||||
"PGCachedString":"wx.propgrid.",
|
||||
"PGCell":"wx.propgrid.",
|
||||
"PGCellData":"wx.propgrid.",
|
||||
"PGCellRenderer":"wx.propgrid.",
|
||||
@@ -2589,6 +2590,7 @@
|
||||
"PGPropArgCls":"wx.propgrid.",
|
||||
"PGProperty":"wx.propgrid.",
|
||||
"PGPropertyFlags":"wx.propgrid.",
|
||||
"PGSortCallback":"wx.propgrid.",
|
||||
"PGSpinCtrlEditor":"wx.propgrid.",
|
||||
"PGTextCtrlAndButtonEditor":"wx.propgrid.",
|
||||
"PGTextCtrlEditor":"wx.propgrid.",
|
||||
@@ -2607,15 +2609,25 @@
|
||||
"PG_ACTION_PREV_PROPERTY":"wx.propgrid.",
|
||||
"PG_ALPHABETIC_MODE":"wx.propgrid.",
|
||||
"PG_AUTO_SORT":"wx.propgrid.",
|
||||
"PG_BASE_DEC":"wx.propgrid.",
|
||||
"PG_BASE_HEX":"wx.propgrid.",
|
||||
"PG_BASE_HEXL":"wx.propgrid.",
|
||||
"PG_BASE_OCT":"wx.propgrid.",
|
||||
"PG_BOLD_MODIFIED":"wx.propgrid.",
|
||||
"PG_CAPRECTXMARGIN":"wx.propgrid.",
|
||||
"PG_CAPRECTYMARGIN":"wx.propgrid.",
|
||||
"PG_COLOUR":"wx.propgrid.",
|
||||
"PG_COLOUR_BLACK":"wx.propgrid.",
|
||||
"PG_COLOUR_CUSTOM":"wx.propgrid.",
|
||||
"PG_COLOUR_UNSPECIFIED":"wx.propgrid.",
|
||||
"PG_COLOUR_WEB_BASE":"wx.propgrid.",
|
||||
"PG_COMPOSITE_FRAGMENT":"wx.propgrid.",
|
||||
"PG_CUSTOM_IMAGE_SPACINGY":"wx.propgrid.",
|
||||
"PG_DEFAULT_IMAGE_SIZE":"wx.propgrid.",
|
||||
"PG_DEFAULT_STYLE":"wx.propgrid.",
|
||||
"PG_DESCRIPTION":"wx.propgrid.",
|
||||
"PG_DONT_RECURSE":"wx.propgrid.",
|
||||
"PG_EDITABLE_VALUE":"wx.propgrid.",
|
||||
"PG_EX_AUTO_UNSPECIFIED_VALUES":"wx.propgrid.",
|
||||
"PG_EX_ENABLE_TLP_TRACKING":"wx.propgrid.",
|
||||
"PG_EX_HELP_AS_TOOLTIPS":"wx.propgrid.",
|
||||
@@ -2629,8 +2641,13 @@
|
||||
"PG_EX_TOOLBAR_SEPARATOR":"wx.propgrid.",
|
||||
"PG_EX_WINDOW_STYLES":"wx.propgrid.",
|
||||
"PG_EX_WRITEONLY_BUILTIN_ATTRIBUTES":"wx.propgrid.",
|
||||
"PG_FORCE":"wx.propgrid.",
|
||||
"PG_FULL_VALUE":"wx.propgrid.",
|
||||
"PG_GETPROPERTYVALUES_FLAGS":"wx.propgrid.",
|
||||
"PG_HIDE_CATEGORIES":"wx.propgrid.",
|
||||
"PG_HIDE_MARGIN":"wx.propgrid.",
|
||||
"PG_INC_ATTRIBUTES":"wx.propgrid.",
|
||||
"PG_INVALID_VALUE":"wx.propgrid.",
|
||||
"PG_ITERATE_ALL":"wx.propgrid.",
|
||||
"PG_ITERATE_ALL_PARENTS":"wx.propgrid.",
|
||||
"PG_ITERATE_ALL_PARENTS_RECURSIVELY":"wx.propgrid.",
|
||||
@@ -2645,9 +2662,19 @@
|
||||
"PG_ITERATOR_FLAGS_ALL":"wx.propgrid.",
|
||||
"PG_ITERATOR_MASK_OP_ITEM":"wx.propgrid.",
|
||||
"PG_ITERATOR_MASK_OP_PARENT":"wx.propgrid.",
|
||||
"PG_KEEP_STRUCTURE":"wx.propgrid.",
|
||||
"PG_KEYBOARD_ACTIONS":"wx.propgrid.",
|
||||
"PG_LABEL":"wx.propgrid.",
|
||||
"PG_LABEL_STRING":"wx.propgrid.",
|
||||
"PG_LIMITED_EDITING":"wx.propgrid.",
|
||||
"PG_MISC_ARG_FLAGS":"wx.propgrid.",
|
||||
"PG_NO_INTERNAL_BORDER":"wx.propgrid.",
|
||||
"PG_NULL_BITMAP":"wx.propgrid.",
|
||||
"PG_PREFIX_0x":"wx.propgrid.",
|
||||
"PG_PREFIX_DOLLAR_SIGN":"wx.propgrid.",
|
||||
"PG_PREFIX_NONE":"wx.propgrid.",
|
||||
"PG_PROGRAMMATIC_VALUE":"wx.propgrid.",
|
||||
"PG_PROPERTY_SPECIFIC":"wx.propgrid.",
|
||||
"PG_PROPERTY_VALIDATION_ERROR_MESSAGE":"wx.propgrid.",
|
||||
"PG_PROPERTY_VALIDATION_SATURATE":"wx.propgrid.",
|
||||
"PG_PROPERTY_VALIDATION_WRAP":"wx.propgrid.",
|
||||
@@ -2680,12 +2707,23 @@
|
||||
"PG_PROP_USE_CHECKBOX":"wx.propgrid.",
|
||||
"PG_PROP_USE_DCC":"wx.propgrid.",
|
||||
"PG_PROP_WAS_MODIFIED":"wx.propgrid.",
|
||||
"PG_RECURSE":"wx.propgrid.",
|
||||
"PG_RECURSE_STARTS":"wx.propgrid.",
|
||||
"PG_REPORT_ERROR":"wx.propgrid.",
|
||||
"PG_SETVALUE_FLAGS":"wx.propgrid.",
|
||||
"PG_SETVAL_AGGREGATED":"wx.propgrid.",
|
||||
"PG_SETVAL_BY_USER":"wx.propgrid.",
|
||||
"PG_SETVAL_FROM_PARENT":"wx.propgrid.",
|
||||
"PG_SETVAL_REFRESH_EDITOR":"wx.propgrid.",
|
||||
"PG_SORT_TOP_LEVEL_ONLY":"wx.propgrid.",
|
||||
"PG_SPLITTER_AUTO_CENTER":"wx.propgrid.",
|
||||
"PG_STATIC_LAYOUT":"wx.propgrid.",
|
||||
"PG_STATIC_SPLITTER":"wx.propgrid.",
|
||||
"PG_TOOLBAR":"wx.propgrid.",
|
||||
"PG_TOOLTIPS":"wx.propgrid.",
|
||||
"PG_UNEDITABLE_COMPOSITE_FRAGMENT":"wx.propgrid.",
|
||||
"PG_VALIDATION_FAILURE_BEHAVIOR_FLAGS":"wx.propgrid.",
|
||||
"PG_VALUE_IS_CURRENT":"wx.propgrid.",
|
||||
"PG_VFB_BEEP":"wx.propgrid.",
|
||||
"PG_VFB_DEFAULT":"wx.propgrid.",
|
||||
"PG_VFB_MARK_CELL":"wx.propgrid.",
|
||||
@@ -2819,12 +2857,14 @@
|
||||
"PropertyCategory":"wx.propgrid.",
|
||||
"PropertyGrid":"wx.propgrid.",
|
||||
"PropertyGridConstIterator":"wx.propgrid.",
|
||||
"PropertyGridEvent":"wx.propgrid.",
|
||||
"PropertyGridHitTestResult":"wx.propgrid.",
|
||||
"PropertyGridInterface":"wx.propgrid.",
|
||||
"PropertyGridIterator":"wx.propgrid.",
|
||||
"PropertyGridIteratorBase":"wx.propgrid.",
|
||||
"PropertyGridManager":"wx.propgrid.",
|
||||
"PropertyGridManagerNameStr":"wx.propgrid.",
|
||||
"PropertyGridNameStr":"wx.propgrid.",
|
||||
"PropertyGridPage":"wx.propgrid.",
|
||||
"PropertyGridPageState":"wx.propgrid.",
|
||||
"PropertySheetDialog":"wx.adv.",
|
||||
@@ -3137,6 +3177,7 @@
|
||||
"Region":"wx.",
|
||||
"RegionContain":"wx.",
|
||||
"RegionIterator":"wx.",
|
||||
"RegisterEditor":"wx.propgrid.",
|
||||
"RegisterId":"wx.",
|
||||
"Relationship":"wx.",
|
||||
"RendererNative":"wx.",
|
||||
@@ -6478,6 +6519,20 @@
|
||||
"wxEVT_NULL":"wx.",
|
||||
"wxEVT_PAINT":"wx.",
|
||||
"wxEVT_PALETTE_CHANGED":"wx.",
|
||||
"wxEVT_PG_CHANGED":"wx.propgrid.",
|
||||
"wxEVT_PG_CHANGING":"wx.propgrid.",
|
||||
"wxEVT_PG_COL_BEGIN_DRAG":"wx.propgrid.",
|
||||
"wxEVT_PG_COL_DRAGGING":"wx.propgrid.",
|
||||
"wxEVT_PG_COL_END_DRAG":"wx.propgrid.",
|
||||
"wxEVT_PG_DOUBLE_CLICK":"wx.propgrid.",
|
||||
"wxEVT_PG_HIGHLIGHTED":"wx.propgrid.",
|
||||
"wxEVT_PG_ITEM_COLLAPSED":"wx.propgrid.",
|
||||
"wxEVT_PG_ITEM_EXPANDED":"wx.propgrid.",
|
||||
"wxEVT_PG_LABEL_EDIT_BEGIN":"wx.propgrid.",
|
||||
"wxEVT_PG_LABEL_EDIT_ENDING":"wx.propgrid.",
|
||||
"wxEVT_PG_PAGE_CHANGED":"wx.propgrid.",
|
||||
"wxEVT_PG_RIGHT_CLICK":"wx.propgrid.",
|
||||
"wxEVT_PG_SELECTED":"wx.propgrid.",
|
||||
"wxEVT_POWER_RESUME":"wx.",
|
||||
"wxEVT_POWER_SUSPENDED":"wx.",
|
||||
"wxEVT_POWER_SUSPENDING":"wx.",
|
||||
|
||||
@@ -23,7 +23,9 @@ ITEMS = [ ]
|
||||
# The list of other ETG scripts and back-end generator modules that are
|
||||
# included as part of this module. These should all be items that are put in
|
||||
# the wxWidgets "propgrid" library in a multi-lib build.
|
||||
INCLUDES = [ 'propgridproperty',
|
||||
INCLUDES = [ 'pgvariant',
|
||||
'propgriddefs',
|
||||
'propgridproperty',
|
||||
'propgrideditors',
|
||||
'propgridpagestate',
|
||||
'propgridiface',
|
||||
@@ -62,6 +64,37 @@ def run():
|
||||
|
||||
module.addInclude(INCLUDES)
|
||||
|
||||
|
||||
# Deprecated aliases for the various helper classes in Classic
|
||||
module.addPyCode("""\
|
||||
PyArrayStringProperty = wx.deprecated(ArrayStringProperty, "Use ArrayStringProperty instead.")
|
||||
PyChoiceEditor = wx.deprecated(PGChoiceEditor, "Use PGChoiceEditor instead.")
|
||||
PyColourProperty = wx.deprecated(ColourProperty, "Use ColourProperty instead.")
|
||||
PyComboBoxEditor = wx.deprecated(PGComboBoxEditor, "Use PGComboBoxEditor instead.")
|
||||
PyEditEnumProperty = wx.deprecated(EditEnumProperty, "Use PGEditEnumProperty instead.")
|
||||
PyEditor = wx.deprecated(PGEditor, "Use PGEditor instead.")
|
||||
PyEditorDialogAdapter = wx.deprecated(PGEditorDialogAdapter, "Use PGEditorDialogAdapter instead.")
|
||||
PyEnumProperty = wx.deprecated(EnumProperty, "Use EnumProperty instead.")
|
||||
PyFileDialogAdapter = wx.deprecated(PGFileDialogAdapter, "Use PGFileDialogAdapter instead.")
|
||||
PyFileProperty = wx.deprecated(FileProperty, "Use FileProperty instead.")
|
||||
PyFlagsProperty = wx.deprecated(FlagsProperty, "Use FlagsProperty instead.")
|
||||
PyFloatProperty = wx.deprecated(FloatProperty, "Use FloatProperty instead.")
|
||||
PyFontProperty = wx.deprecated(FontProperty, "Use FontProperty instead.")
|
||||
PyIntProperty = wx.deprecated(IntProperty, "Use IntProperty instead.")
|
||||
PyLongStringDialogAdapter = wx.deprecated(PGLongStringDialogAdapter, "Use PGLongStringDialogAdapter instead.")
|
||||
PyLongStringProperty = wx.deprecated(LongStringProperty, "Use LongStringProperty instead.")
|
||||
PyProperty = wx.deprecated(PGProperty, "Use PGProperty instead.")
|
||||
PyStringProperty = wx.deprecated(StringProperty, "Use StringProperty instead.")
|
||||
PySystemColourProperty = wx.deprecated(SystemColourProperty, "Use SystemColourProperty instead.")
|
||||
PyTextCtrlEditor = wx.deprecated(PGTextCtrlEditor, "Use PGTextCtrlEditor instead.")
|
||||
PyUIntProperty = wx.deprecated(UIntProperty, "Use UIntProperty instead.")
|
||||
""")
|
||||
|
||||
module.addPyFunction('RegisterEditor', '(editor, editorName)',
|
||||
deprecated='Use PropertyGrid.DoRegisterEditor instead',
|
||||
body='return PropertyGrid.DoRegisterEditorClass(editor, editorName)',
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
tools.doCommonTweaks(module)
|
||||
tools.runGenerators(module)
|
||||
|
||||
@@ -20,6 +20,7 @@ DOCSTRING = ""
|
||||
ITEMS = [ 'interface_2wx_2propgrid_2propgrid_8h.xml',
|
||||
'wxPGValidationInfo',
|
||||
'wxPropertyGrid',
|
||||
'wxPropertyGridEvent',
|
||||
]
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -33,7 +34,6 @@ def run():
|
||||
# Tweak the parsed meta objects in the module object as needed for
|
||||
# customizing the generated code and docstrings.
|
||||
|
||||
|
||||
c = module.find('wxPGValidationInfo')
|
||||
assert isinstance(c, etgtools.ClassDef)
|
||||
|
||||
@@ -42,12 +42,31 @@ def run():
|
||||
assert isinstance(c, etgtools.ClassDef)
|
||||
c.bases.remove('wxScrollHelper')
|
||||
tools.fixWindowClass(c)
|
||||
module.addGlobalStr('wxPropertyGridNameStr', c)
|
||||
|
||||
for m in c.find('RegisterEditorClass').all():
|
||||
m.find('editor').transfer = True
|
||||
|
||||
|
||||
# TODO: provide a way to use a Python callable as a sort function
|
||||
c.find('GetSortFunction').ignore()
|
||||
c.find('SetSortFunction').ignore()
|
||||
module.find('wxPGSortCallback').ignore()
|
||||
|
||||
# Add some extra Python code to be executed when a wxPropertyGrid is
|
||||
# constructed. In Classic with SWIG we did this with %pythonAppend, is
|
||||
# there any better way to do it with sip than monkey-patching?
|
||||
c.addPyCode("""\
|
||||
_PropertyGrid__init__orig = PropertyGrid.__init__
|
||||
def _PropertyGrid__init__(self, *args, **kw):
|
||||
_PropertyGrid__init__orig(self, *args, **kw)
|
||||
self.DoDefaultTypeMappings()
|
||||
self.edited_objects = {}
|
||||
self.DoDefaultValueTypeMappings()
|
||||
if not hasattr(self.__class__, '_vt2setter'):
|
||||
self.__class__._vt2setter = {}
|
||||
PropertyGrid.__init__ = _PropertyGrid__init__
|
||||
""")
|
||||
|
||||
# See note in propgridiface.py
|
||||
for item in module.allItems():
|
||||
@@ -61,6 +80,34 @@ def run():
|
||||
td.noTypeName = True
|
||||
|
||||
|
||||
c = module.find('wxPropertyGridEvent')
|
||||
tools.fixEventClass(c)
|
||||
|
||||
c.addPyCode("""\
|
||||
EVT_PG_CHANGED = wx.PyEventBinder( wxEVT_PG_CHANGED, 1 )
|
||||
EVT_PG_CHANGING = wx.PyEventBinder( wxEVT_PG_CHANGING, 1 )
|
||||
EVT_PG_SELECTED = wx.PyEventBinder( wxEVT_PG_SELECTED, 1 )
|
||||
EVT_PG_HIGHLIGHTED = wx.PyEventBinder( wxEVT_PG_HIGHLIGHTED, 1 )
|
||||
EVT_PG_RIGHT_CLICK = wx.PyEventBinder( wxEVT_PG_RIGHT_CLICK, 1 )
|
||||
EVT_PG_PAGE_CHANGED = wx.PyEventBinder( wxEVT_PG_PAGE_CHANGED, 1 )
|
||||
EVT_PG_ITEM_COLLAPSED = wx.PyEventBinder( wxEVT_PG_ITEM_COLLAPSED, 1 )
|
||||
EVT_PG_ITEM_EXPANDED = wx.PyEventBinder( wxEVT_PG_ITEM_EXPANDED, 1 )
|
||||
EVT_PG_DOUBLE_CLICK = wx.PyEventBinder( wxEVT_PG_DOUBLE_CLICK, 1 )
|
||||
EVT_PG_LABEL_EDIT_BEGIN = wx.PyEventBinder( wxEVT_PG_LABEL_EDIT_BEGIN, 1 )
|
||||
EVT_PG_LABEL_EDIT_ENDING = wx.PyEventBinder( wxEVT_PG_LABEL_EDIT_ENDING, 1 )
|
||||
EVT_PG_COL_BEGIN_DRAG = wx.PyEventBinder( wxEVT_PG_COL_BEGIN_DRAG, 1 )
|
||||
EVT_PG_COL_DRAGGING = wx.PyEventBinder( wxEVT_PG_COL_DRAGGING, 1 )
|
||||
EVT_PG_COL_END_DRAG = wx.PyEventBinder( wxEVT_PG_COL_END_DRAG, 1 )
|
||||
""")
|
||||
|
||||
|
||||
# Switch all wxVariant types to wxPGVariant, so the propgrid-specific
|
||||
# version of the MappedType will be used for converting to/from Python
|
||||
# objects.
|
||||
for item in module.allItems():
|
||||
if hasattr(item, 'type') and 'wxVariant' in item.type:
|
||||
item.type = item.type.replace('wxVariant', 'wxPGVariant')
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
tools.doCommonTweaks(module)
|
||||
tools.runGenerators(module)
|
||||
|
||||
@@ -40,9 +40,24 @@ def run():
|
||||
# Tweak the parsed meta objects in the module object as needed for
|
||||
# customizing the generated code and docstrings.
|
||||
|
||||
#c = module.find('')
|
||||
#assert isinstance(c, etgtools.ClassDef)
|
||||
c = module.find('wxMultiChoiceProperty')
|
||||
assert isinstance(c, etgtools.ClassDef)
|
||||
|
||||
# Fix up the ctor taking a wxArrayString to be the one with the easier and
|
||||
# expected API
|
||||
m = c.find('wxMultiChoiceProperty').findOverload('strings')
|
||||
m.find('name').default = 'wxPG_LABEL'
|
||||
m.find('strings').default = 'wxArrayString()'
|
||||
m.find('strings').name = 'choices'
|
||||
m.find('value').default = 'wxArrayString()'
|
||||
|
||||
|
||||
# Switch all wxVariant types to wxPGVariant, so the propgrid-specific
|
||||
# version of the MappedType will be used for converting to/from Python
|
||||
# objects.
|
||||
for item in module.allItems():
|
||||
if hasattr(item, 'type') and 'wxVariant' in item.type:
|
||||
item.type = item.type.replace('wxVariant', 'wxPGVariant')
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
tools.doCommonTweaks(module)
|
||||
|
||||
60
etg/propgriddefs.py
Normal file
60
etg/propgriddefs.py
Normal file
@@ -0,0 +1,60 @@
|
||||
#---------------------------------------------------------------------------
|
||||
# Name: etg/propgriddefs.py
|
||||
# Author: Robin Dunn
|
||||
#
|
||||
# Created: 14-Feb-2017
|
||||
# Copyright: (c) 2017 by Total Control Software
|
||||
# License: wxWindows License
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
import etgtools
|
||||
import etgtools.tweaker_tools as tools
|
||||
|
||||
PACKAGE = "wx"
|
||||
MODULE = "_propgrid"
|
||||
NAME = "propgriddefs" # Base name of the file to generate to for this script
|
||||
DOCSTRING = ""
|
||||
|
||||
# The classes and/or the basename of the Doxygen XML files to be processed by
|
||||
# this script.
|
||||
ITEMS = [ 'propgriddefs_8h.xml',
|
||||
]
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
def run():
|
||||
# Parse the XML file(s) building a collection of Extractor objects
|
||||
module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING)
|
||||
etgtools.parseDoxyXML(module, ITEMS)
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
# Tweak the parsed meta objects in the module object as needed for
|
||||
# customizing the generated code and docstrings.
|
||||
|
||||
module.find('wxPG_LABEL').ignore()
|
||||
module.find('wxPG_LABEL_STRING').ignore()
|
||||
module.find('wxPG_NULL_BITMAP').ignore()
|
||||
module.find('wxPG_COLOUR_BLACK').ignore()
|
||||
module.find('wxPG_COLOUR').ignore()
|
||||
module.find('wxPG_DEFAULT_IMAGE_SIZE').ignore()
|
||||
module.find('wxPGSortCallback').ignore()
|
||||
|
||||
module.addPyCode(
|
||||
code="""\
|
||||
PG_LABEL = "@!"
|
||||
PG_LABEL_STRING = PG_LABEL
|
||||
PG_NULL_BITMAP = wx.NullBitmap
|
||||
PG_COLOUR_BLACK = wx.BLACK
|
||||
PG_DEFAULT_IMAGE_SIZE = wx.Size(-1, -1)
|
||||
""",
|
||||
order=15)
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
tools.doCommonTweaks(module)
|
||||
tools.runGenerators(module)
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
|
||||
@@ -45,6 +45,13 @@ def run():
|
||||
tools.fixWindowClass(c)
|
||||
|
||||
|
||||
# Switch all wxVariant types to wxPGVariant, so the propgrid-specific
|
||||
# version of the MappedType will be used for converting to/from Python
|
||||
# objects.
|
||||
for item in module.allItems():
|
||||
if hasattr(item, 'type') and 'wxVariant' in item.type:
|
||||
item.type = item.type.replace('wxVariant', 'wxPGVariant')
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
tools.doCommonTweaks(module)
|
||||
tools.runGenerators(module)
|
||||
|
||||
@@ -34,8 +34,75 @@ def run():
|
||||
|
||||
c = module.find('wxPGPropArgCls')
|
||||
assert isinstance(c, etgtools.ClassDef)
|
||||
c.find('wxPGPropArgCls').findOverload('wxString &').ignore()
|
||||
c.find('wxPGPropArgCls').findOverload('char *').ignore()
|
||||
c.find('wxPGPropArgCls').findOverload('wchar_t *').ignore()
|
||||
c.find('wxPGPropArgCls').findOverload('int').ignore()
|
||||
c.find('wxPGPropArgCls').findOverload('deallocPtr').ignore()
|
||||
|
||||
# Make a string ctor that uses the wxPython-specific version of
|
||||
# the C++ class' ctor
|
||||
newCtor = c.addCppCtor('(const wxString& str)',
|
||||
doc="Creates a PGPropArgCls from a string.",
|
||||
body="""\
|
||||
wxString* name = new wxString(*str);
|
||||
return new wxPGPropArgCls(name, true);
|
||||
"""
|
||||
)
|
||||
|
||||
# Make it be the first overload instead of the last
|
||||
ctor = c.find('wxPGPropArgCls')
|
||||
overloads = list(ctor.overloads)
|
||||
del overloads[overloads.index(newCtor)]
|
||||
overloads.insert(0, newCtor)
|
||||
ctor.overloads = overloads
|
||||
|
||||
|
||||
c.find('GetPtr').overloads[0].ignore()
|
||||
|
||||
c.convertFromPyObject = """\
|
||||
// Code to test a PyObject for compatibility with wxPGPropArgCls
|
||||
if (!sipIsErr) {
|
||||
if (sipCanConvertToType(sipPy, sipType_wxPGPropArgCls, SIP_NO_CONVERTORS))
|
||||
return TRUE;
|
||||
if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy))
|
||||
return TRUE;
|
||||
if (sipPy == Py_None)
|
||||
return TRUE;
|
||||
if (sipCanConvertToType(sipPy, sipType_wxPGProperty, SIP_NO_CONVERTORS))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Code to convert a compatible PyObject to a wxPGPropArgCls
|
||||
if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy)) {
|
||||
wxString* name = new wxString(Py2wxString(sipPy));
|
||||
*sipCppPtr = new wxPGPropArgCls(name, true);
|
||||
return sipGetState(sipTransferObj);
|
||||
}
|
||||
else if (sipCanConvertToType(sipPy, sipType_wxPGProperty, SIP_NO_CONVERTORS)) {
|
||||
int state = 0;
|
||||
wxPGProperty* prop = reinterpret_cast<wxPGProperty*>(
|
||||
sipConvertToType(sipPy, sipType_wxPGProperty, sipTransferObj, SIP_NO_CONVERTORS, &state, sipIsErr));
|
||||
*sipCppPtr = new wxPGPropArgCls(prop);
|
||||
sipReleaseType(prop, sipType_wxPGProperty, state);
|
||||
return sipGetState(sipTransferObj);
|
||||
}
|
||||
else if (sipPy == Py_None) {
|
||||
*sipCppPtr = new wxPGPropArgCls(reinterpret_cast< wxPGProperty * >(NULL));
|
||||
return sipGetState(sipTransferObj);
|
||||
}
|
||||
else {
|
||||
// It's already a wxPGPropArgCls, just fetch the pointer and return
|
||||
*sipCppPtr = reinterpret_cast<wxPGPropArgCls*>(sipConvertToType(
|
||||
sipPy, sipType_wxPGPropArgCls, sipTransferObj,
|
||||
SIP_NO_CONVERTORS, 0, sipIsErr));
|
||||
return 0; // not a new instance
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
#----------------------------------------------------------
|
||||
|
||||
c = module.find('wxPropertyGridInterface')
|
||||
c.abstract = True
|
||||
@@ -49,13 +116,371 @@ def run():
|
||||
c.find('SetPropertyValue').findOverload('wxULongLong_t value').ignore()
|
||||
c.find('SetPropertyValue').findOverload('wxObject *value').ignore()
|
||||
|
||||
c.find('Append.property').transfer = True
|
||||
c.find('AppendIn.newProperty').transfer = True
|
||||
for m in c.find('Insert').all():
|
||||
m.find('newProperty').transfer = True
|
||||
|
||||
|
||||
|
||||
# Tons of Python method implementations ported from Classic...
|
||||
|
||||
module.addPyCode("""\
|
||||
_type2property = None
|
||||
_vt2getter = None
|
||||
""")
|
||||
|
||||
c.addPyMethod('MapType', '(self, class_, factory)',
|
||||
doc="""\
|
||||
Registers Python type/class to property mapping.
|
||||
|
||||
:param `factory`: Property builder function/class.
|
||||
""",
|
||||
body="""\
|
||||
global _type2property
|
||||
if _type2property is None:
|
||||
raise AssertionError("call only after a propertygrid or "
|
||||
"manager instance constructed")
|
||||
_type2property[class_] = factory
|
||||
""")
|
||||
|
||||
|
||||
c.addPyMethod('DoDefaultTypeMappings', '(self)',
|
||||
doc="Add built-in properties to the map.",
|
||||
body="""\
|
||||
import sys
|
||||
global _type2property
|
||||
if _type2property is not None:
|
||||
return
|
||||
_type2property = dict()
|
||||
|
||||
_type2property[str] = StringProperty
|
||||
if sys.version_info.major < 2:
|
||||
_type2property[unicode] = StringProperty
|
||||
_type2property[int] = IntProperty
|
||||
_type2property[float] = FloatProperty
|
||||
_type2property[bool] = BoolProperty
|
||||
_type2property[list] = ArrayStringProperty
|
||||
_type2property[tuple] = ArrayStringProperty
|
||||
_type2property[wx.Font] = FontProperty
|
||||
_type2property[wx.Colour] = ColourProperty
|
||||
#_type2property[wx.Size] = SizeProperty
|
||||
#_type2property[wx.Point] = PointProperty
|
||||
#_type2property[wx.FontData] = FontDataProperty
|
||||
""")
|
||||
|
||||
|
||||
# TODO: is this still needed?
|
||||
c.addPyMethod('DoDefaultValueTypeMappings', '(self)',
|
||||
doc="Map pg value type ids to getter methods.",
|
||||
body="""\
|
||||
global _vt2getter
|
||||
if _vt2getter is not None:
|
||||
return
|
||||
_vt2getter = dict()
|
||||
""")
|
||||
|
||||
|
||||
c.find('GetPropertyValues').ignore()
|
||||
c.addPyMethod('GetPropertyValues',
|
||||
'(self, dict_=None, as_strings=False, inc_attributes=False)',
|
||||
doc="""\
|
||||
Returns all property values in the grid.\n
|
||||
:param `dict_`: A to fill with the property values. If not given,
|
||||
then a new one is created. The dict_ can be an object as well,
|
||||
in which case it's __dict__ is used.
|
||||
:param `as_strings`: if True, then string representations of values
|
||||
are fetched instead of native types. Useful for config and such.
|
||||
:param `inc_attributes`: if True, then property attributes are added
|
||||
in the form of "@<propname>@<attr>".
|
||||
:returns: A dictionary with values. It is always a dictionary,
|
||||
so if dict_ was and object with __dict__ attribute, then that
|
||||
attribute is returned.
|
||||
""",
|
||||
body="""\
|
||||
if dict_ is None:
|
||||
dict_ = {}
|
||||
elif hasattr(dict_,'__dict__'):
|
||||
dict_ = dict_.__dict__
|
||||
|
||||
getter = self.GetPropertyValue if not as_strings else self.GetPropertyValueAsString
|
||||
|
||||
it = self.GetVIterator(PG_ITERATE_PROPERTIES)
|
||||
while not it.AtEnd():
|
||||
p = it.GetProperty()
|
||||
name = p.GetName()
|
||||
dict_[name] = getter(p)
|
||||
|
||||
if inc_attributes:
|
||||
attrs = p.GetAttributes()
|
||||
if attrs and len(attrs):
|
||||
dict_['@%s@attr'%name] = attrs
|
||||
|
||||
it.Next()
|
||||
|
||||
return dict_
|
||||
""")
|
||||
|
||||
|
||||
for m in c.find('SetPropertyValues').all():
|
||||
m.ignore()
|
||||
c.addPyMethod('SetPropertyValues', '(self, dict_, autofill=False)',
|
||||
doc="""\
|
||||
Sets property values from a dictionary.\n
|
||||
:param `dict_`: the source of the property values to set, which can be
|
||||
either a dictionary or an object with a __dict__ attribute.
|
||||
:param `autofill`: If true, keys with not relevant properties are
|
||||
auto-created. For more info, see :method:`AutoFill`.
|
||||
|
||||
:note:
|
||||
* Keys starting with underscore are ignored.
|
||||
* Attributes can be set with entries named like "@<propname>@<attr>".
|
||||
""",
|
||||
body="""\
|
||||
if dict_ is None:
|
||||
dict_ = {}
|
||||
elif hasattr(dict_,'__dict__'):
|
||||
dict_ = dict_.__dict__
|
||||
attr_dicts = []
|
||||
|
||||
def set_sub_obj(k0, dict_):
|
||||
for k,v in dict_.items():
|
||||
if k[0] != '_':
|
||||
if k.endswith('@attr'):
|
||||
attr_dicts.append((k[1:-5],v))
|
||||
else:
|
||||
try:
|
||||
self.SetPropertyValue(k,v)
|
||||
except:
|
||||
try:
|
||||
if autofill:
|
||||
self._AutoFillOne(k0,k,v)
|
||||
continue
|
||||
except:
|
||||
if isinstance(v,dict):
|
||||
set_sub_obj(k,v)
|
||||
elif hasattr(v,'__dict__'):
|
||||
set_sub_obj(k,v.__dict__)
|
||||
|
||||
for k,v in attr_dicts:
|
||||
p = self.GetPropertyByName(k)
|
||||
if not p:
|
||||
raise AssertionError("No such property: '%s'"%k)
|
||||
for an,av in v.items():
|
||||
p.SetAttribute(an, av)
|
||||
|
||||
|
||||
cur_page = False
|
||||
is_manager = isinstance(self, PropertyGridManager)
|
||||
|
||||
try:
|
||||
set_sub_obj(self.GetGrid().GetRoot(), dict_)
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
self.Refresh()
|
||||
""")
|
||||
|
||||
# TODO: should these be marked as deprecated?
|
||||
module.addPyCode("""\
|
||||
PropertyGridInterface.GetValues = PropertyGridInterface.GetPropertyValues
|
||||
PropertyGridInterface.SetValues = PropertyGridInterface.SetPropertyValues
|
||||
""")
|
||||
|
||||
|
||||
c.addPyMethod('_AutoFillMany', '(self,cat,dict_)',
|
||||
body="""\
|
||||
for k,v in dict_.items():
|
||||
self._AutoFillOne(cat,k,v)
|
||||
""")
|
||||
|
||||
c.addPyMethod('_AutoFillOne', '(self,cat,k,v)',
|
||||
body="""\
|
||||
global _type2property
|
||||
factory = _type2property.get(v.__class__,None)
|
||||
if factory:
|
||||
self.AppendIn(cat, factory(k,k,v))
|
||||
elif hasattr(v,'__dict__'):
|
||||
cat2 = self.AppendIn(cat, PropertyCategory(k))
|
||||
self._AutoFillMany(cat2, v.__dict__)
|
||||
elif isinstance(v, dict):
|
||||
cat2 = self.AppendIn(cat, PropertyCategory(k))
|
||||
self._AutoFillMany(cat2, v)
|
||||
elif not k.startswith('_'):
|
||||
raise AssertionError("member '%s' is of unregistered type/"
|
||||
"class '%s'"%(k,v.__class__))
|
||||
""")
|
||||
|
||||
c.addPyMethod('AutoFill', '(self, obj, parent=None)',
|
||||
doc="""\
|
||||
"Clears properties and re-fills to match members and values of
|
||||
the given object or dictionary obj.
|
||||
""",
|
||||
body="""\
|
||||
self.edited_objects[parent] = obj
|
||||
|
||||
cur_page = False
|
||||
is_manager = isinstance(self, PropertyGridManager)
|
||||
|
||||
if not parent:
|
||||
if is_manager:
|
||||
page = self.GetCurrentPage()
|
||||
page.Clear()
|
||||
parent = page.GetRoot()
|
||||
else:
|
||||
self.Clear()
|
||||
parent = self.GetGrid().GetRoot()
|
||||
else:
|
||||
it = self.GetIterator(PG_ITERATE_PROPERTIES, parent)
|
||||
it.Next() # Skip the parent
|
||||
while not it.AtEnd():
|
||||
p = it.GetProperty()
|
||||
if not p.IsSomeParent(parent):
|
||||
break
|
||||
|
||||
self.DeleteProperty(p)
|
||||
|
||||
name = p.GetName()
|
||||
it.Next()
|
||||
|
||||
if not is_manager or page == self.GetCurrentPage():
|
||||
self.Freeze()
|
||||
cur_page = True
|
||||
|
||||
try:
|
||||
self._AutoFillMany(parent,obj.__dict__)
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
if cur_page:
|
||||
self.Thaw()
|
||||
""")
|
||||
|
||||
|
||||
c.addPyMethod('RegisterEditor', '(self, editor, editorName=None)',
|
||||
doc="Register a new editor, either an instance or a class.",
|
||||
body="""\
|
||||
if not isinstance(editor, PGEditor):
|
||||
editor = editor()
|
||||
if not editorName:
|
||||
editorName = editor.__class__.__name__
|
||||
try:
|
||||
self._editor_instances.append(editor)
|
||||
except:
|
||||
self._editor_instances = [editor]
|
||||
return PropertyGrid.DoRegisterEditorClass(editor, editorName)
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
c.find('GetPropertyClientData').ignore()
|
||||
c.addPyMethod('GetPropertyClientData', '(self, p)',
|
||||
body="""\
|
||||
if isinstance(p, str):
|
||||
p = self.GetPropertyByName(p)
|
||||
return p.GetClientData()
|
||||
""")
|
||||
|
||||
c.find('SetPropertyClientData').ignore()
|
||||
c.addPyMethod('SetPropertyClientData', '(self, p, data)',
|
||||
body="""\
|
||||
if isinstance(p, str):
|
||||
p = self.GetPropertyByName(p)
|
||||
return p.SetClientData(data)
|
||||
""")
|
||||
|
||||
|
||||
|
||||
c.addPyMethod('GetPyIterator', '(self, flags=PG_ITERATE_DEFAULT, firstProperty=None)',
|
||||
doc="""\
|
||||
Returns a pythonic property iterator for a single :ref:`PropertyGrid`
|
||||
or page in :ref:`PropertyGridManager`. Arguments are same as for
|
||||
:ref:`GetIterator`.
|
||||
|
||||
The following example demonstrates iterating absolutely all items in
|
||||
a single grid::
|
||||
|
||||
iterator = propGrid.GetPyIterator(wx.propgrid.PG_ITERATE_ALL)
|
||||
for prop in iterator:
|
||||
print(prop)
|
||||
|
||||
:see: `wx.propgrid.PropertyGridInterface.Properties`
|
||||
`wx.propgrid.PropertyGridInterface.Items`
|
||||
""",
|
||||
body="""\
|
||||
it = self.GetIterator(flags, firstProperty)
|
||||
while not it.AtEnd():
|
||||
yield it.GetProperty()
|
||||
it.Next()
|
||||
""")
|
||||
|
||||
|
||||
c.addPyMethod('GetPyVIterator', '(self, flags=PG_ITERATE_DEFAULT)',
|
||||
doc="""\
|
||||
Similar to :ref:`GetVIterator` but returns a pythonic iterator.
|
||||
""",
|
||||
body="""\
|
||||
it = self.GetVIterator(flags)
|
||||
while not it.AtEnd():
|
||||
yield it.GetProperty()
|
||||
it.Next()
|
||||
""")
|
||||
|
||||
|
||||
c.addPyMethod('_Properties', '(self)',
|
||||
doc="""\
|
||||
This attribute is a pythonic iterator over all properties in
|
||||
this `PropertyGrid` property container. It will only skip
|
||||
categories and private child properties. Usage is simple::
|
||||
|
||||
for prop in propGrid.Properties:
|
||||
print(prop)
|
||||
|
||||
:see: `wx.propgrid.PropertyGridInterface.Items`
|
||||
`wx.propgrid.PropertyGridInterface.GetPyIterator`
|
||||
""",
|
||||
body="""\
|
||||
it = self.GetIterator(PG_ITERATE_NORMAL)
|
||||
while not it.AtEnd():
|
||||
yield it.GetProperty()
|
||||
it.Next()
|
||||
""")
|
||||
c.addPyProperty('Properties', '_Properties')
|
||||
|
||||
|
||||
c.addPyMethod('_Items', '(self)',
|
||||
doc="""\
|
||||
This attribute is a pythonic iterator over all items in this
|
||||
`PropertyGrid` property container, excluding only private child
|
||||
properties. Usage is simple::
|
||||
|
||||
for prop in propGrid.Items:
|
||||
print(prop)
|
||||
|
||||
:see: `wx.propgrid.PropertyGridInterface.Properties`
|
||||
`wx.propgrid.PropertyGridInterface.GetPyVIterator`
|
||||
""",
|
||||
body="""\
|
||||
it = self.GetVIterator(PG_ITERATE_NORMAL | PG_ITERATE_CATEGORIES)
|
||||
while not it.AtEnd():
|
||||
yield it.GetProperty()
|
||||
it.Next()
|
||||
""")
|
||||
c.addPyProperty('Items', '_Items')
|
||||
|
||||
|
||||
#----------------------------------------------------------
|
||||
|
||||
module.addItem(
|
||||
tools.wxArrayPtrWrapperTemplate('wxArrayPGProperty', 'wxPGProperty', module))
|
||||
|
||||
|
||||
|
||||
# wxPGPropArg is a typedef for "const wxPGPropArgCls&" so having the
|
||||
# wrappers treat it as a normal type can be problematic. ("new cannot be
|
||||
# applied to a reference type", etc.) Let's just ignore it an replace it
|
||||
# applied to a reference type", etc.) Let's just ignore it and replace it
|
||||
# everywhere for the real type.
|
||||
module.find('wxPGPropArg').ignore()
|
||||
for item in module.allItems():
|
||||
@@ -63,6 +488,14 @@ def run():
|
||||
item.type = 'const wxPGPropArgCls &'
|
||||
|
||||
|
||||
# Switch all wxVariant types to wxPGVariant, so the propgrid-specific
|
||||
# version of the MappedType will be used for converting to/from Python
|
||||
# objects.
|
||||
for item in module.allItems():
|
||||
if hasattr(item, 'type') and 'wxVariant' in item.type:
|
||||
item.type = item.type.replace('wxVariant', 'wxPGVariant')
|
||||
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
tools.doCommonTweaks(module)
|
||||
tools.runGenerators(module)
|
||||
|
||||
@@ -45,6 +45,23 @@ def run():
|
||||
tools.ignoreConstOverloads(c)
|
||||
|
||||
|
||||
# Add some extra Python code to be executed when a wxPropertyGridManager
|
||||
# is constructed. In Classic with SWIG we did this with %pythonAppend, is
|
||||
# there any better way to do it with sip than monkey-patching?
|
||||
c.addPyCode("""\
|
||||
_PropertyGridManager__init__orig = PropertyGridManager.__init__
|
||||
def _PropertyGridManager__init__(self, *args, **kw):
|
||||
_PropertyGridManager__init__orig(self, *args, **kw)
|
||||
self.DoDefaultTypeMappings()
|
||||
self.edited_objects = {}
|
||||
self.DoDefaultValueTypeMappings()
|
||||
if not hasattr(self.__class__, '_vt2setter'):
|
||||
self.__class__._vt2setter = {}
|
||||
PropertyGridManager.__init__ = _PropertyGridManager__init__
|
||||
""")
|
||||
|
||||
|
||||
|
||||
# wxPGPropArg is a typedef for "const wxPGPropArgCls&" so having the
|
||||
# wrappers treat it as a normal type can be problematic. ("new cannot be
|
||||
# applied to a reference type", etc.) Let's just ignore it an replace it
|
||||
|
||||
@@ -20,7 +20,6 @@ DOCSTRING = ""
|
||||
ITEMS = [ 'wxPropertyGridHitTestResult',
|
||||
'wxPropertyGridIteratorBase',
|
||||
'wxPropertyGridIterator',
|
||||
#'wxPropertyGridConstIterator', # probably not needed in Python...
|
||||
'wxPGVIterator',
|
||||
'wxPropertyGridPageState',
|
||||
]
|
||||
@@ -52,6 +51,13 @@ def run():
|
||||
module.find('wxPG_IT_CHILDREN').ignore()
|
||||
|
||||
|
||||
# Switch all wxVariant types to wxPGVariant, so the propgrid-specific
|
||||
# version of the MappedType will be used for converting to/from Python
|
||||
# objects.
|
||||
for item in module.allItems():
|
||||
if hasattr(item, 'type') and 'wxVariant' in item.type:
|
||||
item.type = item.type.replace('wxVariant', 'wxPGVariant')
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
tools.doCommonTweaks(module)
|
||||
tools.runGenerators(module)
|
||||
|
||||
@@ -22,7 +22,6 @@ ITEMS = [ 'wxPGPaintData',
|
||||
'wxPGDefaultRenderer',
|
||||
'wxPGCellData',
|
||||
'wxPGCell',
|
||||
'wxPGAttributeStorage',
|
||||
|
||||
'wxPGProperty',
|
||||
'wxPropertyCategory',
|
||||
@@ -45,13 +44,10 @@ def run():
|
||||
c = module.find('wxPGCellData')
|
||||
assert isinstance(c, etgtools.ClassDef)
|
||||
c.find('~wxPGCellData').ignore(False)
|
||||
c.bases = ['wxRefCounter']
|
||||
|
||||
|
||||
c = module.find('wxPGAttributeStorage')
|
||||
# TODO: Add methods to add a Python iterator using these methods
|
||||
c.find('StartIteration').ignore()
|
||||
c.find('GetNext').ignore()
|
||||
c.find('const_iterator').ignore()
|
||||
c = module.find('wxPGCellRenderer')
|
||||
c.bases = ['wxRefCounter']
|
||||
|
||||
|
||||
c = module.find('wxPGProperty')
|
||||
@@ -59,18 +55,62 @@ def run():
|
||||
c.find('StringToValue.variant').out = True
|
||||
c.find('IntToValue.variant').out = True
|
||||
|
||||
# TODO: Some other wxPGProperty methods should be pythonized a bit...
|
||||
# SIP needs to be able to make a copy of the wxPGAttributeStorage value
|
||||
# but the C++ class doesn't have a copy ctor and the default will cause it
|
||||
# to lose references to the variants it contains, so let's just override
|
||||
# the use of the MappedType and convert it to a Python dictionary here
|
||||
# instead.
|
||||
m = c.find('GetAttributes')
|
||||
m.type = 'PyObject*'
|
||||
m.setCppCode("""\
|
||||
const wxPGAttributeStorage& attrs = self->GetAttributes();
|
||||
wxPGAttributeStorage::const_iterator it = attrs.StartIteration();
|
||||
wxVariant v;
|
||||
wxPyThreadBlocker blocker;
|
||||
|
||||
PyObject* dict = PyDict_New();
|
||||
if ( !dict ) return NULL;
|
||||
|
||||
while ( attrs.GetNext( it, v ) ) {
|
||||
const wxString& name = v.GetName();
|
||||
PyObject* pyStr = wx2PyString(name);
|
||||
PyObject* pyVal = wxPGVariant_out_helper(v);
|
||||
int res = PyDict_SetItem( dict, pyStr, pyVal );
|
||||
}
|
||||
return dict;
|
||||
""")
|
||||
|
||||
# SetAttributes uses wxPGAttributeStorage too, but we'll just replace it
|
||||
# with a simple Python method.
|
||||
c.find('SetAttributes').ignore()
|
||||
c.addPyMethod('SetAttributes', '(self, attributes)',
|
||||
doc="Set the property's attributes from a Python dictionary.",
|
||||
body="""\
|
||||
for name,value in attributes.items():
|
||||
self.SetAttribute(name, value)
|
||||
""")
|
||||
|
||||
|
||||
c = module.find('wxPGChoicesData')
|
||||
tools.ignoreConstOverloads(c)
|
||||
#c.addDtor()
|
||||
c.bases = ['wxRefCounter']
|
||||
c.find('~wxPGChoicesData').ignore(False)
|
||||
|
||||
|
||||
c = module.find('wxPGChoices')
|
||||
c.find('wxPGChoices').findOverload('wxChar **').ignore()
|
||||
tools.ignoreConstOverloads(c)
|
||||
c.find('operator[]').ignore()
|
||||
|
||||
c.addPyMethod('__getitem__', '(self, index)',
|
||||
doc="Returns a reference to a :class:PGChoiceEntry using Python list syntax.",
|
||||
body="return self.Item(index)",
|
||||
)
|
||||
c.addPyMethod('__len__', '(self)',
|
||||
doc="",
|
||||
body="return self.GetCount()",
|
||||
)
|
||||
|
||||
|
||||
# Ignore some string constants (#defines) coming from dox, and add them
|
||||
# back in Python code. They are wchar_t* values and this seemed the
|
||||
@@ -147,6 +187,13 @@ def run():
|
||||
""")
|
||||
|
||||
|
||||
# Switch all wxVariant types to wxPGVariant, so the propgrid-specific
|
||||
# version of the MappedType will be used for converting to/from Python
|
||||
# objects.
|
||||
for item in module.allItems():
|
||||
if hasattr(item, 'type') and 'wxVariant' in item.type:
|
||||
item.type = item.type.replace('wxVariant', 'wxPGVariant')
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
tools.doCommonTweaks(module)
|
||||
tools.runGenerators(module)
|
||||
|
||||
@@ -91,6 +91,13 @@ def run():
|
||||
tools.fixWindowClass(c, hideVirtuals=False, ignoreProtected=False)
|
||||
|
||||
|
||||
# Switch all wxVariant types to wxPGVariant, so the propgrid-specific
|
||||
# version of the MappedType will be used for converting to/from Python
|
||||
# objects.
|
||||
for item in module.allItems():
|
||||
if hasattr(item, 'type') and 'wxVariant' in item.type:
|
||||
item.type = item.type.replace('wxVariant', 'wxPGVariant')
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
tools.doCommonTweaks(module)
|
||||
tools.runGenerators(module)
|
||||
|
||||
@@ -301,8 +301,8 @@ class FunctionDef(BaseDef, FixWxPrefix):
|
||||
info we've already received from the source XML such as the argument
|
||||
types and names, docstring, etc.
|
||||
|
||||
The code generated for this verison will expect the given code to use
|
||||
SIP specfic variable names, etc. For example::
|
||||
The code generated for this version will expect the given code to use
|
||||
SIP specific variable names, etc. For example::
|
||||
|
||||
sipRes = sipCpp->Foo();
|
||||
"""
|
||||
@@ -918,7 +918,7 @@ class ClassDef(BaseDef):
|
||||
monkey-patched into the class. (This property will also be
|
||||
jammed in to the class in like manner.)
|
||||
"""
|
||||
# Read the nice comment in the function above. Ditto.
|
||||
# Read the nice comment in the method above. Ditto.
|
||||
if len(args) == 1:
|
||||
name = getter = setter = ''
|
||||
split = args[0].split()
|
||||
@@ -1525,11 +1525,11 @@ class ModuleDef(BaseDef):
|
||||
return md
|
||||
|
||||
|
||||
def addPyCode(self, code, order=None):
|
||||
def addPyCode(self, code, order=None, **kw):
|
||||
"""
|
||||
Add a snippet of Python code to the wrapper module.
|
||||
"""
|
||||
pc = PyCodeDef(code, order)
|
||||
pc = PyCodeDef(code, order, **kw)
|
||||
self.items.append(pc)
|
||||
return pc
|
||||
|
||||
|
||||
Submodule ext/wxWidgets updated: dc7acca2cd...6eb5943ed0
209
src/pgvariant.sip
Normal file
209
src/pgvariant.sip
Normal file
@@ -0,0 +1,209 @@
|
||||
//--------------------------------------------------------------------------
|
||||
// Name: pgvariant.sip
|
||||
// Purpose: MappedType for wxPGVariant
|
||||
//
|
||||
// Author: Robin Dunn
|
||||
//
|
||||
// Created: 24-Feb-2017
|
||||
// Copyright: (c) 2017 by Total Control Software
|
||||
// Licence: wxWindows license
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
%ModuleHeaderCode
|
||||
// A wxPGVariant is really the same thing as a wxVariant. We just create
|
||||
// this new type so a different %MappedType can be created for it that
|
||||
// also supports the variant data types that are in the propgrid APIs
|
||||
// instead of core.
|
||||
typedef wxVariant wxPGVariant;
|
||||
typedef wxVariantList wxPGVariantList;
|
||||
|
||||
wxVariant wxPGVariant_in_helper(PyObject* source);
|
||||
PyObject* wxPGVariant_out_helper(const wxVariant& value);
|
||||
%End
|
||||
|
||||
|
||||
%ModuleCode
|
||||
wxVariant wxPGVariant_in_helper(PyObject* obj)
|
||||
{
|
||||
wxVariant value;
|
||||
int state = 0;
|
||||
int isErr = 0;
|
||||
|
||||
// Always check for None first so we don't just get NULL pointers for the
|
||||
// other types.
|
||||
if (obj == Py_None)
|
||||
value.MakeNull();
|
||||
|
||||
else if (wxPyWrappedPtr_TypeCheck(obj, wxT("wxFont"))) {
|
||||
wxFont* ptr;
|
||||
wxPyConvertWrappedPtr(obj, (void**)&ptr, wxT("wxFont"));
|
||||
value << *ptr;
|
||||
}
|
||||
|
||||
else if (wxPyWrappedPtr_TypeCheck(obj, wxT("wxPoint"))) {
|
||||
wxPoint* ptr;
|
||||
wxPyConvertWrappedPtr(obj, (void**)&ptr, wxT("wxPoint"));
|
||||
value << *ptr;
|
||||
}
|
||||
|
||||
else if (wxPyWrappedPtr_TypeCheck(obj, wxT("wxSize"))) {
|
||||
wxSize* ptr;
|
||||
wxPyConvertWrappedPtr(obj, (void**)&ptr, wxT("wxSize"));
|
||||
value << *ptr;
|
||||
}
|
||||
|
||||
else if (wxPyWrappedPtr_TypeCheck(obj, wxT("wxColourPropertyValue"))) {
|
||||
wxColourPropertyValue* ptr;
|
||||
wxPyConvertWrappedPtr(obj, (void**)&ptr, wxT("wxColourPropertyValue"));
|
||||
value << *ptr;
|
||||
}
|
||||
|
||||
else if (sipCanConvertToType(obj, sipType_wxArrayInt, 0)) {
|
||||
wxArrayInt* ptr;
|
||||
ptr = (wxArrayInt*)sipConvertToType(obj, sipType_wxArrayInt, NULL, 0, &state, &isErr);
|
||||
value << *ptr;
|
||||
sipReleaseType(ptr, sipType_wxArrayInt, state);
|
||||
}
|
||||
|
||||
else
|
||||
value = wxVariant_in_helper(obj);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
PyObject* wxPGVariant_out_helper(const wxVariant& value)
|
||||
{
|
||||
PyObject* obj;
|
||||
|
||||
|
||||
if (value.IsNull()) {
|
||||
obj = Py_None;
|
||||
Py_INCREF(obj);
|
||||
}
|
||||
|
||||
else if ( value.IsType("wxFont") ) {
|
||||
wxFont val;
|
||||
val << value;
|
||||
obj = wxPyConstructObject(new wxFont(val), "wxFont", true);
|
||||
}
|
||||
|
||||
else if ( value.IsType("wxPoint") ) {
|
||||
const wxPoint& val = wxPointRefFromVariant(value);
|
||||
obj = wxPyConstructObject(new wxPoint(val), "wxPoint", true);
|
||||
}
|
||||
|
||||
else if ( value.IsType("wxSize") ) {
|
||||
const wxSize& val = wxSizeRefFromVariant(value);
|
||||
obj = wxPyConstructObject(new wxSize(val), "wxSize", true);
|
||||
}
|
||||
|
||||
else if ( value.IsType("wxColourPropertyValue") ) {
|
||||
wxColourPropertyValue val;
|
||||
val << value;
|
||||
obj = wxPyConstructObject(new wxColourPropertyValue(val), "wxColourPropertyValue", true);
|
||||
}
|
||||
|
||||
else if ( value.IsType("wxArrayInt") ) {
|
||||
const wxArrayInt& arr = wxArrayIntRefFromVariant(value);
|
||||
obj = sipConvertFromType((void*)&arr, sipType_wxArrayInt, NULL);
|
||||
}
|
||||
|
||||
else
|
||||
obj = wxVariant_out_helper(value);
|
||||
return obj;
|
||||
}
|
||||
%End
|
||||
|
||||
|
||||
|
||||
%MappedType wxPGVariant /AllowNone/
|
||||
{
|
||||
%ConvertToTypeCode
|
||||
// Code to test a PyObject for compatibility.
|
||||
if (!sipIsErr) {
|
||||
// Any type should work since we'll just use the PyObject directly
|
||||
// if the type is not one that is explicitly supported.
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Code to create a new wxVariant from the PyObject
|
||||
wxVariant* value = new wxVariant(wxPGVariant_in_helper(sipPy));
|
||||
*sipCppPtr = value;
|
||||
return sipGetState(sipTransferObj);
|
||||
%End
|
||||
|
||||
|
||||
%ConvertFromTypeCode
|
||||
// Code to convert a wxVariant to a PyObject.
|
||||
if (sipCpp == NULL) {
|
||||
return Py_None;
|
||||
} else {
|
||||
return wxPGVariant_out_helper(*sipCpp);
|
||||
}
|
||||
%End
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Add a typemap for wxVariantList
|
||||
%MappedType wxPGVariantList
|
||||
{
|
||||
%ConvertToTypeCode
|
||||
// Code to test a PyObject for compatibility.
|
||||
if (!sipIsErr) {
|
||||
// Any type sequence type is okay.
|
||||
int success = PySequence_Check(sipPy);
|
||||
if (!success)
|
||||
PyErr_SetString(PyExc_TypeError, "Sequence type expected.");
|
||||
return success;
|
||||
}
|
||||
|
||||
// Code to create a new wxVariantList from the PyObject sequence
|
||||
wxVariantList* value = new wxVariantList();
|
||||
Py_ssize_t len = PySequence_Length(sipPy);
|
||||
Py_ssize_t idx = 0;
|
||||
while (idx < len) {
|
||||
PyObject* item = PySequence_GetItem(sipPy, idx);
|
||||
value->Append(new wxVariant(wxPGVariant_in_helper(item)));
|
||||
Py_DECREF(item);
|
||||
}
|
||||
*sipCppPtr = value;
|
||||
return sipGetState(sipTransferObj);
|
||||
%End
|
||||
|
||||
|
||||
%ConvertFromTypeCode
|
||||
// Code to convert a wxVariantList to a Python list.
|
||||
if (sipCpp == NULL) {
|
||||
return Py_None;
|
||||
} else {
|
||||
size_t idx = 0;
|
||||
PyObject* value = PyList_New(0);
|
||||
for (idx=0; idx < sipCpp->GetCount(); idx++) {
|
||||
PyObject* item = wxPGVariant_out_helper(sipCpp->Item(idx));
|
||||
PyList_Append(value, item);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
%End
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Used just for unit testing the MappedType code, it can be removed later
|
||||
%ModuleCode
|
||||
wxPGVariant testPGVariantTypemap(const wxPGVariant& var)
|
||||
{
|
||||
wxVariant local = var; // force a copy
|
||||
return local;
|
||||
}
|
||||
|
||||
wxString testPGVariantTypeName(const wxPGVariant& var)
|
||||
{
|
||||
return var.GetType();
|
||||
}
|
||||
%End
|
||||
wxPGVariant testPGVariantTypemap(const wxPGVariant& var);
|
||||
wxString testPGVariantTypeName(const wxPGVariant& var);
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
// We always convert wxVariant to / from the native Python types since its purpose
|
||||
// is basically to allow a variable to be multiple types in C++
|
||||
%MappedType wxVariant
|
||||
%MappedType wxVariant /AllowNone/
|
||||
{
|
||||
%ConvertToTypeCode
|
||||
// Code to test a PyObject for compatibility.
|
||||
@@ -88,12 +88,18 @@
|
||||
|
||||
|
||||
|
||||
// Used just for unittesting the MappedType code, it can be removed later
|
||||
// Used just for unit testing the MappedType code, it can be removed later
|
||||
%ModuleCode
|
||||
wxVariant testVariantTypemap(const wxVariant& var)
|
||||
{
|
||||
wxVariant local = var; // force a copy
|
||||
return local;
|
||||
}
|
||||
|
||||
wxString testVariantTypeName(const wxVariant& var)
|
||||
{
|
||||
return var.GetType();
|
||||
}
|
||||
%End
|
||||
wxVariant testVariantTypemap(const wxVariant& var);
|
||||
wxString testVariantTypeName(const wxVariant& var);
|
||||
|
||||
105
src/wxpy_api.sip
105
src/wxpy_api.sip
@@ -95,6 +95,10 @@ static wxString i_Py2wxString(PyObject* source)
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Wrapped object checks and converters
|
||||
//
|
||||
// TODO: Add some versions of these helpers that take a sipTypeDef
|
||||
// instead of a name? They're accessible everywhere we need them, and
|
||||
// it may be enough of an efficiency boost to make it worth it.
|
||||
|
||||
// Create a PyObject of the requested type from a void* and a class name.
|
||||
static PyObject* i_wxPyConstructObject(void* ptr,
|
||||
@@ -121,6 +125,7 @@ static bool i_wxPyWrappedPtr_Check(PyObject* obj)
|
||||
return PyObject_TypeCheck(obj, sipWrapper_Type);
|
||||
}
|
||||
|
||||
|
||||
// Check if a PyObject is a specific wrapped class or subclass
|
||||
static bool i_wxPyWrappedPtr_TypeCheck(PyObject* obj, const wxString& className)
|
||||
{
|
||||
@@ -130,6 +135,7 @@ static bool i_wxPyWrappedPtr_TypeCheck(PyObject* obj, const wxString& className)
|
||||
return sipCanConvertToType(obj, td, SIP_NO_CONVERTORS);
|
||||
}
|
||||
|
||||
|
||||
// Convert a wrapped SIP object to its C++ pointer, ensuring that it is of the expected type
|
||||
static bool i_wxPyConvertWrappedPtr(PyObject* obj, void **ptr, const wxString& className)
|
||||
{
|
||||
@@ -143,6 +149,7 @@ static bool i_wxPyConvertWrappedPtr(PyObject* obj, void **ptr, const wxString& c
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Deal with the GIL
|
||||
|
||||
@@ -269,7 +276,7 @@ bool wxVariantDataPyObject::Eq(wxVariantData& data) const
|
||||
//
|
||||
// These functions are here in the API so they can be used by both the
|
||||
// wxVariant MappedType and by other classes or types that want to add support
|
||||
// for additional kinds of nativly supported types (see dataview for example.)
|
||||
// for additional kinds of natively supported types (see dataview for example.)
|
||||
|
||||
// PyObject --> wxVariant
|
||||
wxVariant i_wxVariant_in_helper(PyObject* obj)
|
||||
@@ -278,30 +285,66 @@ wxVariant i_wxVariant_in_helper(PyObject* obj)
|
||||
|
||||
if (PyBytes_Check(obj) || PyUnicode_Check(obj))
|
||||
value = Py2wxString(obj);
|
||||
|
||||
else if (PyBool_Check(obj))
|
||||
value = (obj == Py_True);
|
||||
|
||||
else if (wxPyInt_Check(obj))
|
||||
value = (long)wxPyInt_AS_LONG(obj);
|
||||
|
||||
else if (PyLong_Check(obj))
|
||||
value = (long)PyLong_AsLong(obj);
|
||||
|
||||
else if (PyFloat_Check(obj))
|
||||
value = PyFloat_AS_DOUBLE(obj);
|
||||
else if (wxPyWrappedPtr_TypeCheck(obj, wxT("wxDateTime"))) {
|
||||
|
||||
else if (obj == Py_None)
|
||||
value.MakeNull();
|
||||
|
||||
else if (sipCanConvertToType(obj, sipType_wxDateTime, 0)) {
|
||||
wxDateTime* ptr;
|
||||
wxPyConvertWrappedPtr(obj, (void**)&ptr, wxT("wxDateTime"));
|
||||
int state = 0;
|
||||
int isErr = 0;
|
||||
ptr = (wxDateTime*)sipConvertToType(obj, sipType_wxDateTime, NULL, 0, &state, &isErr);
|
||||
value = *ptr;
|
||||
sipReleaseType(ptr, sipType_wxDateTime, state);
|
||||
}
|
||||
|
||||
else if (wxPyWrappedPtr_TypeCheck(obj, wxT("wxBitmap"))) {
|
||||
wxBitmap* ptr;
|
||||
wxPyConvertWrappedPtr(obj, (void**)&ptr, wxT("wxBitmap"));
|
||||
value << *ptr;
|
||||
}
|
||||
|
||||
else if (wxPyWrappedPtr_TypeCheck(obj, wxT("wxImage"))) {
|
||||
wxImage* ptr;
|
||||
wxPyConvertWrappedPtr(obj, (void**)&ptr, wxT("wxImage"));
|
||||
value << *ptr;
|
||||
}
|
||||
|
||||
else if (wxPyWrappedPtr_TypeCheck(obj, wxT("wxIcon"))) {
|
||||
wxIcon* ptr;
|
||||
wxPyConvertWrappedPtr(obj, (void**)&ptr, wxT("wxIcon"));
|
||||
value <<*ptr;
|
||||
value << *ptr;
|
||||
}
|
||||
|
||||
else if (wxPyWrappedPtr_TypeCheck(obj, wxT("wxColour"))) {
|
||||
wxColour* ptr;
|
||||
wxPyConvertWrappedPtr(obj, (void**)&ptr, wxT("wxColour"));
|
||||
value << *ptr;
|
||||
}
|
||||
|
||||
else if (sipCanConvertToType(obj, sipType_wxArrayString, 0)) {
|
||||
wxArrayString* ptr;
|
||||
int state = 0;
|
||||
int isErr = 0;
|
||||
ptr = (wxArrayString*)sipConvertToType(obj, sipType_wxArrayString, NULL, 0, &state, &isErr);
|
||||
value = *ptr;
|
||||
sipReleaseType(ptr, sipType_wxArrayString, state);
|
||||
}
|
||||
|
||||
else
|
||||
// Just use the PyObject itself
|
||||
value = new wxVariantDataPyObject(obj);
|
||||
|
||||
return value;
|
||||
@@ -313,42 +356,68 @@ PyObject* i_wxVariant_out_helper(const wxVariant& value)
|
||||
{
|
||||
PyObject* obj;
|
||||
|
||||
if (value.IsType("string"))
|
||||
if (value.IsNull()) {
|
||||
obj = Py_None;
|
||||
Py_INCREF(obj);
|
||||
}
|
||||
|
||||
else if (value.IsType("string"))
|
||||
obj = wx2PyString(value.GetString());
|
||||
|
||||
else if (value.IsType("bool"))
|
||||
obj = PyBool_FromLong((long)value.GetBool());
|
||||
|
||||
else if (value.IsType("long"))
|
||||
obj = PyLong_FromLong(value.GetLong());
|
||||
|
||||
else if (value.IsType("double"))
|
||||
obj = PyFloat_FromDouble(value.GetDouble());
|
||||
else if ( value.IsType("datetime") )
|
||||
{
|
||||
|
||||
else if ( value.IsType("datetime") ) {
|
||||
wxDateTime val = value.GetDateTime();
|
||||
obj = wxPyConstructObject(new wxDateTime(val), wxT("wxDateTime"));
|
||||
obj = wxPyConstructObject(new wxDateTime(val), "wxDateTime", true);
|
||||
}
|
||||
else if ( value.IsType("wxBitmap") )
|
||||
{
|
||||
|
||||
else if ( value.IsType("wxBitmap") ) {
|
||||
wxBitmap val;
|
||||
val << value;
|
||||
obj = wxPyConstructObject(new wxBitmap(val), wxT("wxBitmap"));
|
||||
obj = wxPyConstructObject(new wxBitmap(val), "wxBitmap", true);
|
||||
}
|
||||
else if ( value.IsType("wxIcon") )
|
||||
{
|
||||
|
||||
else if ( value.IsType("wxImage") ) {
|
||||
wxImage val;
|
||||
val << value;
|
||||
obj = wxPyConstructObject(new wxImage(val), "wxImage", true);
|
||||
}
|
||||
|
||||
else if ( value.IsType("wxIcon") ) {
|
||||
wxIcon val;
|
||||
val << value;
|
||||
obj = wxPyConstructObject(new wxIcon(val), wxT("wxIcon"));
|
||||
obj = wxPyConstructObject(new wxIcon(val), "wxIcon", true);
|
||||
}
|
||||
else if ( value.IsType("PyObject") )
|
||||
{
|
||||
|
||||
else if ( value.IsType("wxColour") ) {
|
||||
wxColour val;
|
||||
val << value;
|
||||
obj = wxPyConstructObject(new wxColour(val), "wxColour", true);
|
||||
}
|
||||
|
||||
else if ( value.IsType("arrstring") ) {
|
||||
wxArrayString arr = value.GetArrayString();
|
||||
obj = sipConvertFromType(&arr, sipType_wxArrayString, NULL);
|
||||
}
|
||||
|
||||
else if ( value.IsType("PyObject") ) {
|
||||
wxVariantDataPyObject* data = (wxVariantDataPyObject*)value.GetData();
|
||||
obj = data->GetData();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
else {
|
||||
wxString msg = "Unexpected type (\"" + value.GetType() + "\") in wxVariant.";
|
||||
wxPyErr_SetString(PyExc_TypeError, msg.mb_str());
|
||||
obj = NULL;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
87
unittests/test_pgvariant.py
Normal file
87
unittests/test_pgvariant.py
Normal file
@@ -0,0 +1,87 @@
|
||||
import unittest
|
||||
from unittests import wtc
|
||||
import wx
|
||||
import wx.propgrid as pg
|
||||
|
||||
import six
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
class pgvariant_Tests(wtc.WidgetTestCase):
|
||||
|
||||
|
||||
@unittest.skipIf(not hasattr(pg, 'testPGVariantTypemap'), '')
|
||||
def test_pgvariant1(self):
|
||||
d1 = wx.Point(123,456)
|
||||
d2 = pg.testPGVariantTypemap(d1)
|
||||
assert isinstance(d2, wx.Point)
|
||||
assert d1 == d2
|
||||
|
||||
@unittest.skipIf(not hasattr(pg, 'testPGVariantTypeName'), '')
|
||||
def test_pgvariant2(self):
|
||||
d1 = wx.Point(123,456)
|
||||
assert pg.testPGVariantTypeName(d1) == 'wxPoint'
|
||||
|
||||
|
||||
|
||||
@unittest.skipIf(not hasattr(pg, 'testPGVariantTypemap'), '')
|
||||
def test_pgvariant3(self):
|
||||
d1 = wx.Size(123,456)
|
||||
d2 = pg.testPGVariantTypemap(d1)
|
||||
assert isinstance(d2, wx.Size)
|
||||
assert d1 == d2
|
||||
|
||||
@unittest.skipIf(not hasattr(pg, 'testPGVariantTypeName'), '')
|
||||
def test_pgvariant4(self):
|
||||
d1 = wx.Size(123,456)
|
||||
assert pg.testPGVariantTypeName(d1) == 'wxSize'
|
||||
|
||||
|
||||
|
||||
@unittest.skipIf(not hasattr(pg, 'testPGVariantTypemap'), '')
|
||||
def test_pgvariant5(self):
|
||||
d1 = wx.Font( wx.FontInfo(10).Bold().Underlined() )
|
||||
d2 = pg.testPGVariantTypemap(d1)
|
||||
assert isinstance(d2, wx.Font)
|
||||
assert d2.PointSize == 10
|
||||
|
||||
@unittest.skipIf(not hasattr(pg, 'testPGVariantTypeName'), '')
|
||||
def test_pgvariant6(self):
|
||||
d1 = wx.Font( wx.FontInfo(10).Bold().Underlined() )
|
||||
assert pg.testPGVariantTypeName(d1) == 'wxFont'
|
||||
|
||||
|
||||
|
||||
@unittest.skipIf(not hasattr(pg, 'testPGVariantTypemap'), '')
|
||||
def test_pgvariant7(self):
|
||||
d1 = [0,1,2,3,4,5,6,7,8,9]
|
||||
d2 = pg.testPGVariantTypemap(d1)
|
||||
assert isinstance(d2, list)
|
||||
assert d1 == d2
|
||||
|
||||
d1 = (123,456)
|
||||
d2 = pg.testPGVariantTypemap(d1)
|
||||
assert isinstance(d2, list)
|
||||
assert list(d1) == d2
|
||||
|
||||
@unittest.skipIf(not hasattr(pg, 'testPGVariantTypeName'), '')
|
||||
def test_pgvariant8(self):
|
||||
d1 = [0,1,2,3,4,5,6,7,8,9]
|
||||
assert pg.testPGVariantTypeName(d1) == 'wxArrayInt'
|
||||
|
||||
d1 = (123,456)
|
||||
assert pg.testPGVariantTypeName(d1) == 'wxArrayInt'
|
||||
|
||||
|
||||
|
||||
@unittest.skipIf(not hasattr(pg, 'testPGVariantTypemap'), '')
|
||||
def test_pgvariant9(self):
|
||||
d1 = None
|
||||
d2 = pg.testPGVariantTypemap(d1)
|
||||
self.assertTrue(d2 is None)
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
51
unittests/test_propgriddefs.py
Normal file
51
unittests/test_propgriddefs.py
Normal file
@@ -0,0 +1,51 @@
|
||||
import unittest
|
||||
from unittests import wtc
|
||||
import wx
|
||||
import wx.propgrid as pg
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
class propgriddefs_Tests(wtc.WidgetTestCase):
|
||||
|
||||
def test_propgriddefs1(self):
|
||||
pg.PG_INVALID_VALUE
|
||||
pg.PG_DONT_RECURSE
|
||||
pg.PG_BASE_OCT
|
||||
pg.PG_BASE_DEC
|
||||
pg.PG_BASE_HEX
|
||||
pg.PG_BASE_HEXL
|
||||
pg.PG_PREFIX_NONE
|
||||
pg.PG_PREFIX_0x
|
||||
pg.PG_PREFIX_DOLLAR_SIGN
|
||||
|
||||
pg.PG_KEEP_STRUCTURE
|
||||
pg.PG_RECURSE
|
||||
pg.PG_INC_ATTRIBUTES
|
||||
pg.PG_RECURSE_STARTS
|
||||
pg.PG_FORCE
|
||||
pg.PG_SORT_TOP_LEVEL_ONLY
|
||||
|
||||
pg.PG_FULL_VALUE
|
||||
pg.PG_REPORT_ERROR
|
||||
pg.PG_PROPERTY_SPECIFIC
|
||||
pg.PG_EDITABLE_VALUE
|
||||
pg.PG_COMPOSITE_FRAGMENT
|
||||
pg.PG_UNEDITABLE_COMPOSITE_FRAGMENT
|
||||
pg.PG_VALUE_IS_CURRENT
|
||||
pg.PG_PROGRAMMATIC_VALUE
|
||||
|
||||
pg.PG_SETVAL_REFRESH_EDITOR
|
||||
pg.PG_SETVAL_AGGREGATED
|
||||
pg.PG_SETVAL_FROM_PARENT
|
||||
pg.PG_SETVAL_BY_USER
|
||||
|
||||
pg.PG_LABEL
|
||||
pg.PG_LABEL_STRING
|
||||
pg.PG_NULL_BITMAP
|
||||
pg.PG_COLOUR_BLACK
|
||||
pg.PG_DEFAULT_IMAGE_SIZE
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -27,6 +27,63 @@ class variant_Tests(wtc.WidgetTestCase):
|
||||
d2 = wx.testVariantTypemap(d1)
|
||||
self.assertEqual(d1, d2)
|
||||
|
||||
@unittest.skipIf(not hasattr(wx, 'testVariantTypemap'), '')
|
||||
def test_variantNone(self):
|
||||
d1 = None
|
||||
d2 = wx.testVariantTypemap(d1)
|
||||
self.assertTrue(d2 is None)
|
||||
|
||||
@unittest.skipIf(not hasattr(wx, 'testVariantTypemap'), '')
|
||||
def test_variantPyObject(self):
|
||||
class Data(object):
|
||||
def __init__(self):
|
||||
self.a = 123
|
||||
d1 = Data()
|
||||
d2 = wx.testVariantTypemap(d1)
|
||||
self.assertTrue(isinstance(d2, Data))
|
||||
self.assertEqual(d2.a, 123)
|
||||
self.assertTrue(d1 is d2)
|
||||
|
||||
|
||||
@unittest.skipIf(not hasattr(wx, 'testVariantTypemap'), '')
|
||||
def test_variantDateTime1(self):
|
||||
d1 = wx.DateTime(1,2,2003, 4,5,6)
|
||||
d2 = wx.testVariantTypemap(d1)
|
||||
self.assertEqual(d1, d2)
|
||||
self.assertTrue(isinstance(d2, wx.DateTime))
|
||||
|
||||
|
||||
@unittest.skipIf(not hasattr(wx, 'testVariantTypemap'), '')
|
||||
def test_variantDateTime2(self):
|
||||
import datetime
|
||||
d1 = datetime.datetime(2003,2,1, 4,5,6)
|
||||
d2 = wx.testVariantTypemap(d1)
|
||||
#print(wx.testVariantTypeName(d1))
|
||||
self.assertTrue(isinstance(d2, wx.DateTime))
|
||||
self.assertEqual(d2.year, 2003)
|
||||
self.assertEqual(d2.month, wx.DateTime.Feb)
|
||||
self.assertEqual(d2.day, 1)
|
||||
self.assertEqual(d2.hour, 4)
|
||||
self.assertEqual(d2.minute, 5)
|
||||
self.assertEqual(d2.second, 6)
|
||||
|
||||
|
||||
@unittest.skipIf(not hasattr(wx, 'testVariantTypemap'), '')
|
||||
def test_variantArrayString1(self):
|
||||
a1 = "This is a test".split()
|
||||
a2 = wx.testVariantTypemap(a1)
|
||||
self.assertEqual(a1, a2)
|
||||
self.assertTrue(isinstance(a2, list))
|
||||
|
||||
|
||||
@unittest.skipIf(not hasattr(wx, 'testVariantTypeName'), '')
|
||||
def test_variantArrayString2(self):
|
||||
a = "This is a test".split()
|
||||
s = wx.testVariantTypeName(a)
|
||||
self.assertEqual(s, "arrstring")
|
||||
|
||||
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user