mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2026-01-04 19:10:09 +01:00
Add wxProcess, utils.h and the wx.Py events.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxPython/Phoenix/trunk@66461 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -53,6 +53,9 @@ INCLUDES = [ 'defs',
|
||||
'tooltip',
|
||||
'layout',
|
||||
'event',
|
||||
'pyevent',
|
||||
'process',
|
||||
'utils',
|
||||
|
||||
'evtloop',
|
||||
'apptrait',
|
||||
|
||||
45
etg/process.py
Normal file
45
etg/process.py
Normal file
@@ -0,0 +1,45 @@
|
||||
#---------------------------------------------------------------------------
|
||||
# Name: etg/process.py
|
||||
# Author: Robin Dunn
|
||||
#
|
||||
# Created: 19-Dec-2010
|
||||
# Copyright: (c) 2010 by Total Control Software
|
||||
# License: wxWindows License
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
import etgtools
|
||||
import etgtools.tweaker_tools as tools
|
||||
|
||||
PACKAGE = "wx"
|
||||
MODULE = "_core"
|
||||
NAME = "process" # 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 = [ 'wxProcess' ]
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
tools.doCommonTweaks(module)
|
||||
tools.runGenerators(module)
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
|
||||
76
etg/utils.py
Normal file
76
etg/utils.py
Normal file
@@ -0,0 +1,76 @@
|
||||
#---------------------------------------------------------------------------
|
||||
# Name: etg/utils.py
|
||||
# Author: Robin Dunn
|
||||
#
|
||||
# Created: 19-Dec-2010
|
||||
# Copyright: (c) 2010 by Total Control Software
|
||||
# License: wxWindows License
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
import etgtools
|
||||
import etgtools.tweaker_tools as tools
|
||||
|
||||
PACKAGE = "wx"
|
||||
MODULE = "_core"
|
||||
NAME = "utils" # 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 = [ 'utils_8h.xml',
|
||||
'power_8h.xml',
|
||||
'wxWindowDisabler',
|
||||
'wxBusyCursor',
|
||||
'wxVersionInfo',
|
||||
]
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
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.addHeaderCode('#include <wx/utils.h>')
|
||||
module.addHeaderCode('#include <wx/power.h>')
|
||||
|
||||
c = module.find('wxWindowDisabler')
|
||||
assert isinstance(c, etgtools.ClassDef)
|
||||
c.addPrivateCopyCtor()
|
||||
|
||||
module.find('wxQsort').ignore()
|
||||
module.find('wxGetEmailAddress').findOverload('buf').ignore()
|
||||
module.find('wxGetHostName').findOverload('buf').ignore()
|
||||
module.find('wxGetUserId').findOverload('buf').ignore()
|
||||
module.find('wxGetUserName').findOverload('buf').ignore()
|
||||
module.find('CMPFUNCDATA').ignore()
|
||||
module.find('wxLoadUserResource').ignore()
|
||||
module.find('wxGetFreeMemory').ignore()
|
||||
module.find('wxGetLinuxDistributionInfo').ignore()
|
||||
module.find('wxGetDisplayName').ignore()
|
||||
module.find('wxSetDisplayName').ignore()
|
||||
module.find('wxPostDelete').ignore()
|
||||
|
||||
# ignore all the environment related functions
|
||||
for item in module.allItems():
|
||||
if 'Env' in item.name:
|
||||
item.ignore()
|
||||
module.find('wxGetenv').ignore()
|
||||
|
||||
# Keep just the first wxExecute overload
|
||||
f = module.find('wxExecute')
|
||||
f.overloads = []
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
tools.doCommonTweaks(module)
|
||||
tools.runGenerators(module)
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
|
||||
161
src/pyevent.sip
Normal file
161
src/pyevent.sip
Normal file
@@ -0,0 +1,161 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: pyevent.sip
|
||||
// Purpose: A set of event classes that can be derived from in Python
|
||||
// and that preserve their attributes when cloned.
|
||||
//
|
||||
// Author: Robin Dunn
|
||||
//
|
||||
// Created: 18-Dec-2010
|
||||
// Copyright: (c) 2010 by Total Control Software
|
||||
// Licence: wxWindows license
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// These Event classes can be derived from in Python and passed through the
|
||||
// event system without loosing anything. They do this by keeping a seaparate
|
||||
// dictionary for storring any extra attributes set from Python code. When the
|
||||
// event object is cloned then the clone gets a new reference to the same
|
||||
// dictionary held by the original object.
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// TODO: Use this comment for a docstring
|
||||
|
||||
// wx.PyEvent can be used as a base class for implementing custom event
|
||||
// types in Python. You should derive from this class instead of
|
||||
// `wx.Event` because this class is Python-aware and is able to transport
|
||||
// its Python bits safely through the wxWidgets event system and have
|
||||
// them still be there when the event handler is invoked.
|
||||
// :see: `wx.PyCommandEvent`
|
||||
class wxPyEvent : wxEvent {
|
||||
%TypeCode
|
||||
class wxPyEvent : public wxEvent
|
||||
{
|
||||
DECLARE_DYNAMIC_CLASS(wxPyEvent)
|
||||
public:
|
||||
wxPyEvent(int winid=0, wxEventType commandType = wxEVT_NULL)
|
||||
: wxEvent(winid, commandType) {}
|
||||
|
||||
// Create a new instance of the Python object for the cloned event,
|
||||
// and then copy the attributes from the original Python instance to
|
||||
// the clone.
|
||||
virtual wxEvent* Clone() const
|
||||
{
|
||||
wxPyEvent* newEvent = new wxPyEvent(*this);
|
||||
wxPyBlock_t blocked = wxPyBeginBlockThreads();
|
||||
PyObject* thisObj = sipGetPyObject((void*)this, sipType_wxPyEvent);
|
||||
PyObject* newObj = sipConvertFromType((void*)newEvent,
|
||||
sipType_wxPyEvent,
|
||||
NULL);
|
||||
PyObject* newDict = PyObject_GetAttrString(newObj, "__dict__");
|
||||
PyObject* thisDict = PyObject_GetAttrString(thisObj, "__dict__");
|
||||
PyDict_Update(newDict, thisDict);
|
||||
Py_DECREF(newDict);
|
||||
Py_DECREF(thisDict);
|
||||
wxPyEndBlockThreads(blocked);
|
||||
return newEvent;
|
||||
}
|
||||
};
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxPyEvent, wxEvent);
|
||||
%End
|
||||
|
||||
public:
|
||||
wxPyEvent(int winid=0, wxEventType eventType = wxEVT_NULL );
|
||||
|
||||
virtual wxEvent* Clone() const /Factory, NoArgParser/;
|
||||
%MethodCode
|
||||
PyObject *sipParseErr = NULL;
|
||||
bool sipSelfWasArg = (!sipSelf || sipIsDerived((sipSimpleWrapper *)sipSelf));
|
||||
wxPyEvent *sipCpp;
|
||||
if (sipParseArgs(&sipParseErr, sipArgs, "B", &sipSelf, sipType_wxPyEvent, &sipCpp))
|
||||
{
|
||||
wxEvent *sipRes;
|
||||
sipRes = (sipSelfWasArg ? sipCpp->wxPyEvent::Clone() : sipCpp->Clone());
|
||||
// Note that this MethodCode is nearly identical to what is normally generated,
|
||||
// except for the following lines. wxPyEvent::Clone already made a PyObject,
|
||||
// so just fetch it.
|
||||
PyObject* obj = sipGetPyObject(sipRes, sipType_wxPyEvent);
|
||||
sipTransferBack(obj);
|
||||
return obj;
|
||||
}
|
||||
sipNoMethod(sipParseErr, sipName_PyEvent, sipName_Clone, NULL); //doc_wxPyEvent_Clone);
|
||||
return NULL;
|
||||
%End
|
||||
};
|
||||
|
||||
|
||||
|
||||
// wx.PyCommandEvent can be used as a base class for implementing custom
|
||||
// event types in Python, where the event should travel up to parent
|
||||
// windows looking for a handler. You should derived from this class
|
||||
// instead of `wx.CommandEvent` because this class is Python-aware and is
|
||||
// able to transport its Python bits safely through the wxWidgets event
|
||||
// system and have them still be there when the event handler is invoked.
|
||||
// :see: `wx.PyEvent`
|
||||
class wxPyCommandEvent : wxCommandEvent {
|
||||
%TypeCode
|
||||
class wxPyCommandEvent : public wxCommandEvent
|
||||
{
|
||||
DECLARE_DYNAMIC_CLASS(wxPyCommandEvent)
|
||||
public:
|
||||
wxPyCommandEvent(wxEventType eventType = wxEVT_NULL, int id=0)
|
||||
: wxCommandEvent(eventType, id) {}
|
||||
|
||||
// Create a new instance of the Python object for the cloned event,
|
||||
// and then copy the attributes from the original Python instance to
|
||||
// the clone.
|
||||
virtual wxEvent* Clone() const
|
||||
{
|
||||
wxPyCommandEvent* newEvent = new wxPyCommandEvent(*this);
|
||||
wxPyBlock_t blocked = wxPyBeginBlockThreads();
|
||||
PyObject* thisObj = sipGetPyObject((void*)this, sipType_wxPyCommandEvent);
|
||||
PyObject* newObj = sipConvertFromNewType((void*)newEvent,
|
||||
sipType_wxPyCommandEvent,
|
||||
NULL);
|
||||
PyObject* newDict = PyObject_GetAttrString(newObj, "__dict__");
|
||||
PyObject* thisDict = PyObject_GetAttrString(thisObj, "__dict__");
|
||||
PyDict_Update(newDict, thisDict);
|
||||
Py_DECREF(newDict);
|
||||
Py_DECREF(thisDict);
|
||||
wxPyEndBlockThreads(blocked);
|
||||
return newEvent;
|
||||
}
|
||||
};
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxPyCommandEvent, wxCommandEvent);
|
||||
%End
|
||||
|
||||
public:
|
||||
wxPyCommandEvent(wxEventType eventType = wxEVT_NULL, int id=0);
|
||||
|
||||
virtual wxEvent* Clone() const /Factory, NoArgParser/;
|
||||
%MethodCode
|
||||
PyObject *sipParseErr = NULL;
|
||||
bool sipSelfWasArg = (!sipSelf || sipIsDerived((sipSimpleWrapper *)sipSelf));
|
||||
wxPyCommandEvent *sipCpp;
|
||||
if (sipParseArgs(&sipParseErr, sipArgs, "B", &sipSelf, sipType_wxPyCommandEvent, &sipCpp))
|
||||
{
|
||||
wxEvent *sipRes;
|
||||
sipRes = (sipSelfWasArg ? sipCpp->wxPyCommandEvent::Clone() : sipCpp->Clone());
|
||||
// Note that this MethodCode is nearly identical to what is normally generated,
|
||||
// except for the following lines. wxPyCommandEvent::Clone already made a PyObject,
|
||||
// so just fetch it.
|
||||
PyObject* obj = sipGetPyObject(sipRes, sipType_wxPyCommandEvent);
|
||||
sipTransferBack(obj);
|
||||
return obj;
|
||||
}
|
||||
sipNoMethod(sipParseErr, sipName_PyCommandEvent, sipName_Clone, NULL); //doc_wxPyEvent_Clone);
|
||||
return NULL;
|
||||
%End
|
||||
};
|
||||
|
||||
|
||||
// TODO: Temporary testing code, get rid of this later
|
||||
%ModuleCode
|
||||
wxEvent* testCppClone(wxEvent& evt)
|
||||
{
|
||||
return evt.Clone();
|
||||
}
|
||||
%End
|
||||
wxEvent* testCppClone(wxEvent& evt);
|
||||
|
||||
|
||||
102
unittests/test_pyevent.py
Normal file
102
unittests/test_pyevent.py
Normal file
@@ -0,0 +1,102 @@
|
||||
import sys
|
||||
import unittest2
|
||||
import wxPhoenix as wx
|
||||
##import os; print 'PID:', os.getpid(); raw_input('Ready to start, press enter...')
|
||||
|
||||
from wxPhoenix import siplib
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
class PyEvents(unittest2.TestCase):
|
||||
|
||||
def test_PyEvent(self):
|
||||
id = wx.NewId()
|
||||
typ = wx.NewEventType()
|
||||
evt = wx.PyEvent(id, typ)
|
||||
evt.newAttr = "hello"
|
||||
evt2 = evt.Clone()
|
||||
self.assertTrue(type(evt2) == wx.PyEvent)
|
||||
self.assertTrue(evt is not evt2)
|
||||
self.assertTrue(getattr(evt2, 'newAttr'))
|
||||
self.assertTrue(evt.newAttr == evt2.newAttr)
|
||||
self.assertTrue(evt.Id == evt2.Id)
|
||||
self.assertTrue(evt.EventType == evt2.EventType)
|
||||
|
||||
|
||||
|
||||
def test_PyCommandEvent(self):
|
||||
id = wx.NewId()
|
||||
typ = wx.NewEventType()
|
||||
evt = wx.PyCommandEvent(id, typ)
|
||||
evt.newAttr = "hello"
|
||||
evt2 = evt.Clone()
|
||||
self.assertTrue(type(evt2) == wx.PyCommandEvent)
|
||||
self.assertTrue(evt is not evt2)
|
||||
self.assertTrue(getattr(evt2, 'newAttr'))
|
||||
self.assertTrue(evt.newAttr == evt2.newAttr)
|
||||
self.assertTrue(evt.Id == evt2.Id)
|
||||
self.assertTrue(evt.EventType == evt2.EventType)
|
||||
|
||||
|
||||
def test_PyEvtCloneRefCounts(self):
|
||||
# Since we're doing some funky stuff under the covers with Clone, make
|
||||
# sure that the reference counts on everything (before and after)
|
||||
# still make sense
|
||||
evt1 = wx.PyEvent()
|
||||
rc1 = sys.getrefcount(evt1)
|
||||
evt1.attr = 'Howdy!'
|
||||
evt2 = evt1.Clone()
|
||||
rc2 = sys.getrefcount(evt2)
|
||||
rc3 = sys.getrefcount(evt1)
|
||||
#print '\n****', rc1, rc2, rc3
|
||||
self.assertTrue(rc1 == rc2 == rc3)
|
||||
self.assertTrue(evt1.attr == evt2.attr)
|
||||
|
||||
|
||||
def test_CppClone(self):
|
||||
# test what happens when Clone is called from C++
|
||||
if hasattr(wx, 'testCppClone'):
|
||||
evt1 = wx.PyEvent()
|
||||
evt1.attr = 'testCppClone'
|
||||
evt2 = wx.testCppClone(evt1)
|
||||
self.assertTrue(evt1.attr == evt2.attr)
|
||||
|
||||
def test_CppCloneRefCounts(self):
|
||||
# Since we're doing some funky stuff under the covers with Clone, make
|
||||
# sure that the reference counts on everything (before and after)
|
||||
# still make sense
|
||||
if hasattr(wx, 'testCppClone'):
|
||||
evt1 = wx.PyEvent()
|
||||
rc1 = sys.getrefcount(evt1)
|
||||
evt1.attr = 'Howdy!'
|
||||
evt2 = wx.testCppClone(evt1)
|
||||
rc2 = sys.getrefcount(evt2)
|
||||
rc3 = sys.getrefcount(evt1)
|
||||
#print '\n****', rc1, rc2, rc3
|
||||
##self.assertTrue(rc1 == rc2 == rc3) TODO: rc2 has an extra refcount. Why?
|
||||
self.assertTrue(evt1.attr == evt2.attr)
|
||||
|
||||
#def test_AA(self):
|
||||
#class MyEvent(wx.PyEvent):
|
||||
#def __init__(self, name):
|
||||
#wx.PyEvent.__init__(self)
|
||||
#self.name = name
|
||||
#def __del__(self):
|
||||
#print '\n-=-=-= __del__:', self.name
|
||||
|
||||
#evt1 = MyEvent('orig')
|
||||
#evt2 = evt1.Clone()
|
||||
#evt2.name += ' clone'
|
||||
#evt3 = wx.testCppClone(evt1)
|
||||
#evt3.name += ' clone2'
|
||||
#print sys.getrefcount(evt1), sys.getrefcount(evt2), sys.getrefcount(evt3)
|
||||
#print siplib.ispyowned(evt1), siplib.ispyowned(evt2), siplib.ispyowned(evt3)
|
||||
#del evt1, evt2
|
||||
#print 'deleted'
|
||||
#evt3.Destroy()
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest2.main()
|
||||
Reference in New Issue
Block a user