mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2026-01-04 19:10:09 +01:00
* Add the rest of the wx.DataObject classes and unittests.
* Enable all the important virtual methods to be overridden in Pytyhon subclasses. * Use Python buffer object APIs and objects for data transfer where appropriate. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxPython/Phoenix/trunk@71412 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
1
TODO.txt
1
TODO.txt
@@ -129,7 +129,6 @@ other dev stuff
|
||||
* joystick
|
||||
* sound
|
||||
* mimetype
|
||||
* finish dataobj
|
||||
* power
|
||||
* overlay
|
||||
* PseudoDC
|
||||
|
||||
@@ -319,3 +319,42 @@ other platforms) has been changed to not accept the cursor/icon in the
|
||||
constructors. Instead you'll have to call either SetCursor or SetIcon
|
||||
depending on the platform.
|
||||
|
||||
|
||||
|
||||
wx.DataObject and derived classes
|
||||
---------------------------------
|
||||
|
||||
The wx.DataObject and wx.DataObjectSimple classes can now be
|
||||
subclassed in Python. wx.DataObject will let you proivide complex
|
||||
multi-format data objects that do not need to copy the data until one
|
||||
of the formats is requested from the clipboard or a DnD operation.
|
||||
wx.DataObjectSimple is a simplification that only deals with one data
|
||||
format, (although multiple objects can still be provided with
|
||||
wx.DataObjectComposite.)
|
||||
|
||||
Python buffer objects are used for transferring data to/from the
|
||||
clipboard or DnD partner. Anything that supports the buffer protocol
|
||||
can be used for setting or providing data, and a memoryview object is
|
||||
created for the APIs where the data object should fetch from or copy
|
||||
to a specific memory location. Here is a simple example::
|
||||
|
||||
class MyDataObject(wx.DataObjectSimple):
|
||||
def __init__(self, value=''):
|
||||
wx.DataObjectSimple.__init__(self)
|
||||
self.SetFormat(wx.DataFormat("my data format"))
|
||||
self.myData = bytes(value)
|
||||
|
||||
def GetDataSize(self):
|
||||
return len(self.myData)
|
||||
|
||||
def GetDataHere(self, buf):
|
||||
# copy our local data value to buf
|
||||
assert isinstance(buf, memoryview)
|
||||
buf[:] = self.myData
|
||||
return True
|
||||
|
||||
def SetData(self, buf):
|
||||
# copy from buf to our local data value
|
||||
assert isinstance(buf, memoryview)
|
||||
self.myData = buf.tobytes()
|
||||
return True
|
||||
|
||||
308
etg/dataobj.py
308
etg/dataobj.py
@@ -19,17 +19,86 @@ DOCSTRING = ""
|
||||
# this script.
|
||||
ITEMS = [ 'wxDataFormat',
|
||||
'wxDataObject',
|
||||
#'wxDataObjectSimple',
|
||||
#'wxCustomDataObject',
|
||||
#'wxDataObjectComposite',
|
||||
#'wxBitmapDataObject',
|
||||
#'wxTextDataObject',
|
||||
#'wxURLDataObject',
|
||||
#'wxFileDataObject',
|
||||
'wxDataObjectSimple',
|
||||
'wxCustomDataObject',
|
||||
'wxDataObjectComposite',
|
||||
'wxBitmapDataObject',
|
||||
'wxTextDataObject',
|
||||
'wxURLDataObject',
|
||||
'wxFileDataObject',
|
||||
]
|
||||
|
||||
# TODO: apply some tweaks similar to how Classic implements these classes
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
def addGetAllFormats(klass, pureVirtual=False):
|
||||
# Replace the GetAllFormats method with an implementation that returns
|
||||
# the formats as a Python list
|
||||
m = klass.findItem('GetAllFormats')
|
||||
if m:
|
||||
m.ignore()
|
||||
|
||||
klass.addCppMethod('PyObject*', 'GetAllFormats', '(wxDataObject::Direction dir=wxDataObject::Get)',
|
||||
cppSignature='void (wxDataFormat* formats, Direction dir)',
|
||||
isVirtual=True,
|
||||
isPureVirtual=pureVirtual,
|
||||
isConst=True,
|
||||
doc="""\
|
||||
Returns a list of wx.DataFormat objects which this data object supports
|
||||
transfering in the given direction.""",
|
||||
body="""\
|
||||
size_t count = self->GetFormatCount(dir);
|
||||
wxDataFormat* formats = new wxDataFormat[count];
|
||||
self->GetAllFormats(formats, dir);
|
||||
wxPyBlock_t blocked = wxPyBeginBlockThreads();
|
||||
PyObject* list = PyList_New(count);
|
||||
for (size_t i=0; i<count; i++) {
|
||||
wxDataFormat* format = new wxDataFormat(formats[i]);
|
||||
PyObject* obj = wxPyConstructObject((void*)format, wxT("wxDataFormat"), true);
|
||||
PyList_SET_ITEM(list, i, obj); // PyList_SET_ITEM steals a reference
|
||||
}
|
||||
wxPyEndBlockThreads(blocked);
|
||||
delete [] formats;
|
||||
return list;
|
||||
""",
|
||||
|
||||
# This code will be used in the function that calls a Python implementation
|
||||
# of this method. So we need to translate between the real C++ siganture
|
||||
# and the Python signature.
|
||||
virtualCatcherCode="""\
|
||||
// VirtualCatcherCode for wx.DataObject.GetAllFormats
|
||||
PyObject *resObj = sipCallMethod(0,sipMethod,"F",dir,sipType_wxDataObject_Direction);
|
||||
if (resObj) {
|
||||
if (!PySequence_Check(resObj)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Should return a list of wx.DataFormat objects.");
|
||||
// or this? sipBadCatcherResult(sipMethod);
|
||||
}
|
||||
else {
|
||||
Py_ssize_t len = PySequence_Length(resObj);
|
||||
Py_ssize_t idx;
|
||||
for (idx=0; idx<len; idx+=1) {
|
||||
PyObject* item = PySequence_GetItem(resObj, idx);
|
||||
if (! sipCanConvertToType(item, sipType_wxDataFormat, SIP_NOT_NONE)) {
|
||||
PyErr_SetString(PyExc_TypeError, "List of wx.DataFormat objects expected.");
|
||||
// or this? sipBadCatcherResult(sipMethod);
|
||||
Py_DECREF(item);
|
||||
break;
|
||||
}
|
||||
wxDataFormat* fmt;
|
||||
int err = 0;
|
||||
fmt = (wxDataFormat*)sipConvertToType(
|
||||
item, sipType_wxDataFormat, NULL,
|
||||
SIP_NOT_NONE|SIP_NO_CONVERTORS, NULL, &err);
|
||||
formats[idx] = *fmt;
|
||||
Py_DECREF(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (PyErr_Occurred())
|
||||
PyErr_Print();
|
||||
Py_XDECREF(resObj);
|
||||
""" if pureVirtual else "")
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
def run():
|
||||
@@ -45,10 +114,231 @@ def run():
|
||||
assert isinstance(c, etgtools.ClassDef)
|
||||
c.find('GetType').setCppCode("return static_cast<wxDataFormatId>(self->GetType());")
|
||||
|
||||
item = module.find('wxFormatInvalid')
|
||||
module.items.remove(item)
|
||||
module.insertItemAfter(c, item)
|
||||
|
||||
|
||||
#------------------------------------------------------------
|
||||
c = module.find('wxDataObject')
|
||||
c.abstract = True
|
||||
c.addPrivateCopyCtor()
|
||||
|
||||
addGetAllFormats(c, True)
|
||||
|
||||
# For initial testing only. TODO: Remove later
|
||||
c.addPublic()
|
||||
c.addCppMethod('void', '_testGetAllFormats', '()',
|
||||
body="""\
|
||||
size_t count = self->GetFormatCount();
|
||||
wxDataFormat fmts[count];
|
||||
self->GetAllFormats(fmts);
|
||||
""")
|
||||
|
||||
# Replace the GetDataHere method with a version that uses a smarter
|
||||
# Python buffer object instead of a stupid void pointer.
|
||||
c.find('GetDataHere').ignore()
|
||||
c.addCppMethod('bool', 'GetDataHere', '(const wxDataFormat& format, wxPyBuffer* buf)',
|
||||
cppSignature='bool (const wxDataFormat& format, void* buf)',
|
||||
isVirtual=True, isPureVirtual=True,
|
||||
isConst=True,
|
||||
doc="Copies this data object's data in the requested format to the buffer provided.",
|
||||
body="""\
|
||||
if (!buf->checkSize(self->GetDataSize(*format)))
|
||||
return false;
|
||||
return self->GetDataHere(*format, buf->m_ptr);
|
||||
""",
|
||||
|
||||
# This code will be used in the function that calls a Python implementation
|
||||
# of this method.
|
||||
virtualCatcherCode="""\
|
||||
// Call self.GetDataSize() to find out how big the buffer should be
|
||||
PyObject* self = NULL;
|
||||
PyObject* fmtObj = NULL;
|
||||
PyObject* sizeObj = NULL;
|
||||
PyObject* buffer = NULL;
|
||||
PyObject* resObj = NULL;
|
||||
Py_ssize_t size = 0;
|
||||
|
||||
self = PyMethod_Self(sipMethod); // this shouldn't fail, and the reference is borrowed
|
||||
|
||||
fmtObj = wxPyConstructObject((void*)&format, "wxDataFormat", false);
|
||||
if (!fmtObj) goto error;
|
||||
sizeObj = PyObject_CallMethod(self, "GetDataSize", "(O)", fmtObj, NULL);
|
||||
if (!sizeObj) goto error;
|
||||
size = PyInt_AsSsize_t(sizeObj);
|
||||
|
||||
// Make a buffer that big using the pointer passed to us, and then
|
||||
// call the Python method.
|
||||
buffer = wxPyMakeBuffer(buf, size);
|
||||
resObj = sipCallMethod(0, sipMethod, "SS", fmtObj, buffer);
|
||||
|
||||
if (!resObj || sipParseResult(0,sipMethod,resObj,"b",&sipRes) < 0)
|
||||
PyErr_Print();
|
||||
|
||||
error:
|
||||
Py_XDECREF(resObj);
|
||||
Py_XDECREF(buffer);
|
||||
Py_XDECREF(fmtObj);
|
||||
Py_XDECREF(sizeObj);
|
||||
""")
|
||||
|
||||
# Replace the SetData method with an implementation that uses Python
|
||||
# buffer objects.
|
||||
c.find('SetData').ignore()
|
||||
c.addCppMethod('bool', 'SetData', '(const wxDataFormat& format, wxPyBuffer* buf)',
|
||||
cppSignature='bool (const wxDataFormat& format, size_t len, const void* buf)',
|
||||
isVirtual=True,
|
||||
doc="Copies data from the provided buffer to this data object for the specified format.",
|
||||
body="return self->SetData(*format, buf->m_len, buf->m_ptr);",
|
||||
|
||||
# This code will be used in the function that calls a Python implementation
|
||||
# of this method.
|
||||
virtualCatcherCode="""\
|
||||
PyObject* buffer = wxPyMakeBuffer((void*)buf, len);
|
||||
PyObject *resObj = sipCallMethod(0,sipMethod,"NS",
|
||||
new wxDataFormat(format),sipType_wxDataFormat,NULL,
|
||||
buffer);
|
||||
if (!resObj || sipParseResult(0,sipMethod,resObj,"b",&sipRes) < 0)
|
||||
PyErr_Print();
|
||||
Py_XDECREF(resObj);
|
||||
Py_XDECREF(buffer);
|
||||
""")
|
||||
|
||||
|
||||
#------------------------------------------------------------
|
||||
c = module.find('wxDataObjectSimple')
|
||||
|
||||
c.addCppCtor_sip('(const wxString& formatName)',
|
||||
body='sipCpp = new sipwxDataObjectSimple(wxDataFormat(*formatName));')
|
||||
|
||||
# As in wxDataObject above replace GetDataHere and SetData with methods
|
||||
# that use buffer objects instead of void*, but this time we do not pass
|
||||
# a DataFormat object with it.
|
||||
c.find('GetDataHere').ignore()
|
||||
c.addCppMethod('bool', 'GetDataHere', '(wxPyBuffer* buf)',
|
||||
cppSignature='bool (void* buf)',
|
||||
isVirtual=True,
|
||||
isConst=True,
|
||||
doc="Copies this data object's data bytes to the given buffer",
|
||||
body="""\
|
||||
if (!buf->checkSize(self->GetDataSize()))
|
||||
return false;
|
||||
return self->GetDataHere(buf->m_ptr);
|
||||
""",
|
||||
virtualCatcherCode="""\
|
||||
// Call self.GetDataSize() to find out how big the buffer should be
|
||||
PyObject* self = NULL;
|
||||
PyObject* sizeObj = NULL;
|
||||
PyObject* buffer = NULL;
|
||||
PyObject* resObj = NULL;
|
||||
Py_ssize_t size = 0;
|
||||
|
||||
self = PyMethod_Self(sipMethod);
|
||||
|
||||
sizeObj = PyObject_CallMethod(self, "GetDataSize", "", NULL);
|
||||
if (!sizeObj) goto error;
|
||||
size = PyInt_AsSsize_t(sizeObj);
|
||||
|
||||
// Make a buffer that big using the pointer passed to us, and then
|
||||
// call the Python method.
|
||||
buffer = wxPyMakeBuffer(buf, size);
|
||||
resObj = sipCallMethod(0, sipMethod, "S", buffer);
|
||||
|
||||
if (!resObj || sipParseResult(0,sipMethod,resObj,"b",&sipRes) < 0)
|
||||
PyErr_Print();
|
||||
|
||||
error:
|
||||
Py_XDECREF(resObj);
|
||||
Py_XDECREF(buffer);
|
||||
Py_XDECREF(sizeObj);
|
||||
""")
|
||||
|
||||
c.find('SetData').ignore()
|
||||
c.addCppMethod('bool', 'SetData', '(wxPyBuffer* buf)',
|
||||
cppSignature='bool (size_t len, const void* buf)',
|
||||
isVirtual=True,
|
||||
doc="Copies data from the provided buffer to this data object.",
|
||||
body="return self->SetData(buf->m_len, buf->m_ptr);",
|
||||
virtualCatcherCode="""\
|
||||
PyObject* buffer = wxPyMakeBuffer((void*)buf, len);
|
||||
PyObject *resObj = sipCallMethod(0,sipMethod,"S",buffer);
|
||||
if (!resObj || sipParseResult(0,sipMethod,resObj,"b",&sipRes) < 0)
|
||||
PyErr_Print();
|
||||
Py_XDECREF(resObj);
|
||||
Py_XDECREF(buffer);
|
||||
""")
|
||||
|
||||
addGetAllFormats(c)
|
||||
|
||||
# We need to let SIP know that the pure virtuals in the base class have
|
||||
# impelmentations here even though they will not be used much (if at
|
||||
# all.) Those that are overridden in this class with different signatures
|
||||
# we'll just mark as private to help avoid confusion.
|
||||
c.addItem(etgtools.WigCode(code="""\
|
||||
virtual size_t GetFormatCount(Direction dir = Get) const;
|
||||
virtual wxDataFormat GetPreferredFormat(Direction dir = Get) const;
|
||||
private:
|
||||
virtual size_t GetDataSize(const wxDataFormat& format) const;
|
||||
virtual bool GetDataHere(const wxDataFormat& format, void* buf) const;
|
||||
virtual bool SetData(const wxDataFormat& format, size_t len, const void* buf);
|
||||
"""))
|
||||
|
||||
|
||||
|
||||
#------------------------------------------------------------
|
||||
c = module.find('wxCustomDataObject')
|
||||
tools.removeVirtuals(c)
|
||||
|
||||
c.addCppCtor_sip('(const wxString& formatName)',
|
||||
body='sipCpp = new sipwxCustomDataObject(wxDataFormat(*formatName));')
|
||||
|
||||
# remove the methods having to do with allocating or owning the data buffer
|
||||
c.find('Alloc').ignore()
|
||||
c.find('Free').ignore()
|
||||
c.find('TakeData').ignore()
|
||||
|
||||
c.find('GetData').ignore()
|
||||
c.addCppMethod('PyObject*', 'GetData', '()', isConst=True,
|
||||
doc="Returns a reference to the data buffer.",
|
||||
body="return wxPyMakeBuffer(self->GetData(), self->GetSize());")
|
||||
|
||||
c.find('SetData').ignore()
|
||||
c.addCppMethod('bool', 'SetData', '(wxPyBuffer* buf)',
|
||||
cppSignature='bool (size_t len, const void* buf)',
|
||||
isVirtual=True,
|
||||
doc="Copies data from the provided buffer to this data object's buffer",
|
||||
body="return self->SetData(buf->m_len, buf->m_ptr);")
|
||||
|
||||
|
||||
|
||||
#------------------------------------------------------------
|
||||
c = module.find('wxDataObjectComposite')
|
||||
|
||||
c.find('Add.dataObject').transfer = True
|
||||
|
||||
addGetAllFormats(c)
|
||||
|
||||
# The pure virtuals from wxDataObject have implementations here
|
||||
c.addItem(etgtools.WigCode(code="""\
|
||||
virtual size_t GetFormatCount(Direction dir = Get) const;
|
||||
virtual wxDataFormat GetPreferredFormat(Direction dir = Get) const;
|
||||
private:
|
||||
virtual size_t GetDataSize(const wxDataFormat& format) const;
|
||||
virtual bool GetDataHere(const wxDataFormat& format, void* buf) const;
|
||||
virtual bool SetData(const wxDataFormat& format, size_t len, const void* buf);
|
||||
"""))
|
||||
|
||||
|
||||
|
||||
#------------------------------------------------------------
|
||||
c = module.find('wxTextDataObject')
|
||||
addGetAllFormats(c)
|
||||
|
||||
|
||||
#------------------------------------------------------------
|
||||
module.addPyCode("PyDataObjectSimple = wx.deprecated(DataObjectSimple)")
|
||||
module.addPyCode("PyTextDataObject = wx.deprecated(TextDataObject)")
|
||||
module.addPyCode("PyBitmapDataObject = wx.deprecated(BitmapDataObject)")
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
tools.doCommonTweaks(module)
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import imp_unittest, unittest
|
||||
import wtc
|
||||
import wx
|
||||
import os
|
||||
|
||||
pngFile = os.path.join(os.path.dirname(__file__), 'toucan.png')
|
||||
|
||||
#print os.getpid(); raw_input('Press enter...')
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
@@ -10,6 +15,9 @@ class DataObjTests(wtc.WidgetTestCase):
|
||||
fmt1 = wx.DataFormat('my custom format')
|
||||
fmt2 = wx.DataFormat(wx.DF_TEXT)
|
||||
self.assertTrue(fmt1 != fmt2)
|
||||
fmt3 = wx.DataFormat(wx.DF_TEXT)
|
||||
self.assertTrue(fmt2 == fmt3)
|
||||
|
||||
|
||||
|
||||
def test_DataFormatIDsExist(self):
|
||||
@@ -34,6 +42,178 @@ class DataObjTests(wtc.WidgetTestCase):
|
||||
wx.DF_HTML
|
||||
wx.DF_MAX
|
||||
|
||||
|
||||
|
||||
def test_DataObjectGetAllFormats(self):
|
||||
class MyDataObject(wx.DataObject):
|
||||
def __init__(self):
|
||||
wx.DataObject.__init__(self)
|
||||
self.myFormats = [wx.DataFormat(wx.DF_TEXT),
|
||||
wx.DataFormat(wx.DF_UNICODETEXT)]
|
||||
|
||||
def GetAllFormats(self, d):
|
||||
return self.myFormats
|
||||
|
||||
def GetFormatCount(self, d):
|
||||
return len(self.myFormats)
|
||||
|
||||
data = MyDataObject()
|
||||
if hasattr(data, '_testGetAllFormats'):
|
||||
data._testGetAllFormats()
|
||||
|
||||
|
||||
|
||||
def test_DataObject(self):
|
||||
class MyDataObject(wx.DataObject):
|
||||
def __init__(self, value=''):
|
||||
wx.DataObject.__init__(self)
|
||||
self.myFormats = [wx.DataFormat(wx.DF_TEXT)]
|
||||
self.myData = bytes(value)
|
||||
|
||||
def GetAllFormats(self, d):
|
||||
return self.myFormats
|
||||
def GetFormatCount(self, d):
|
||||
return len(self.myFormats)
|
||||
def GetPreferredFormat(self, d):
|
||||
return self.myFormats[0]
|
||||
def GetDataSize(self, format):
|
||||
return len(self.myData)
|
||||
|
||||
def GetDataHere(self, format, buf):
|
||||
# copy our local data value to buf
|
||||
assert isinstance(buf, memoryview)
|
||||
buf[:] = self.myData
|
||||
return True
|
||||
|
||||
def SetData(self, format, buf):
|
||||
# copy from buf to our local data value
|
||||
assert isinstance(buf, memoryview)
|
||||
self.myData = buf.tobytes()
|
||||
return True
|
||||
|
||||
# copy
|
||||
data1 = MyDataObject('This is some data.')
|
||||
if wx.TheClipboard.Open():
|
||||
wx.TheClipboard.SetData(data1)
|
||||
wx.TheClipboard.Close()
|
||||
|
||||
# paste
|
||||
data2 = MyDataObject()
|
||||
if wx.TheClipboard.Open():
|
||||
wx.TheClipboard.GetData(data2)
|
||||
wx.TheClipboard.Close()
|
||||
|
||||
self.assertEqual(data1.myData, data2.myData)
|
||||
|
||||
|
||||
|
||||
def test_DataObjectSimple1(self):
|
||||
df = wx.DataFormat(wx.DF_TEXT)
|
||||
dobj = wx.DataObjectSimple(df)
|
||||
self.assertTrue(dobj.GetFormatCount() == 1)
|
||||
self.assertTrue(dobj.GetFormat() == df)
|
||||
self.assertTrue(dobj.GetAllFormats()[0] == df)
|
||||
|
||||
|
||||
def test_DataObjectSimple2(self):
|
||||
class MyDataObject(wx.DataObjectSimple):
|
||||
def __init__(self, value=''):
|
||||
wx.DataObjectSimple.__init__(self)
|
||||
self.SetFormat(wx.DataFormat(wx.DF_TEXT))
|
||||
self.myData = bytes(value)
|
||||
|
||||
def GetDataSize(self):
|
||||
return len(self.myData)
|
||||
|
||||
def GetDataHere(self, buf):
|
||||
# copy our local data value to buf
|
||||
assert isinstance(buf, memoryview)
|
||||
buf[:] = self.myData
|
||||
return True
|
||||
|
||||
def SetData(self, buf):
|
||||
# copy from buf to our local data value
|
||||
assert isinstance(buf, memoryview)
|
||||
self.myData = buf.tobytes()
|
||||
return True
|
||||
|
||||
# copy
|
||||
data1 = MyDataObject('This is some data.')
|
||||
if wx.TheClipboard.Open():
|
||||
wx.TheClipboard.SetData(data1)
|
||||
wx.TheClipboard.Close()
|
||||
|
||||
# paste
|
||||
data2 = MyDataObject()
|
||||
if wx.TheClipboard.Open():
|
||||
wx.TheClipboard.GetData(data2)
|
||||
wx.TheClipboard.Close()
|
||||
|
||||
self.assertEqual(data1.myData, data2.myData)
|
||||
|
||||
|
||||
|
||||
def test_CustomDataObject(self):
|
||||
import pickle
|
||||
data1 = range(10)
|
||||
obj = wx.CustomDataObject('my custom format')
|
||||
obj.SetData(pickle.dumps(data1))
|
||||
data2 = pickle.loads(obj.GetData().tobytes())
|
||||
self.assertTrue(data1 == data2)
|
||||
|
||||
|
||||
|
||||
def test_DataObjectComposite(self):
|
||||
do = wx.DataObjectComposite()
|
||||
df1 = wx.DataFormat("data type 1")
|
||||
df2 = wx.DataFormat("data type 2")
|
||||
d1 = wx.CustomDataObject(df1)
|
||||
d2 = wx.CustomDataObject(df2)
|
||||
do.Add(d1, True)
|
||||
do.Add(d2)
|
||||
|
||||
self.assertTrue(do.GetPreferredFormat() == df1)
|
||||
d3 = do.GetObject(df2)
|
||||
self.assertTrue(isinstance(d3, wx.CustomDataObject))
|
||||
self.assertTrue(d3 is d2)
|
||||
|
||||
|
||||
def test_BitmapDataObject(self):
|
||||
do = wx.BitmapDataObject()
|
||||
do.Bitmap = wx.Bitmap(pngFile)
|
||||
self.assertTrue(do.GetBitmap().IsOk())
|
||||
self.assertTrue(do.Bitmap.IsOk())
|
||||
|
||||
|
||||
def test_TextDataObject(self):
|
||||
data = "This is some data"
|
||||
do = wx.TextDataObject(data)
|
||||
self.assertEqual(do.GetText(), data)
|
||||
self.assertEqual(do.Text, data)
|
||||
self.assertAlmostEqual(do.GetTextLength(), len(data), delta=1)
|
||||
self.assertAlmostEqual(do.TextLength, len(data), delta=1)
|
||||
|
||||
|
||||
def test_URLDataObject(self):
|
||||
url = 'http://wxPython.org/'
|
||||
do = wx.URLDataObject()
|
||||
do.URL = url
|
||||
self.assertEqual(do.GetURL(), url)
|
||||
self.assertEqual(do.URL, url)
|
||||
|
||||
|
||||
def test_FileDataObject(self):
|
||||
do = wx.FileDataObject()
|
||||
do.AddFile('filename1')
|
||||
do.AddFile('filename2')
|
||||
do.AddFile('filename3')
|
||||
|
||||
names = do.GetFilenames()
|
||||
self.assertTrue(len(names) == 3)
|
||||
self.assertTrue(names[0] == 'filename1')
|
||||
self.assertTrue(names == do.Filenames)
|
||||
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user