summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugo Lima <hugo.lima@openbossa.org>2009-08-17 17:36:11 -0300
committerHugo Lima <hugo.lima@openbossa.org>2009-08-17 17:36:11 -0300
commitcbac30b07bae6c72be5eefd5e47fe83650a16acd (patch)
tree5fa8211c6f880c6777188934bd994d1f4359fe5c
downloadgeneratorrunner-cbac30b07bae6c72be5eefd5e47fe83650a16acd.tar.gz
generatorrunner-cbac30b07bae6c72be5eefd5e47fe83650a16acd.tar.xz
generatorrunner-cbac30b07bae6c72be5eefd5e47fe83650a16acd.zip
The genesis...
-rw-r--r--.gitignore10
-rw-r--r--AUTHORS8
-rw-r--r--CMakeLists.txt54
-rw-r--r--COPYING342
-rw-r--r--Doxyfile311
-rw-r--r--boostpythongenerator.cpp494
-rw-r--r--boostpythongenerator.h147
-rw-r--r--boostpythongeneratorversion.h.in4
-rw-r--r--cmake_uninstall.cmake21
-rw-r--r--convertergenerator.cpp180
-rw-r--r--convertergenerator.h77
-rw-r--r--cppgenerator.cpp1421
-rw-r--r--cppgenerator.h102
-rw-r--r--doc/Makefile88
-rw-r--r--doc/_static/basic.css417
-rw-r--r--doc/_static/bindingexample.tar.bz2bin0 -> 107006 bytes
-rw-r--r--doc/_static/default.css248
-rwxr-xr-xdoc/_static/images/._background_search.jpgbin0 -> 4096 bytes
-rwxr-xr-xdoc/_static/images/._bread_crumb.pngbin0 -> 4096 bytes
-rwxr-xr-xdoc/_static/images/._button_search.jpgbin0 -> 4096 bytes
-rwxr-xr-xdoc/_static/images/._side_background.jpgbin0 -> 25192 bytes
-rwxr-xr-xdoc/_static/images/._top_background.jpgbin0 -> 4096 bytes
-rw-r--r--doc/_static/images/background_search.jpgbin0 -> 2129 bytes
-rw-r--r--doc/_static/images/bg.jpgbin0 -> 5749 bytes
-rw-r--r--doc/_static/images/bread_crumb.pngbin0 -> 743 bytes
-rw-r--r--doc/_static/images/button_search.pngbin0 -> 3259 bytes
-rw-r--r--doc/_static/images/side_background.jpgbin0 -> 13760 bytes
-rw-r--r--doc/_static/images/top_background.jpgbin0 -> 500 bytes
-rw-r--r--doc/_templates/index.html32
-rw-r--r--doc/_templates/layout.html34
-rw-r--r--doc/compiling/cmake-primer.rst72
-rw-r--r--doc/compiling/compiling.rst9
-rw-r--r--doc/compiling/setup-apiextractor.rst48
-rw-r--r--doc/compiling/setup-generator.rst49
-rw-r--r--doc/conf.py188
-rw-r--r--doc/contents.rst9
-rw-r--r--doc/dependency-pyside.svg527
-rw-r--r--doc/images/.directory3
-rw-r--r--doc/images/bindinggen-development.pngbin0 -> 35681 bytes
-rw-r--r--doc/images/bindinggen-development.svg543
-rw-r--r--doc/images/boostgenarch.pngbin0 -> 80531 bytes
-rw-r--r--doc/images/boostgenarch.svg711
-rw-r--r--doc/images/boostqtarch.pngbin0 -> 31605 bytes
-rw-r--r--doc/images/boostqtarch.svg226
-rw-r--r--doc/overview.rst46
-rw-r--r--doc/tutorial/bindinglibfoo.rst77
-rw-r--r--doc/tutorial/buildingthebinding.rst132
-rw-r--r--doc/tutorial/globalheader.rst36
-rw-r--r--doc/tutorial/images/generatorworkings.pngbin0 -> 37257 bytes
-rw-r--r--doc/tutorial/images/generatorworkings.svg392
-rw-r--r--doc/tutorial/introduction.rst32
-rw-r--r--doc/tutorial/libfoo.rst68
-rw-r--r--doc/tutorial/typesystemcreation.rst135
-rw-r--r--docgenerator.cpp1371
-rw-r--r--docgenerator.h212
-rw-r--r--hppgenerator.cpp219
-rw-r--r--hppgenerator.h51
-rw-r--r--main.cpp52
-rw-r--r--tests/CMakeLists.txt9
-rw-r--r--tests/Makefile12
-rw-r--r--tests/foo_test.py105
-rw-r--r--tests/foobinding/Makefile13
-rw-r--r--tests/foobinding/foo/Makefile21
-rw-r--r--tests/foobinding/global.h2
-rw-r--r--tests/foobinding/typesystem_foo.xml6
-rw-r--r--tests/libfoo/Makefile15
-rw-r--r--tests/libfoo/bar.cpp15
-rw-r--r--tests/libfoo/bar.h15
-rw-r--r--tests/libfoo/foo.cpp17
-rw-r--r--tests/libfoo/foo.h14
-rw-r--r--tests/libfoo/main.cpp15
-rw-r--r--tests/sphinxtabletest.cpp269
-rw-r--r--tests/sphinxtabletest.h48
73 files changed, 9774 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fa13dcc
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+build
+.kdev4
+*.log
+*.pyc
+*.o
+*.so
+.preprocessed.tmp
+.*.swp
+*.kdev4
+doc/_build
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..6e802fb
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,8 @@
+Anderson Lizardo <anderson.lizardo@openbossa.org>
+Bruno Araujo <bruno.araujo@openbossa.org>
+Hugo Parente Lima <hugo.lima@openbossa.org>
+Lauro Moura <lauro.neto@openbossa.org>
+Luciano Wolf <luciano.wolf@openbossa.org>
+Marcelo Lira <marcelo.lira@openbossa.org>
+Renato Araujo Oliveira Filho <renato.filho@openbossa.org>
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..6c9c309
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,54 @@
+project(boostpythongenerator)
+
+cmake_minimum_required(VERSION 2.6)
+
+find_package(Qt4 4.5.0 REQUIRED)
+find_package(ApiExtractor REQUIRED)
+
+add_definitions(${QT_DEFINITIONS})
+
+set(boostpythongenerator_VERSION 0.1)
+configure_file(boostpythongeneratorversion.h.in ${CMAKE_CURRENT_BINARY_DIR}/boostpythongeneratorversion.h @ONLY)
+set(CMAKE_BUILD_TYPE Debug)
+
+set(boostpythongenerator_SRC
+boostpythongenerator.cpp
+convertergenerator.cpp
+docgenerator.cpp
+hppgenerator.cpp
+cppgenerator.cpp
+)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${APIEXTRACTOR_INCLUDE_DIR}
+ ${APIEXTRACTOR_INCLUDE_DIR}/..
+ ${QT_INCLUDE_DIR}
+ ${QT_QTCORE_INCLUDE_DIR})
+
+add_library(libboostpythongenerator STATIC ${boostpythongenerator_SRC})
+target_link_libraries(libboostpythongenerator
+ ${APIEXTRACTOR_LIBRARY}
+ ${QT_QTCORE_LIBRARY}
+ ${QT_QTXML_LIBRARY})
+add_executable(boostpythongenerator main.cpp)
+target_link_libraries(boostpythongenerator libboostpythongenerator)
+
+# uninstall target
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
+ IMMEDIATE @ONLY)
+add_custom_target(uninstall "${CMAKE_COMMAND}"
+ -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
+
+
+# "make dist", in fact "make package_source"
+set(CPACK_SOURCE_PACKAGE_FILE_NAME "boostpythongenerator-${boostpythongenerator_VERSION}")
+set(CPACK_SOURCE_GENERATOR TGZ)
+set(CPACK_SOURCE_IGNORE_FILES "~$" ".svn" "debian/" "build/" ".swp$" "*.kdev4")
+include(CPack)
+
+install(TARGETS boostpythongenerator DESTINATION bin)
+
+enable_testing()
+add_subdirectory(tests)
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..4ccd714
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,342 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+-------------------------------------------------------------------------
diff --git a/Doxyfile b/Doxyfile
new file mode 100644
index 0000000..f5e8d73
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,311 @@
+# Doxyfile 1.5.7.1
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING = UTF-8
+PROJECT_NAME = "Boost Python Generator Backend"
+PROJECT_NUMBER = 0.1
+OUTPUT_DIRECTORY = doc
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = /tmp/src/boostbackend/
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = YES
+QT_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+INHERIT_DOCS = YES
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 8
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+OPTIMIZE_FOR_FORTRAN = NO
+OPTIMIZE_OUTPUT_VHDL = NO
+BUILTIN_STL_SUPPORT = NO
+CPP_CLI_SUPPORT = NO
+SIP_SUPPORT = NO
+IDL_PROPERTY_SUPPORT = YES
+DISTRIBUTE_GROUP_DOC = NO
+SUBGROUPING = YES
+TYPEDEF_HIDES_STRUCT = NO
+SYMBOL_CACHE_SIZE = 0
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = YES
+EXTRACT_PRIVATE = YES
+EXTRACT_STATIC = YES
+EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_LOCAL_METHODS = NO
+EXTRACT_ANON_NSPACES = NO
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = NO
+SORT_GROUP_NAMES = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = YES
+SHOW_DIRECTORIES = NO
+SHOW_FILES = YES
+SHOW_NAMESPACES = YES
+FILE_VERSION_FILTER =
+LAYOUT_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = /tmp/src/boostbackend
+INPUT_ENCODING = UTF-8
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.d \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.idl \
+ *.odl \
+ *.cs \
+ *.php \
+ *.php3 \
+ *.inc \
+ *.m \
+ *.mm \
+ *.dox \
+ *.py \
+ *.f90 \
+ *.f \
+ *.vhd \
+ *.vhdl \
+ *.C \
+ *.CC \
+ *.C++ \
+ *.II \
+ *.I++ \
+ *.H \
+ *.HH \
+ *.H++ \
+ *.CS \
+ *.PHP \
+ *.PHP3 \
+ *.M \
+ *.MM \
+ *.PY \
+ *.F90 \
+ *.F \
+ *.VHD \
+ *.VHDL
+RECURSIVE = YES
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXCLUDE_SYMBOLS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS = *
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS = NO
+VERBATIM_HEADERS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = YES
+COLS_IN_ALPHA_INDEX = 3
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+HTML_DYNAMIC_SECTIONS = NO
+GENERATE_DOCSET = NO
+DOCSET_FEEDNAME = "Doxygen generated docs"
+DOCSET_BUNDLE_ID = org.doxygen.Project
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+CHM_INDEX_ENCODING =
+BINARY_TOC = NO
+TOC_EXPAND = NO
+GENERATE_QHP = NO
+QCH_FILE =
+QHP_NAMESPACE = org.doxygen.Project
+QHP_VIRTUAL_FOLDER = doc
+QHG_LOCATION =
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = NONE
+TREEVIEW_WIDTH = 250
+FORMULA_FONTSIZE = 10
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = YES
+USE_PDFLATEX = YES
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+XML_PROGRAMLISTING = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED =
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES = ../libgenerator/libgenerator.tag=../libgenerator
+GENERATE_TAGFILE = boostbackend.tag
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = YES
+MSCGEN_PATH =
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = YES
+DOT_FONTNAME = FreeSans
+DOT_FONTSIZE = 10
+DOT_FONTPATH =
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+GROUP_GRAPHS = NO
+UML_LOOK = NO
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = NO
+INCLUDED_BY_GRAPH = NO
+CALL_GRAPH = NO
+CALLER_GRAPH = NO
+GRAPHICAL_HIERARCHY = YES
+DIRECTORY_GRAPH = NO
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+DOT_GRAPH_MAX_NODES = 50
+MAX_DOT_GRAPH_DEPTH = 1000
+DOT_TRANSPARENT = NO
+DOT_MULTI_TARGETS = NO
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
diff --git a/boostpythongenerator.cpp b/boostpythongenerator.cpp
new file mode 100644
index 0000000..70ce4a5
--- /dev/null
+++ b/boostpythongenerator.cpp
@@ -0,0 +1,494 @@
+/*
+ * This file is part of the Boost Python Generator project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "boostpythongenerator.h"
+#include <reporthandler.h>
+
+#include <QtCore/QDir>
+#include <QtCore/QTextStream>
+#include <QtCore/QVariant>
+#include <QtCore/QRegExp>
+#include <QtCore/QDebug>
+
+#define NULL_VALUE "NULL"
+#define COMMENT_LINE_WIDTH 77
+
+static Indentor INDENT;
+static void dump_function(AbstractMetaFunctionList lst);
+
+FunctionModificationList BoostPythonGenerator::functionModifications(const AbstractMetaFunction *metaFunction)
+{
+ FunctionModificationList mods;
+ const AbstractMetaClass *cls = metaFunction->implementingClass();
+ while (cls) {
+ mods += metaFunction->modifications(cls);
+
+ if (cls == cls->baseClass())
+ break;
+ cls = cls->baseClass();
+ }
+ return mods;
+}
+
+QString BoostPythonGenerator::translateType(const AbstractMetaType *cType,
+ const AbstractMetaClass *context,
+ int option) const
+{
+ QString s;
+
+ if (context && cType &&
+ context->typeEntry()->isGenericClass() &&
+ cType->originalTemplateType()) {
+ qDebug() << "set original templateType" << cType->name();
+ cType = cType->originalTemplateType();
+ }
+
+ if (!cType) {
+ s = "void";
+ } else if (cType->isArray()) {
+ s = translateType(cType->arrayElementType(), context) + "[]";
+ } else if (cType->isEnum() || cType->isFlags()) {
+ if (option & Generator::EnumAsInts)
+ s = "int";
+ else
+ s = cType->cppSignature();
+#if 0
+ } else if (c_type->isContainer()) {
+ qDebug() << "is container" << c_type->cppSignature();
+ s = c_type->name();
+ if (!(option & SkipTemplateParameters)) {
+ s += " < ";
+ QList<AbstractMetaType *> args = c_type->instantiations();
+ for (int i = 0; i < args.size(); ++i) {
+ if (i)
+ s += ", ";
+ qDebug() << "container type: " << args.at(i)->cppSignature() << " / " << args.at(i)->instantiations().count();
+ s += translateType(args.at(i), context, option);
+ }
+ s += " > ";
+ }
+#endif
+ } else {
+ s = cType->cppSignature();
+ if (cType->isConstant() && (option & Generator::ExcludeConst))
+ s.replace("const", "");
+ if (cType->isReference() && (option & Generator::ExcludeReference))
+ s.replace("&", "");
+ }
+
+ return s;
+}
+
+QString BoostPythonGenerator::getWrapperName(const AbstractMetaClass* clazz)
+{
+ QString result = clazz->name().toLower();
+ result.replace("::", "_");
+ result += "_wrapper";
+ return result;
+}
+
+QString BoostPythonGenerator::argumentString(const AbstractMetaFunction *cppFunction,
+ const AbstractMetaArgument *cppArgument,
+ uint options) const
+{
+ QString modifiedType = cppFunction->typeReplaced(cppArgument->argumentIndex() + 1);
+ QString arg;
+
+ if (modifiedType.isEmpty())
+ arg = translateType(cppArgument->type(), cppFunction->implementingClass(), (Generator::Option) options);
+ else
+ arg = modifiedType.replace('$', '.');
+
+ if (!(options & Generator::SkipName)) {
+ arg += " ";
+ arg += cppArgument->argumentName();
+ }
+
+ QList<ReferenceCount> referenceCounts;
+ referenceCounts = cppFunction->referenceCounts(cppFunction->implementingClass(), cppArgument->argumentIndex() + 1);
+ if ((options & Generator::SkipDefaultValues) != Generator::SkipDefaultValues &&
+ !cppArgument->defaultValueExpression().isEmpty()) {
+ QString defaultValue = cppArgument->defaultValueExpression();
+ if (defaultValue == "NULL")
+ defaultValue = NULL_VALUE;
+
+ //WORKAROUND: fix this please
+ if (defaultValue.startsWith("new "))
+ defaultValue.remove(0, 4);
+
+ arg += " = " + defaultValue;
+ }
+
+ return arg;
+}
+
+void BoostPythonGenerator::writeArgument(QTextStream &s,
+ const AbstractMetaFunction *func,
+ const AbstractMetaArgument *cppArgument,
+ uint options) const
+{
+ s << argumentString(func, cppArgument, options);
+}
+
+void BoostPythonGenerator::writeFunctionArguments(QTextStream &s,
+ const AbstractMetaFunction *func,
+ uint options) const
+{
+ AbstractMetaArgumentList arguments = func->arguments();
+
+ if (options & Generator::WriteSelf) {
+ s << func->implementingClass()->name() << '&';
+ if (!(options & SkipName))
+ s << " self";
+ }
+
+ int argUsed = 0;
+ for (int i = 0; i < arguments.size(); ++i) {
+ if ((options & Generator::SkipRemovedArguments) && func->argumentRemoved(i + 1))
+ continue;
+
+ if ((options & Generator::WriteSelf) || argUsed)
+ s << ", ";
+
+ writeArgument(s, func, arguments[i], options);
+ argUsed++;
+ }
+}
+
+QString BoostPythonGenerator::functionReturnType(const AbstractMetaFunction* func, int option)
+{
+ QString modifiedReturnType = QString(func->typeReplaced(0));
+ if (!modifiedReturnType.isNull() && (!(option & OriginalTypeDescription)))
+ return modifiedReturnType;
+ else
+ return translateType(func->type(), func->implementingClass(), option);
+}
+
+QString BoostPythonGenerator::functionSignature(const AbstractMetaFunction *func,
+ QString prepend,
+ QString append,
+ int option,
+ int argCount)
+{
+ AbstractMetaArgumentList arguments = func->arguments();
+ int argument_count = argCount < 0 ? arguments.size() : argCount;
+
+
+ QString result;
+ QTextStream s(&result);
+ // The actual function
+ if (!(func->isEmptyFunction() ||
+ func->isNormal() ||
+ func->isSignal())) {
+ option = Option(option | Generator::SkipReturnType);
+ } else {
+ s << functionReturnType(func, option) << ' ';
+ }
+
+ // name
+ QString name(func->originalName());
+ if (func->isConstructor())
+ name = getWrapperName(func->ownerClass());
+
+ s << prepend << name << append << "(";
+ writeFunctionArguments(s, func, option);
+ s << ")";
+
+ if (func->isConstant() && (!(option & Generator::ExcludeMethodConst)))
+ s << " const";
+
+ return result;
+}
+
+QString BoostPythonGenerator::signatureForDefaultVirtualMethod(const AbstractMetaFunction *cppFunction,
+ QString prepend,
+ QString append,
+ int option,
+ int arg_count)
+{
+ QString defaultMethodSignature = functionSignature(cppFunction, prepend, append, option, arg_count);
+ QString staticSelf("(");
+ if (cppFunction->isConstant())
+ staticSelf += "const ";
+
+ staticSelf += cppFunction->ownerClass()->qualifiedCppName() + "& ";
+ if (!(option & SkipName))
+ staticSelf += " self";
+
+ if (cppFunction->arguments().size() > 0)
+ staticSelf += ", ";
+
+ defaultMethodSignature.replace(defaultMethodSignature.lastIndexOf(") const"), 7, ")");
+ defaultMethodSignature.replace(defaultMethodSignature.indexOf('('), 1, staticSelf);
+ return defaultMethodSignature;
+}
+
+void BoostPythonGenerator::writeArgumentNames(QTextStream &s,
+ const AbstractMetaFunction *func,
+ uint options) const
+{
+ AbstractMetaArgumentList arguments = func->arguments();
+ int argCount = 0;
+ for (int j = 0, max = arguments.size(); j < max; j++) {
+
+ if ((options & Generator::SkipRemovedArguments) &&
+ (func->argumentRemoved(arguments.at(j)->argumentIndex() + 1))) {
+ continue;
+ }
+
+ if (argCount > 0)
+ s << ", ";
+
+ if ((options & Generator::BoxedPrimitive) &&
+ !arguments.at(j)->type()->isReference() &&
+ (arguments.at(j)->type()->isQObject() ||
+ arguments.at(j)->type()->isObject())) {
+ s << "PySide::ptr( " << arguments.at(j)->argumentName() << ")";
+ } else {
+ s << arguments.at(j)->argumentName();
+ }
+ argCount++;
+ }
+}
+
+AbstractMetaFunctionList BoostPythonGenerator::queryGlobalOperators(const AbstractMetaClass *cppClass)
+{
+ AbstractMetaFunctionList result;
+
+ foreach (AbstractMetaFunction *func, cppClass->functions()) {
+ if (func->isInGlobalScope() && func->isOperatorOverload())
+ result.append(func);
+ }
+ return result;
+}
+
+AbstractMetaFunctionList BoostPythonGenerator::sortContructor(AbstractMetaFunctionList list)
+{
+ AbstractMetaFunctionList result;
+
+ foreach (AbstractMetaFunction *func, list) {
+ bool inserted = false;
+ foreach (AbstractMetaArgument *arg, func->arguments()) {
+ if (arg->type()->isFlags() || arg->type()->isEnum()) {
+ result.push_back(func);
+ inserted = true;
+ break;
+ }
+ }
+ if (!inserted)
+ result.push_front(func);
+ }
+
+ return result;
+}
+
+AbstractMetaFunctionList BoostPythonGenerator::queryFunctions(const AbstractMetaClass *cppClass, bool allFunctions)
+{
+ AbstractMetaFunctionList result;
+
+ if (allFunctions) {
+ int default_flags = AbstractMetaClass::NormalFunctions | AbstractMetaClass::Visible;
+ default_flags |= cppClass->isInterface() ? 0 : AbstractMetaClass::ClassImplements;
+
+ // Constructors
+ result = cppClass->queryFunctions(AbstractMetaClass::Constructors |
+ default_flags);
+
+ // put enum constructor first to avoid conflict with int contructor
+ result = sortContructor(result);
+
+ // Final functions
+ result += cppClass->queryFunctions(AbstractMetaClass::FinalInTargetLangFunctions |
+ AbstractMetaClass::NonStaticFunctions |
+ default_flags);
+
+ //virtual
+ result += cppClass->queryFunctions(AbstractMetaClass::VirtualInTargetLangFunctions |
+ AbstractMetaClass::NonStaticFunctions |
+ default_flags);
+
+ // Static functions
+ result += cppClass->queryFunctions(AbstractMetaClass::StaticFunctions | default_flags);
+
+ // Empty, private functions, since they aren't caught by the other ones
+ result += cppClass->queryFunctions(AbstractMetaClass::Empty |
+ AbstractMetaClass::Invisible | default_flags);
+ // Signals
+ result += cppClass->queryFunctions(AbstractMetaClass::Signals | default_flags);
+ } else {
+ result = cppClass->functionsInTargetLang();
+ }
+
+ return result;
+}
+
+void BoostPythonGenerator::writeFunctionCall(QTextStream &s,
+ const AbstractMetaFunction* func,
+ uint options)
+
+{
+ if (!(options & Generator::SkipName))
+ s << (func->isConstructor() ? func->ownerClass()->qualifiedCppName() : func->originalName());
+
+ s << '(';
+ writeArgumentNames(s, func, options);
+ s << ')';
+}
+
+AbstractMetaFunctionList BoostPythonGenerator::filterFunctions(const AbstractMetaClass *cppClass)
+{
+ AbstractMetaFunctionList lst = queryFunctions(cppClass, true);
+ foreach (AbstractMetaFunction *func, lst) {
+ //skip signals
+ if (func->isSignal() ||
+ func->isDestructor() ||
+ (func->isModifiedRemoved() && !func->isAbstract())) {
+ lst.removeOne(func);
+ }
+ }
+
+ //virtual not implemented in current class
+ AbstractMetaFunctionList virtual_lst = cppClass->queryFunctions(AbstractMetaClass::VirtualFunctions);
+ foreach (AbstractMetaFunction *func, virtual_lst) {
+ if ((func->implementingClass() != cppClass) &&
+ !lst.contains(func)) {
+ lst.append(func);
+ }
+ }
+
+ //append global operators
+ foreach (AbstractMetaFunction *func , queryGlobalOperators(cppClass)) {
+ if (!lst.contains(func))
+ lst.append(func);
+ }
+
+ return lst;
+ //return cpp_class->functions();
+}
+
+CodeSnipList BoostPythonGenerator::getCodeSnips(const AbstractMetaFunction *func)
+{
+ CodeSnipList result;
+ const AbstractMetaClass *cppClass = func->implementingClass();
+ while (cppClass) {
+ foreach (FunctionModification mod, func->modifications(cppClass)) {
+ if (mod.isCodeInjection())
+ result << mod.snips;
+ }
+
+ if (cppClass == cppClass->baseClass())
+ break;
+ cppClass = cppClass->baseClass();
+ }
+
+ return result;
+}
+
+void BoostPythonGenerator::writeCodeSnips(QTextStream &s,
+ const CodeSnipList &codeSnips,
+ CodeSnip::Position position,
+ TypeSystem::Language language,
+ const AbstractMetaFunction *func)
+{
+ Indentation indentation(INDENT);
+ foreach (CodeSnip snip, codeSnips) {
+ if ((snip.position != position) ||
+ !(snip.language & language)) {
+ continue;
+ }
+
+ QString code;
+ QTextStream tmpStream(&code);
+ snip.formattedCode(tmpStream, INDENT);
+
+ if (func)
+ replaceTemplateVariables(code, func);
+
+ s << code << endl;
+ }
+}
+
+bool BoostPythonGenerator::canCreateWrapperFor(const AbstractMetaClass* cppClass)
+{
+ return !cppClass->hasPrivateDestructor() && !cppClass->isNamespace();
+}
+
+
+
+QStringList BoostPythonGenerator::getBaseClasses(const AbstractMetaClass *cppClass)
+{
+ QStringList baseClass;
+
+ if (!cppClass->baseClassName().isEmpty() &&
+ (cppClass->name() != cppClass->baseClassName())) {
+ baseClass.append(cppClass->baseClassName());
+ }
+
+ foreach (AbstractMetaClass *interface, cppClass->interfaces()) {
+ AbstractMetaClass *aux = interface->primaryInterfaceImplementor();
+ if (!aux)
+ continue;
+
+ //skip templates
+ if (aux->templateArguments().size() > 0)
+ continue;
+
+ if (!aux->name().isEmpty() && (cppClass->qualifiedCppName() != aux->qualifiedCppName()))
+ baseClass.append(aux->qualifiedCppName());
+ }
+
+ return baseClass;
+}
+
+
+bool BoostPythonGenerator::isCopyable(const AbstractMetaClass *cppClass)
+{
+ if (cppClass->typeEntry()->copyable() == ComplexTypeEntry::Unknown)
+ return cppClass->hasCloneOperator();
+ else
+ return (cppClass->typeEntry()->copyable() == ComplexTypeEntry::CopyableSet);
+
+ return false;
+}
+
+static void dump_function(AbstractMetaFunctionList lst)
+{
+ qDebug() << "DUMP FUNCTIONS: ";
+ foreach (AbstractMetaFunction *func, lst) {
+ qDebug() << "*" << func->ownerClass()->name()
+ << func->signature()
+ << "Private: " << func->isPrivate()
+ << "Empty: " << func->isEmptyFunction()
+ << "Static:" << func->isStatic()
+ << "Signal:" << func->isSignal()
+ << "ClassImplements: " << (func->ownerClass() != func->implementingClass())
+ << "is operator:" << func->isOperatorOverload()
+ << "is global:" << func->isInGlobalScope();
+ }
+}
+
+
+bool BoostPythonGenerator::prepareGeneration(const QMap<QString, QString>&)
+{
+ return true;
+}
diff --git a/boostpythongenerator.h b/boostpythongenerator.h
new file mode 100644
index 0000000..4ad191b
--- /dev/null
+++ b/boostpythongenerator.h
@@ -0,0 +1,147 @@
+/*
+ * This file is part of the Boost Python Generator project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef BOOSTPYTHONGENERATOR_H
+#define BOOSTPYTHONGENERATOR_H
+
+#include <apiextractor/generator.h>
+#include <QtCore/QTextStream>
+
+class DocParser;
+
+/**
+* Abstract generator that contains common methods used in CppGenerator and HppGenerator.
+*/
+class BoostPythonGenerator : public Generator
+{
+public:
+ /**
+ * Translate metatypes to boost::python format.
+ * \param boost_type a pointer to metatype
+ * \param context the current meta class
+ * \param option some extra options
+ * \return the metatype translated to boost::python format
+ */
+ virtual QString translateType(const AbstractMetaType *boost_type,
+ const AbstractMetaClass *context,
+ int option = NoOption) const;
+ /**
+ * Write a function argument in the boost::python format in the text stream \p s.
+ * This function just call \code s << argumentString(); \endcode
+ * \param s text stream used to write the output.
+ * \param boost_fuction the current metafunction.
+ * \param boost_argument metaargument information to be parsed.
+ * \param options some extra options.
+ */
+ void writeArgument(QTextStream &s,
+ const AbstractMetaFunction *boost_function,
+ const AbstractMetaArgument *boost_argument,
+ uint options = 0) const;
+ /**
+ * Create a QString in the boost::python format to an function argument.
+ * \param boost_fuction the current metafunction.
+ * \param boost_argument metaargument information to be parsed.
+ * \param options some extra options.
+ */
+ QString argumentString(const AbstractMetaFunction *boost_function,
+ const AbstractMetaArgument *boost_argument,
+ uint options = 0) const;
+
+ void writeArgumentNames(QTextStream &s,
+ const AbstractMetaFunction *cpp_function,
+ uint options = 0) const;
+
+ /**
+ * Function used to write the fucntion arguments on the class buffer.
+ * \param s the class output buffer
+ * \param boost_function the pointer to metafunction information
+ * \param count the number of function arguments
+ * \param options some extra options used during the parser
+ */
+ void writeFunctionArguments(QTextStream &s,
+ const AbstractMetaFunction *boost_function,
+ uint options = 0) const;
+ QString functionReturnType(const AbstractMetaFunction* func, int option = NoOption);
+ /**
+ * Write a code snip into the buffer \p s.
+ * CodeSnip are codes inside inject-code tags.
+ * \param s the buffer
+ * \param cpp_function the cpp function
+ * \param code_snips a list of code snips
+ * \param position the position to insert the code snip
+ * \param language the kind of code snip
+ */
+ void writeCodeSnips(QTextStream &s,
+ const CodeSnipList &code_snips,
+ CodeSnip::Position position,
+ TypeSystem::Language language,
+ const AbstractMetaFunction *cpp_function = 0);
+ /// returns the code snips of a function
+ CodeSnipList getCodeSnips(const AbstractMetaFunction *func);
+ static bool canCreateWrapperFor(const AbstractMetaClass* cppClass);
+ /**
+ * Function witch parse the metafunction information
+ * \param cpp_function the function witch will be parserd
+ * \param option some extra options
+ * \param arg_count the number of function arguments
+ */
+ QString functionSignature(const AbstractMetaFunction *boost_function,
+ QString prepend = "",
+ QString append = "",
+ int option = NoOption,
+ int arg_count = -1);
+
+ QString signatureForDefaultVirtualMethod(const AbstractMetaFunction *cpp_function,
+ QString prepend = "",
+ QString append = "_default",
+ int option = NoOption,
+ int arg_count = -1);
+
+ virtual QString subDirectoryForClass(const AbstractMetaClass* metaClass) const
+ {
+ return subDirectoryForPackage(metaClass->package());
+ }
+
+ QStringList getBaseClasses(const AbstractMetaClass* cppClass);
+
+ static QString getWrapperName(const AbstractMetaClass* clazz);
+
+
+ virtual bool prepareGeneration(const QMap<QString, QString>& args);
+
+protected:
+ // verify if the class is copyalbe
+ bool isCopyable(const AbstractMetaClass *cpp_class);
+
+ static FunctionModificationList functionModifications(const AbstractMetaFunction *meta_function);
+ AbstractMetaFunctionList queryFunctions(const AbstractMetaClass *cpp_class, bool all_function = false);
+ void writeFunctionCall(QTextStream &s, const AbstractMetaFunction *cpp_func, uint options = 0);
+
+ AbstractMetaFunctionList filterFunctions(const AbstractMetaClass *cpp_class);
+ AbstractMetaFunctionList queryGlobalOperators(const AbstractMetaClass *cpp_class);
+ AbstractMetaFunctionList sortContructor(AbstractMetaFunctionList list);
+};
+
+
+#endif // BOOSTPYTHONGENERATOR_H
+
diff --git a/boostpythongeneratorversion.h.in b/boostpythongeneratorversion.h.in
new file mode 100644
index 0000000..9d7d2b6
--- /dev/null
+++ b/boostpythongeneratorversion.h.in
@@ -0,0 +1,4 @@
+#ifndef BOOSTPYTHONGENERATORVERSION_H
+#define BOOSTPYTHONGENERATORVERSION_H
+#define BOOSTPYTHONGENERATOR_VERSION "@boostpythongenerator_VERSION@"
+#endif
diff --git a/cmake_uninstall.cmake b/cmake_uninstall.cmake
new file mode 100644
index 0000000..df95fb9
--- /dev/null
+++ b/cmake_uninstall.cmake
@@ -0,0 +1,21 @@
+IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+ MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
+ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+
+FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
+STRING(REGEX REPLACE "\n" ";" files "${files}")
+FOREACH(file ${files})
+ MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
+ IF(EXISTS "$ENV{DESTDIR}${file}")
+ EXEC_PROGRAM(
+ "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
+ OUTPUT_VARIABLE rm_out
+ RETURN_VALUE rm_retval
+ )
+ IF(NOT "${rm_retval}" STREQUAL 0)
+ MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
+ ENDIF(NOT "${rm_retval}" STREQUAL 0)
+ ELSE(EXISTS "$ENV{DESTDIR}${file}")
+ MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
+ ENDIF(EXISTS "$ENV{DESTDIR}${file}")
+ENDFOREACH(file)
diff --git a/convertergenerator.cpp b/convertergenerator.cpp
new file mode 100644
index 0000000..ea52b91
--- /dev/null
+++ b/convertergenerator.cpp
@@ -0,0 +1,180 @@
+/*
+ * This file is part of the Boost Python Generator project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <QtCore/QDebug>
+#include <fileout.h>
+#include "convertergenerator.h"
+
+static Indentor INDENT;
+
+ConverterGenerator::ConverterGenerator()
+{
+ // QPair
+ m_conversions << qMakePair(QString("QPair<"), &m_qpairTypes);
+ // QList
+ m_conversions << qMakePair(QString("QList<"), &m_qlistTypes);
+ // QVector
+ m_conversions << qMakePair(QString("QVector<"), &m_qvectorTypes);
+ // QMap
+ m_conversions << qMakePair(QString("QMap<"), &m_qmapTypes);
+ // QHash
+ m_conversions << qMakePair(QString("QHash<"), &m_qhashTypes);
+ // QMultiMap
+ m_conversions << qMakePair(QString("QMultiMap<"), &m_qmultiMapTypes);
+
+}
+
+void ConverterGenerator::finishGeneration()
+{
+ if (!classes().size())
+ return;
+
+ QString fileOutPath;
+
+ foreach (AbstractMetaClass *cls, classes()) {
+ if (!shouldGenerate(cls))
+ continue;
+
+ if (fileOutPath.isNull()) {
+ m_packageName = cls->package();
+ fileOutPath = outputDirectory() + '/' + subDirectoryForClass(cls)
+ + "/converter_register_" + moduleName().toLower() + ".hpp";
+ }
+
+ foreach (AbstractMetaFunction* func, filterFunctions(cls))
+ checkFunctionMetaTypes(func);
+ }
+
+ FileOut fileOut(fileOutPath);
+ QTextStream& s = fileOut.stream;
+
+ // write license comment
+ s << licenseComment() << endl;
+
+ s << "#ifndef CONVERTERREGISTER_" << moduleName().toUpper() << "_HPP\n";
+ s << "#define CONVERTERREGISTER_" << moduleName().toUpper() << "_HPP\n\n";
+
+ //Includes
+ QStringList includes;
+ foreach (AbstractMetaClass *cls, classes()) {
+ if (cls->typeEntry()->include().isValid()) {
+ QString include_file = cls->typeEntry()->include().toString();
+ if (!includes.contains(include_file)) {
+ s << include_file << endl;
+ includes << include_file;
+ }
+ }
+
+ if (cls->typeEntry()->generateCode()) {
+ QList<Include> extra_includes = cls->typeEntry()->extraIncludes();
+ foreach (Include include, extra_includes) {
+ if (!includes.contains(include.toString())) {
+ s << include.toString() << endl;
+ includes << include.toString();
+ }
+ }
+ }
+ }
+
+ s << "#include \"type_converter.hpp\"\n\n";
+
+ s << "void register_type_converters_" << moduleName().toLower() << "()\n{\n";
+ Indentation indent(INDENT);
+ writeConverterRegistration(s, "register_qpair_converter", "QPair", m_qpairTypes);
+ writeConverterRegistration(s, "register_container_converter", "QList", m_qlistTypes);
+ writeConverterRegistration(s, "register_container_converter", "QVector", m_qvectorTypes);
+ writeConverterRegistration(s, "register_dict_converter", "QMap", m_qmapTypes);
+ writeConverterRegistration(s, "register_dict_converter", "QHash", m_qhashTypes);
+ writeConverterRegistration(s, "register_multimap_converter", "QMultiMap", m_qmultiMapTypes);
+ s << "}\n\n";
+ s << "#endif\n\n";
+
+ m_numGeneratedWritten = m_qpairTypes.size() + m_qlistTypes.size() +
+ m_qvectorTypes.size() + m_qmapTypes.size() +
+ m_qhashTypes.size();
+}
+
+void ConverterGenerator::writeConverterRegistration(QTextStream& out,
+ const QString& funcName,
+ const QString& type,
+ const QSet<QString>& params)
+{
+ foreach (QString param, params) {
+ QString completeType(QMetaObject::normalizedType(
+ (type + '<' + param + " >").toLatin1().data()));
+ out << INDENT << "PySide::" << funcName;
+ out << '<' << completeType << " >(\"";
+ out << completeType << "\");" << endl;
+ }
+}
+
+void ConverterGenerator::checkFunctionMetaTypes(AbstractMetaFunction* func)
+{
+ if (func->type())
+ checkMetaType(functionReturnType(func));
+
+ foreach (AbstractMetaArgument* arg, func->arguments()) {
+ if (arg->type()) {
+ checkMetaType(argumentString(func, arg,
+ (Generator::SkipName | Generator::SkipDefaultValues)));
+ }
+ }
+}
+
+// FIXME Use some AbstracyMetaAnything info instead of parse the cpp signature?
+void ConverterGenerator::checkMetaType(const QString& cppSignature)
+{
+ QRegExp typeRegex("Q\\w+");
+
+ foreach (Conversion conv, m_conversions) {
+ int index = cppSignature.indexOf(conv.first);
+ if (index >= 0) {
+ QString templateArg = extractTemplateArgument(cppSignature.right(cppSignature.length() - index - conv.first.length()));
+ conv.second->insert(templateArg);
+ // detect types to generate includes
+ int offset = 0;
+ while ((offset = typeRegex.indexIn(templateArg, offset)) != -1) {
+ const QString cap(typeRegex.cap(0));
+ offset += cap.length();
+ }
+ }
+ }
+}
+
+QString ConverterGenerator::extractTemplateArgument(const QString& templateParams)
+{
+ int stack = 0;
+ for (int i = 0; i < templateParams.length(); ++i) {
+ QChar c = templateParams[i];
+ if (c == '<') {
+ stack++;
+ } else if (c == '>') {
+ stack--;
+ if (stack < 0)
+ return templateParams.left(i).trimmed();
+ }
+ }
+ Q_ASSERT(false);
+ return QString();
+}
+
diff --git a/convertergenerator.h b/convertergenerator.h
new file mode 100644
index 0000000..8f91377
--- /dev/null
+++ b/convertergenerator.h
@@ -0,0 +1,77 @@
+/*
+ * This file is part of the Boost Python Generator project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef CONVERTERGENERATOR_H
+#define CONVERTERGENERATOR_H
+
+// #include <QRegExp>
+#include <QtCore/QSet>
+#include "boostpythongenerator.h"
+
+/**
+* Generator for convertions between python collections and Qt collections.
+*
+* It generates a file called converter_register_MODULENAME.hpp with only one
+* function called register_type_converters_MODULENAME, where MODULENAME is the current module name.
+* QPair are converted to python tuples, QList, QVector and QLinkedList to python lists, QHash and QMap to python dicts.
+*/
+class ConverterGenerator : public BoostPythonGenerator
+{
+public:
+ ConverterGenerator();
+
+ const char* name() const
+ {
+ return "ConverterGenerator";
+ }
+
+protected:
+ void generateClass(QTextStream& s, const AbstractMetaClass* clazz)
+ {
+ }
+
+ void finishGeneration();
+ QString fileNameForClass(const AbstractMetaClass* cppClass) const
+ {
+ return QString();
+ }
+private:
+ void checkFunctionMetaTypes(AbstractMetaFunction* func);
+ void checkMetaType(const QString& cppSignature);
+ QString extractTemplateArgument(const QString& templateParams);
+
+ void writeConverterRegistration(QTextStream& out, const QString& func_name, const QString& type, const QSet<QString>& params);
+
+ typedef QPair<QString, QSet<QString>* > Conversion;
+ typedef QList<Conversion> ConversionList;
+ ConversionList m_conversions;
+ QSet<QString> m_qpairTypes;
+ QSet<QString> m_qlistTypes;
+ QSet<QString> m_qvectorTypes;
+ QSet<QString> m_qmapTypes;
+ QSet<QString> m_qhashTypes;
+ QSet<QString> m_qmultiMapTypes;
+};
+
+#endif // CONVERSIONGENERATOR_H
+
diff --git a/cppgenerator.cpp b/cppgenerator.cpp
new file mode 100644
index 0000000..ae1f625
--- /dev/null
+++ b/cppgenerator.cpp
@@ -0,0 +1,1421 @@
+/*
+ * This file is part of the Boost Python Generator project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#include "cppgenerator.h"
+#include <apiextractor/reporthandler.h>
+#include <apiextractor/fileout.h>
+#include <apiextractor/abstractmetalang.h>
+
+#include <QtCore/QDir>
+#include <QtCore/QTextStream>
+#include <QtCore/QVariant>
+#include <QtCore/QRegExp>
+#include <QtCore/QDebug>
+#include <QtCore/QListIterator>
+
+static Indentor INDENT;
+
+// utiliy functions
+inline QString getMethodPointerString(const AbstractMetaFunction* func)
+{
+ QString className;
+ if (!func->declaringClass()->isAbstract())
+ className = func->declaringClass()->qualifiedCppName();
+ else
+ className = func->ownerClass()->qualifiedCppName();
+
+ return '&' + className + "::" + func->originalName();
+}
+
+static QString nameForModifiedCtorFunction(const AbstractMetaFunction* func) {
+ QString res = func->ownerClass()->name().toLower().replace("::", "_");
+ res += "_constructor";
+ foreach (AbstractMetaArgument* arg, func->arguments()) {
+ res += '_';
+ res += arg->type()->name().toLower();
+ }
+ return res;
+}
+
+static QString createStaticFunctionName(const AbstractMetaFunction* func)
+{
+ QString funcName;
+ QString originalName(func->name());
+
+
+ funcName = func->ownerClass()->name().toLower();
+
+ //remove initial 'Q'
+ if (funcName.startsWith('q'))
+ funcName = funcName.remove(0, 1);
+
+ //upercase first letter
+ funcName += originalName[0].toUpper() + originalName.mid(1);
+
+ return funcName;
+}
+
+QString CppGenerator::fileNameForClass(const AbstractMetaClass* cppClass) const
+{
+ return getWrapperName(cppClass) + QLatin1String(".cpp");
+}
+
+QString CppGenerator::getFuncTypedefName(const AbstractMetaFunction* func) const
+{
+ return func->name() + QLatin1String("_type");
+}
+
+void CppGenerator::writeConstructorInitialization(QTextStream &s, const AbstractMetaFunction *function)
+{
+ QStringList nonOpts;
+ QStringList opts;
+
+ foreach (AbstractMetaArgument *arg, function->arguments()) {
+ uint options = SkipName | SkipDefaultValues;
+ QString argType = argumentString(function, arg, options);
+ if (arg->defaultValueExpression().isEmpty())
+ nonOpts << argType;
+ else
+ opts << argType;
+ }
+
+ bool hasModifications = function->allowThread() || function->hasInjectedCode();
+
+ if (hasModifications) {
+ s << "\"__init__\", python::make_constructor("
+ << nameForModifiedCtorFunction(function);
+ } else {
+ s << "python::init< ";
+
+ if (nonOpts.size() > 0)
+ s << nonOpts.join(", ");
+
+ if (opts.size() > 0) {
+ if (nonOpts.size() > 0)
+ s << ", ";
+
+ s << "python::optional< " << opts.join(",") << " > ";
+ }
+
+ s << " > ()";
+ }
+
+ QString callPolicy = getFunctionCallPolicy(function);
+ QString parentType;
+ const AbstractMetaClass *cppClass = function->ownerClass();
+ uint closePolicy = 0;
+ bool hasPolicy = false;
+
+ if (
+ !hasModifications &&
+ (!cppClass->isPolymorphic() || cppClass->hasPrivateDestructor() || cppClass->isNamespace())
+ ) {
+ closePolicy++;
+ hasPolicy = true;
+ s << "[ PySide::register_wrapper_object< "
+ << function->ownerClass()->qualifiedCppName();
+ }
+
+ if (callPolicy.isEmpty()) {
+ int parentIndex = -1;
+ //try find for parent arg to create callPolicy
+ foreach (AbstractMetaArgument *arg, function->arguments()) {
+ if (arg->argumentName() == "parent") {
+ parentIndex = arg->argumentIndex();
+ parentType = translateType(arg->type(), function->ownerClass(),
+ Generator::ExcludeConst | Generator::ExcludeReference).replace("*", "");
+ break;
+ }
+ }
+ if (parentIndex != -1) {
+ if (!closePolicy)
+ s << (hasModifications ? ", " : "[ ");
+ else
+ s << ", ";
+
+ s << "parent_policy_add< " << parentIndex + 2 << ", 1, "
+ << parentType << " , " << function->ownerClass()->qualifiedCppName();
+
+ hasPolicy = true;
+ closePolicy++;
+ }
+ } else {
+ if (!closePolicy)
+ s << (hasModifications ? ", " : "[ ");
+ else
+ s << ", ";
+
+ if (callPolicy.endsWith("()"))
+ callPolicy = callPolicy.remove(callPolicy.size() - 2, 2);
+
+ s << callPolicy;
+ hasPolicy = true;
+ }
+
+ while(closePolicy) {
+ s << " > ";
+ closePolicy--;
+ }
+
+ if (hasModifications)
+ s << ')';
+ else if (hasPolicy)
+ s << "() ]";
+}
+
+QString CppGenerator::getFunctionReturnType(const AbstractMetaFunction* func)
+{
+ QString modifiedReturnType = QString(func->typeReplaced(0));
+
+ return modifiedReturnType.isNull() ? translateType(func->type(), func->implementingClass()) : modifiedReturnType;
+}
+
+QString CppGenerator::writeFunctionCast(QTextStream &s,
+ const AbstractMetaFunction* func,
+ const QString& castNameSuffix,
+ const QString& className)
+{
+ QString castName = getFuncTypedefName(func) + castNameSuffix;
+ const AbstractMetaClass* cppClass = func->ownerClass();
+ bool isWrapped = !func->isVirtual() &&
+ (func->hasInjectedCode() || func->isThread() || func->allowThread());
+ bool isVirtualMethodDefault = castNameSuffix == "_default";
+
+ s << INDENT << "typedef ";
+ s << getFunctionReturnType(func);
+ s << " (";
+ if (cppClass && !func->isStatic() && func->ownerClass() && !isVirtualMethodDefault) {
+ if (!isWrapped) {
+ // pointer to a class method
+ if (!className.isEmpty())
+ s << className;
+ else if (func->isVirtual() && !func->declaringClass()->isAbstract())
+ s << func->declaringClass()->qualifiedCppName();
+ else
+ s << cppClass->qualifiedCppName();
+
+ s << "::";
+ }
+ }
+
+ s << '*' << castName << ") (";
+ if (isVirtualMethodDefault) {
+ if (func->isConstant())
+ s << "const ";
+
+ s << func->implementingClass()->qualifiedCppName() << "&";
+ if (func->arguments().size() > 0)
+ s << ", ";
+ }
+ int options = SkipName | SkipDefaultValues | SkipRemovedArguments;
+ if (isWrapped && !func->isStatic())
+ options |= WriteSelf;
+
+ writeFunctionArguments(s, func, options);
+ s << ')';
+
+ if (func->isConstant() && !isWrapped && !isVirtualMethodDefault)
+ s << " const";
+
+ s << ';' << endl;
+
+ return castName;
+}
+
+QString CppGenerator::verifyDefaultReturnPolicy(const AbstractMetaFunction *cppFunction, const QString& callPolicy)
+{
+ AbstractMetaType *type = cppFunction->type();
+ QString returnPolicy;
+
+ if (type && type->isReference() && type->isConstant()) {
+ returnPolicy = "python::return_value_policy<python::copy_const_reference";
+ if (!callPolicy.isEmpty())
+ returnPolicy += ", " + callPolicy;
+ returnPolicy += " >()";
+ } else if (type && (type->isReference() || type->isQObject() || type->isObject())) {
+ bool cppOwnership = type->isConstant();
+ if (cppFunction->isStatic() || cppOwnership) {
+ returnPolicy = "python::return_value_policy<PySide::return_ptr_object< "
+ + (cppOwnership ? QString("true") : QString("false")) + "> >()";
+ } else if (type->isQObject() || type->isObject()) {
+ returnPolicy = QString("PySide::return_object<1, 0, %1, %2 %3 %4 >()")
+ .arg(getArgumentType(cppFunction->ownerClass(), cppFunction, -1))
+ .arg(getArgumentType(cppFunction->ownerClass(), cppFunction, 0))
+ .arg(callPolicy.isEmpty() ? "" : ",")
+ .arg(callPolicy);
+ } else {
+ returnPolicy = QString("python::return_internal_reference<%1 %2>()")
+ .arg(callPolicy.isEmpty() ? "" : ",")
+ .arg(callPolicy);
+ }
+ } else if (!callPolicy.isEmpty()) {
+ returnPolicy = callPolicy + "()";
+ }
+
+ return returnPolicy;
+}
+
+static int boost_parent_policy_index(int i, const AbstractMetaFunction* func = 0)
+{
+ if (func && func->isStatic())
+ return i;
+
+ if (i == -1)
+ return 1;
+ else if (i > 0)
+ return i + 1;
+ else
+ return i;
+}
+
+QString CppGenerator::getArgumentType(const AbstractMetaClass *cppClass, const AbstractMetaFunction *func, int idx)
+{
+ QString retval;
+ if (idx == -1) {
+ retval = cppClass->qualifiedCppName();
+ } else if (idx == 0 && func->type()) {
+ retval = translateType(func->type(), cppClass,
+ Generator::ExcludeConst | Generator::ExcludeReference);
+ } else if (idx > 0) {
+ retval = argumentString(func, func->arguments()[idx-1],
+ Generator::SkipDefaultValues | Generator::ExcludeConst |
+ Generator::ExcludeReference | Generator::SkipName);
+ }
+
+ retval = retval.trimmed();
+ if (retval.endsWith('*'))
+ retval.chop(1);
+ return retval;
+}
+
+QString CppGenerator::getFunctionCallPolicy(const AbstractMetaFunction *func)
+{
+ QString callPolicy;
+ QStringList callPolicies;
+ bool returnChild = false;
+ const AbstractMetaClass* cppClass = func->implementingClass();
+
+ const int numArgs = func->arguments().count();
+
+ for (int i = -1; i <= numArgs; ++i) {
+ ArgumentOwner ao = func->argumentOwner(cppClass, i);
+ //Parent Policy
+ if ((ao.index != -2) && (ao.index != i)) {
+ switch (ao.action) {
+ case ArgumentOwner::Add:
+ if (!i) {
+ callPolicy = "return_object<";
+ returnChild = true;
+ } else {
+ callPolicy = "parent_policy_add<";
+ }
+ break;
+ case ArgumentOwner::Remove:
+ callPolicy = "parent_policy_remove<";
+ break;
+ default:
+ continue;
+ }
+
+ callPolicy += QString("%1, %2, %3, %4")
+ .arg(boost_parent_policy_index(ao.index, func))
+ .arg(boost_parent_policy_index(i, func))
+ .arg(getArgumentType(cppClass, func, ao.index))
+ .arg(getArgumentType(cppClass, func, i));
+
+ callPolicies << callPolicy;
+ } else if (i) { //only function args ignore return value
+ //Ownership policy
+ bool changeOwnership = false;
+ bool releaseOwnership = false;
+ TypeSystem::Ownership owner = func->ownership(cppClass,
+ TypeSystem::TargetLangCode, i);
+
+ switch(owner)
+ {
+ case TypeSystem::CppOwnership:
+ releaseOwnership = true;
+ case TypeSystem::TargetLangOwnership:
+ changeOwnership = true;
+ break;
+ default:
+ changeOwnership = false;
+ }
+
+ if (changeOwnership)
+ {
+ QString ownershipPolicy = QString("transfer_ownership<%1, %2, %3")
+ .arg(boost_parent_policy_index(i, func))
+ .arg(releaseOwnership ? "true" : "false")
+ .arg(getArgumentType(cppClass, func, i));
+ callPolicies << ownershipPolicy;
+ }
+ }
+ }
+
+ if (callPolicies.size() > 0) {
+ callPolicy = callPolicies.join(", ");
+ for (int i = 0; i < callPolicies.count(); ++i)
+ callPolicy += " >";
+ }
+
+ QString returnPolicy;
+
+ //return value
+ bool cppOwnership = false;
+
+ if (!returnChild) {
+ switch (func->ownership(cppClass, TypeSystem::TargetLangCode, 0))
+ {
+ case TypeSystem::CppOwnership:
+ cppOwnership = true;
+ case TypeSystem::TargetLangOwnership:
+ {
+ QString cppOwnershipFlag = (cppOwnership ? "true" : "false");
+ returnPolicy = "python::return_value_policy< PySide::return_ptr_object<" + cppOwnershipFlag + "> ";
+ if (!callPolicy.isEmpty())
+ returnPolicy += ", " + callPolicy;
+ returnPolicy += " >()";
+ break;
+ }
+ default:
+ returnPolicy = verifyDefaultReturnPolicy(func, callPolicy);
+ break;
+ }
+ }
+
+ //return policy
+ if (func->shouldReturnThisObject())
+ return "python::return_self< " + callPolicy + " >()";
+ else if (!returnPolicy.isEmpty())
+ return returnPolicy;
+ else if (!callPolicy.isEmpty())
+ return callPolicy + "()";
+
+ return QString();
+}
+
+/*!\internal
+ Function used to write the enum boost code on the buffer
+ \param s the output buffer
+ \param cpp_enum the pointer to metaenum information to be translated to boost
+*/
+void CppGenerator::writeEnum(QTextStream &s,
+ const AbstractMetaEnum *cppEnum,
+ const QString &nameSpace)
+{
+ s << INDENT << "python::enum_<" << nameSpace << cppEnum->name();
+ s << ">(\"" << cppEnum->name() << "\")" << endl;
+ const AbstractMetaEnumValueList &values = cppEnum->values();
+ EnumTypeEntry *ete = cppEnum->typeEntry();
+
+ foreach (const AbstractMetaEnumValue* enumValue, values) {
+ Indentation indent(INDENT);
+ if (ete->isEnumValueRejected(enumValue->name()))
+ continue;
+
+ s << INDENT << ".value(\"" << enumValue->name() << "\", ";
+ s << nameSpace << enumValue->name() << ")" << endl;
+ }
+
+ //Export values to current scope
+ s << INDENT << INDENT << ".export_values()" << endl;
+ s << INDENT << ";" << endl << endl;
+
+ FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags();
+
+ if (flagsEntry) {
+ s << INDENT << "PySide::declare_" << (cppEnum->typeEntry()->forceInteger() ? "int_" : "") << "qflags< "
+ << flagsEntry->originalName() << " >(\"" << flagsEntry->flagsName() << "\");" << endl;
+ }
+
+ //register enum in typemanager
+ s << INDENT
+ << "type_manager::instance().register_native_type<int>(\""
+ << cppEnum->qualifier() << "::" << cppEnum->name() << "\");\n\n";
+}
+
+void CppGenerator::writeEnums(QTextStream &s, const AbstractMetaClass *cppClass, bool useNamespace)
+{
+ AbstractMetaEnumList enums = cppClass->enums();
+ if (!enums.size())
+ return;
+
+ s << INDENT << "// Enums" << endl;
+ QString name_space;
+ if (useNamespace || !cppClass->isPolymorphic() || cppClass->hasPrivateDestructor())
+ name_space = cppClass->qualifiedCppName() + "::";
+
+ foreach (AbstractMetaEnum *cpp_enum, enums)
+ writeEnum(s, cpp_enum, name_space);
+}
+
+void CppGenerator::writeImplicitlyConversion(QTextStream &s, const AbstractMetaClass *cppClass)
+{
+#if 0
+ if (cppClass->isNamespace())
+ return;
+ s << endl << "// Implicitly conversions" << endl;
+ QStringList interfaces = getBaseClasses(cppClass);
+
+ if (!interfaces.size()) {
+ s << INDENT << "python::implicitly_convertible< " << endl;
+ s << INDENT << INDENT << "std::auto_ptr< " << getWrapperName(cppClass->name()) << " >," << endl;
+ s << INDENT << INDENT << "std::auto_ptr< " << cppClass->name() << " > >();" << endl;
+ } else {
+ foreach (QString base_class, interfaces) {
+ s << INDENT << "python::implicitly_convertible< " << endl;
+ s << INDENT << INDENT << "std::auto_ptr< " << cppClass->name() << " >," << endl;
+ s << INDENT << INDENT << "std::auto_ptr< " << base_class << " > >();" << endl;
+ }
+ }
+#endif
+}
+
+
+void CppGenerator::writeDestructor(QTextStream &s, const AbstractMetaClass *cppClass)
+{
+ Indentation indentation(INDENT);
+ QString wrapperName = getWrapperName(cppClass);
+ s << wrapperName << "::~" << wrapperName << "()" << endl << "{" << endl
+ << INDENT << "PySide::qptr_base::invalidate(this);" << endl << "}" << endl;
+}
+
+/*!
+ Function used to write the class generated boost code on the buffer
+ \param s the output buffer
+ \param cppClass the pointer to metaclass information
+*/
+void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *cppClass)
+{
+ ReportHandler::debugSparse("Generating wrapper implementation for " + cppClass->fullName());
+
+ // write license comment
+ s << licenseComment() << endl;
+
+ QString localStr, globalStr;
+ QTextStream includesLocal(&localStr);
+ QTextStream includesGlobal(&globalStr);
+
+ bool canCreateWrapper = canCreateWrapperFor(cppClass);
+
+ QList<Include> includes = cppClass->typeEntry()->extraIncludes();
+ qSort(includes.begin(), includes.end());
+
+ foreach (Include inc, includes) {
+ if (inc.type == Include::IncludePath)
+ includesGlobal << inc.toString() << endl;
+ else
+ includesLocal << inc.toString() << endl;
+ }
+
+ //workaround to access protected functions
+ s << "//workaround to access protected functions" << endl;
+ s << "#define protected public" << endl;
+
+ s << "//Base Class" << endl;
+ if (cppClass->typeEntry()->include().isValid())
+ s << cppClass->typeEntry()->include().toString() << endl << endl;
+
+ s << "//Extra includes [global]" << endl;
+ s << globalStr << endl;
+
+ s << "#undef protected" << endl;
+ s << "//Base include" << endl;
+ s << "#include \"pyside.hpp\"" << endl;
+ s << "#include \"" << getWrapperName(cppClass) << ".hpp\"" << endl;
+ foreach (AbstractMetaClass* innerClass, cppClass->innerClasses()) {
+ if (shouldGenerate(innerClass))
+ s << "#include \"" << getWrapperName(innerClass) << ".hpp\"" << endl;
+ }
+ s << endl << "//Extra includes [local]" << endl;
+ s << localStr << endl;
+
+ s << endl << "using namespace boost;" << endl;
+ s << "using namespace PySide;" << endl;
+ s << endl;
+
+ if (cppClass->typeEntry()->typeFlags() & ComplexTypeEntry::Deprecated)
+ s << "#Deprecated" << endl;
+
+ if (canCreateWrapper) {
+ writePrelude(s, cppClass);
+ if (cppClass->isPolymorphic() && !cppClass->hasPrivateDestructor())
+ writeDestructor(s, cppClass);
+ }
+ writeBoostDeclaration(s, cppClass);
+}
+
+void CppGenerator::writePrelude(QTextStream& s, const AbstractMetaClass* cppClass)
+{
+ //inject code native beginner
+ writeCodeSnips(s, cppClass->typeEntry()->codeSnips(),
+ CodeSnip::Beginning, TypeSystem::NativeCode);
+
+ foreach (AbstractMetaFunction *func, filterFunctions(cppClass)) {
+ if ((func->isPrivate() || func->isModifiedRemoved()) && !func->isAbstract())
+ continue;
+
+ if (func->isConstructor() && (func->allowThread() || func->hasInjectedCode())) {
+ writeModifiedConstructorImpl(s, func);
+ } else if (cppClass->isPolymorphic() && !cppClass->hasPrivateDestructor() &&
+ func->isConstructor() && !func->isCopyConstructor()) {
+ writeConstructorImpl(s, func);
+ } else if (func->isVirtual() || func->isAbstract()) {
+ writeVirtualMethodImpl(s, func);
+ } else if (func->hasInjectedCode() || func->isThread() || func->allowThread()) {
+ writeNonVirtualModifiedFunctionImpl(s, func);
+ } else if (func->isInGlobalScope() && func->isOperatorOverload()) {
+ writeGlobalOperatorOverloadImpl(s, func);
+ }
+ }
+
+ //inject code native end
+ writeCodeSnips(s, cppClass->typeEntry()->codeSnips(),
+ CodeSnip::End, TypeSystem::NativeCode);
+}
+
+
+void CppGenerator::writeModifiedConstructorImpl ( QTextStream& s, const AbstractMetaFunction* func )
+{
+ Indentation indentation(INDENT);
+ const AbstractMetaClass* clazz = func->ownerClass();
+ s << "static " << clazz->name() << "* " << nameForModifiedCtorFunction(func) << '(';
+ writeFunctionArguments(s, func, SkipDefaultValues);
+ s << ")\n{" << endl;
+
+ s << INDENT << clazz->name() << "* _self = 0;" << endl;
+ s << INDENT << '{' << endl;
+ {
+ Indentation indentation(INDENT);
+ if (func->allowThread())
+ s << INDENT << "py_allow_threads allow_threads;" << endl;
+
+ s << INDENT << "_self = new ";
+ writeFunctionCall(s, func);
+ s << ';' << endl;
+ }
+ s << INDENT << '}' << endl;
+ writeCodeSnips(s, getCodeSnips(func), CodeSnip::Beginning, TypeSystem::All, func);
+ writeCodeSnips(s, getCodeSnips(func), CodeSnip::End, TypeSystem::All, func);
+ s << INDENT << "python::object _obj(PySide::ptr(_self));" << endl;
+ s << INDENT << "return _self;" << endl;
+ s << '}' << endl;
+}
+
+void CppGenerator::writeConstructorImpl(QTextStream& s, const AbstractMetaFunction* func)
+{
+ s << functionSignature(func, getWrapperName(func->ownerClass()) + "::", "",
+ (Option)(OriginalTypeDescription | SkipDefaultValues));
+ s << " : ";
+ writeFunctionCall(s, func);
+ s << " {" << endl;
+ writeCodeSnips(s, getCodeSnips(func), CodeSnip::Beginning, TypeSystem::All, func);
+ writeCodeSnips(s, getCodeSnips(func), CodeSnip::End, TypeSystem::All, func);
+ s << '}' << endl << endl;
+}
+
+void CppGenerator::writeVirtualMethodImplHead(QTextStream& s, const AbstractMetaFunction* func)
+{
+ Indentation indentation(INDENT);
+ s << INDENT << "thread_locker lock;" << endl;
+
+ if (func->hasInjectedCode()) {
+ writeCodeSnips(s, getCodeSnips(func),
+ CodeSnip::Beginning, TypeSystem::NativeCode, func);
+ }
+
+ s << INDENT << "python::object method = PySide::detail::get_override(this, \"" << func->implementingClass()->name();
+ if (func->implementingClass()->typeEntry()->isObject() || func->implementingClass()->typeEntry()->isQObject())
+ s << '*';
+
+ s << "\", \"" << func->name() << "\");" << endl
+ << INDENT << "if (method)" << endl << INDENT << "{" << endl;
+
+ {
+ Indentation indentation(INDENT);
+ s << INDENT;
+ if (func->type())
+ s << "python::object __result = ";
+
+ s << "method(";
+ writeArgumentNames(s, func, BoxedPrimitive);
+ s << ");" << endl;
+
+ QString typeName = getFunctionReturnType(func);
+ if (!typeName.isEmpty()) {
+
+ CodeSnipList codeSnips = getCodeSnips(func);
+ bool hasVirtualBeginningCode = false;
+ foreach(CodeSnip cs, codeSnips) {
+ if ((cs.position == CodeSnip::Beginning) && (cs.language == TypeSystem::TargetLangCode)) {
+ hasVirtualBeginningCode = true;
+ break;
+ }
+ }
+
+ if (hasVirtualBeginningCode) {
+ writeCodeSnips(s, codeSnips, CodeSnip::Beginning, TypeSystem::TargetLangCode, func);
+ } else if (func->type()) {
+ s << INDENT << typeName << " __return_value = " << "python::extract<" << typeName << " >(__result);" << endl;
+ bool boxedPointer = false;
+ if (func->type() && !func->type()->isConstant() &&
+ (func->type()->isObject() || func->type()->isQObject())) {
+
+ s << INDENT << "PySide::qptr<" << QString(typeName).replace("*", "") << " > __ptr(__result.ptr());" << endl
+ << INDENT << "if (__ptr.is_wrapper()) {" << endl
+ << INDENT << INDENT << "python::incref(__result.ptr());" << endl
+ << INDENT << "}" << endl
+ << INDENT << "__ptr.release_ownership();" << endl;
+ }
+
+ s << INDENT << "return __return_value;" << endl;
+ }
+ }
+ }
+ s << INDENT << "}" << endl;
+}
+
+void CppGenerator::writeVirtualMethodImpl(QTextStream& s, const AbstractMetaFunction* func)
+{
+ if (func->isModifiedRemoved())
+ return;
+
+ if (!func->isAbstract() && !func->ownerClass()->hasPrivateDestructor() &&
+ func->implementingClass() == func->ownerClass()) {
+ writeVirtualDefaultFunction(s, func);
+ }
+
+
+ QString prefix = getWrapperName(func->ownerClass()) + "::";
+ s << functionSignature(func, prefix, "",
+ Generator::OriginalTypeDescription | Generator::SkipDefaultValues)
+ << endl << "{" << endl;
+
+ writeVirtualMethodImplHead(s, func);
+
+ if (func->isAbstract())
+ writePureVirtualMethodImplFoot(s, func);
+ else
+ writeVirtualMethodImplFoot(s, func);
+
+ s << '}' << endl << endl;
+}
+
+
+void CppGenerator::writePureVirtualMethodImplFoot(QTextStream& s, const AbstractMetaFunction* func)
+{
+ Indentation indentation(INDENT);
+ s << INDENT << "else" << endl
+ << INDENT << "{" << endl;
+ {
+ Indentation indentation(INDENT);
+ s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \""
+ << func->ownerClass()->name() << "." << func->name() << " : "
+ << "You need to implement pure virtual functions in python\");" << endl
+ << INDENT << "throw python::error_already_set();" << endl;
+ }
+ s << INDENT << "}" << endl;
+}
+
+void CppGenerator::writeVirtualMethodImplFoot(QTextStream& s, const AbstractMetaFunction* func)
+{
+ Indentation indentation(INDENT);
+ s << INDENT << "else" << endl << INDENT << "{" << endl;
+ {
+ Indentation indentation(INDENT);
+ QString returnKeyword = func->type() ? QLatin1String("return ") : QString();
+
+ if (func->allowThread())
+ s << INDENT << "py_allow_threads allow_threads;" << endl;
+
+ s << INDENT << returnKeyword << func->implementingClass()->qualifiedCppName() << "::";
+ writeFunctionCall(s, func);
+ s << ';' << endl;
+ }
+ s << INDENT << '}' << endl;
+}
+
+void CppGenerator::writeVirtualDefaultFunction(QTextStream &s, const AbstractMetaFunction *func)
+{
+ Indentation indentation(INDENT);
+ QString returnKeyword = func->type() ? QLatin1String("return ") : QString();
+ QString defaultMethodSignature = signatureForDefaultVirtualMethod(func, getWrapperName(func->ownerClass()) + "::", "_default", Generator::SkipDefaultValues);
+ s << defaultMethodSignature << endl << '{' << endl;
+
+ if (func->allowThread())
+ s << INDENT << "py_allow_threads allow_threads;" << endl;
+
+ CodeSnipList codeSnips = getCodeSnips(func);
+ bool hasVirtualEndCode = false;
+ foreach(CodeSnip cs, codeSnips) {
+ if ((cs.position == CodeSnip::End) && (cs.language == TypeSystem::TargetLangCode)) {
+ hasVirtualEndCode = true;
+ break;
+ }
+ }
+
+ if (!hasVirtualEndCode) {
+ s << INDENT << returnKeyword << "self." << func->implementingClass()->qualifiedCppName() << "::";
+ writeFunctionCall(s, func);
+ s << ";" << endl;
+ } else {
+ writeCodeSnips(s, getCodeSnips(func),
+ CodeSnip::End, TypeSystem::TargetLangCode, func);
+ }
+ s << '}' << endl << endl;
+
+}
+
+
+
+void CppGenerator::writeNonVirtualModifiedFunctionImpl(QTextStream& s, const AbstractMetaFunction* func)
+{
+ Indentation indentation(INDENT);
+
+ s << "static " << getFunctionReturnType(func) << ' ';
+ s << func->ownerClass()->name() << '_' << func->originalName() << "_modified(";
+
+ uint options = SkipRemovedArguments | SkipDefaultValues;
+ if (!func->isStatic())
+ options |= WriteSelf;
+
+ writeFunctionArguments(s, func, options);
+ s << ")" << endl << "{" << endl;
+
+ if (func->isThread())
+ s << INDENT << "thread_locker lock;" << endl;
+
+ if (func->allowThread())
+ s << INDENT << "py_allow_threads allow_threads;" << endl;
+
+ if (getCodeSnips(func).size() > 0) {
+ writeCodeSnips(s, getCodeSnips(func), CodeSnip::Beginning, TypeSystem::All, func);
+ writeCodeSnips(s, getCodeSnips(func), CodeSnip::End, TypeSystem::All, func);
+ } else {
+ s << INDENT;
+ if (func->type())
+ s << "return ";
+
+ if (func->isStatic())
+ s << func->declaringClass()->name() << "::";
+ else
+ s << "self.";
+
+ writeFunctionCall(s, func);
+ s << ";" << endl;
+ }
+
+ s << '}' << endl << endl;
+}
+
+AbstractMetaFunction* CppGenerator::findMainConstructor(const AbstractMetaClass* clazz)
+{
+ foreach (AbstractMetaFunction* func, clazz->functions()) {
+ if (func->isConstructor() &&
+ func->isPublic() &&
+ !func->isModifiedRemoved() &&
+ !func->isPrivate()) {
+ return func;
+ }
+ }
+ return 0;
+}
+
+void CppGenerator::writeHashFunction(QTextStream& s, const AbstractMetaClass* cppClass)
+{
+ QString argType;
+
+ //WORKAROUND: diferent way to QChar
+ if (cppClass->name() == "QChar")
+ argType = "QChar";
+ else
+ argType = "const " + cppClass->name() + "&";
+
+ s << "// Hash function" << endl
+ << "{" << endl
+ << INDENT << INDENT << "typedef uint (*hash_type) ( " << argType << " );"
+ << INDENT << INDENT << "python_cls.def(\"__hash__\", hash_type(&"
+ << cppClass->typeEntry()->hashFunction() << "));" << endl
+ << "}" << endl;
+}
+
+QString CppGenerator::baseClassName(const QString& name)
+{
+ QStringList lst = name.split("::");
+ return lst.last();
+}
+
+void CppGenerator::writeBoostDeclaration(QTextStream& s, const AbstractMetaClass* cppClass)
+{
+ Indentation indent(INDENT);
+ QString wrapperName = getWrapperName(cppClass);
+
+ s << "void " << wrapperName << "::define_python_class() throw() {" << endl;
+
+ const AbstractMetaFunction* mainCtor = 0;
+ bool mainCtorHasModifications = false;
+ if (!cppClass->isNamespace()) {
+ // python_cls declaration
+ mainCtor = findMainConstructor(cppClass);
+ if (mainCtor)
+ mainCtorHasModifications = mainCtor->allowThread() || mainCtor->hasInjectedCode();
+
+ s << INDENT;
+ if (!cppClass->isPolymorphic() || cppClass->hasPrivateDestructor())
+ s << wrapperName << "::";
+
+ s << "class_type python_cls(\""
+ << baseClassName(cppClass->name()) << "\", ";
+
+ if (!mainCtor || mainCtorHasModifications)
+ s << "python::no_init";
+ else
+ writeConstructorInitialization(s, mainCtor);
+
+ s << ");" << endl << endl;
+ } else {
+ QRegExp reg("(?:\\w+::)*(\\w+)");
+ reg.indexIn(cppClass->name());
+ s << INDENT << "python::class_<Namespace> python_cls(\"" << reg.cap(1) << "\");" << endl;
+ }
+ // scope declaration
+ s << INDENT << "python::scope " << wrapperName << "_scope(python_cls);" << endl;
+
+ if (cppClass->templateBaseClass() && cppClass->templateBaseClass()->typeEntry()->isContainer()) {
+ //const ContainerTypeEntry *type = static_cast<const ContainerTypeEntry*>(cppClass->templateBaseClass()->typeEntry());
+ //if (type->type() == ContainerTypeEntry::ListContainer) {
+ s << endl << INDENT << "//Index suite for QContainer" << endl
+ << INDENT << "python_cls.def(qcontainer_indexing_suite< " << cppClass->qualifiedCppName() << " >());" << endl << endl;
+ //}
+ }
+
+ if (isCopyable(cppClass) && !cppClass->isNamespace()) {
+ s << INDENT << "python_cls.def(python::init<const ";
+ s << cppClass->qualifiedCppName() << "&>());" << endl;
+ }
+
+ if (cppClass->isPolymorphic() && !cppClass->hasPrivateDestructor() && canCreateWrapperFor(cppClass)) {
+ QString heldType = cppClass->typeEntry()->heldTypeValue();
+ if (heldType.isEmpty())
+ heldType = "PySide::qptr";
+
+ s << INDENT << "python::implicitly_convertible< "
+ << heldType << "<" << wrapperName << ">, "
+ << heldType << "<" << cppClass->qualifiedCppName() << "> >();" << endl;
+ }
+
+ //Enums
+ writeEnums(s, cppClass, cppClass->hasPrivateDestructor() || cppClass->isNamespace());
+
+ if (cppClass->innerClasses().count()) {
+ s << endl << INDENT << "// Inner classes" << endl;
+ foreach (AbstractMetaClass* innerClass, cppClass->innerClasses()) {
+ if (!innerClass->typeEntry()->generateCode())
+ continue;
+ s << INDENT << getWrapperName(innerClass) << "::define_python_class();" << endl;
+ }
+ }
+
+ //Fields
+ foreach (AbstractMetaField *field, cppClass->fields()) {
+ QString strAccess;
+
+ if (field->isPublic()) {
+ if (field->type()->isConstant())
+ strAccess = "def_readonly";
+ else
+ strAccess = "def_readwrite";
+
+ s << INDENT << "python_cls."
+ << strAccess
+ << "(\"" << field->name() << "\", &"
+ << field->enclosingClass()->name() << "::" << field->name() << ");" << endl;
+ }
+ }
+
+ writeCodeSnips(s, cppClass->typeEntry()->codeSnips(),
+ CodeSnip::Beginning, TypeSystem::TargetLangCode);
+
+ QSet<QString> staticMethods;
+
+ if (!cppClass->isNamespace()) {
+ //search for all static methods to match with normal functions
+ //to rename when match with one member function
+ foreach (AbstractMetaFunction *func, filterFunctions(cppClass)) {
+ if (func->isStatic() && !func->isOperatorOverload())
+ staticMethods << func->name();
+ }
+ }
+
+ foreach (AbstractMetaFunction *func, filterFunctions(cppClass)) {
+ if (func->isModifiedRemoved() || func->isPrivate() || func->isSignal())
+ continue;
+
+ //rename static function when is the same name as member function
+ if (!cppClass->isNamespace() && func->isStatic()) {
+ QString staticName(createStaticFunctionName(func));
+ QSet<QString>::iterator staticFuncInter = staticMethods.find(staticName);
+ if (staticFuncInter != staticMethods.end())
+ func->setName(staticName);
+ } else {
+ QSet<QString>::iterator staticFuncInter = staticMethods.find(func->name());
+ if (staticFuncInter != staticMethods.end()) {
+ staticMethods.erase(staticFuncInter);
+ staticMethods << createStaticFunctionName(func);
+ }
+ }
+
+ if (func->isOperatorOverload()) {
+ // Do not join the ifs -- isOperatorOverload must be checked alone
+ if (func->originalName() == func->name())
+ writeOperatorOverload(s, func);
+ } else if (func->isConstructor()) {
+ if (mainCtorHasModifications || func != mainCtor)
+ writeConstructor(s, func);
+ } else if (!func->isVirtual() &&
+ (func->hasInjectedCode() ||
+ func->isThread() || func->allowThread())) {
+ writeModifiedMethodDef(s, func);
+ } else if (func->implementingClass() == func->ownerClass()) {
+ writeNormalMethodDef(s, func);
+ }
+
+ //if is namespace all methothds is stattic
+ if (cppClass->isNamespace())
+ s << INDENT << "python_cls.staticmethod(\"" << func->name() << "\");" << endl;
+ }
+
+ writeCodeSnips(s, cppClass->typeEntry()->codeSnips(),
+ CodeSnip::End, TypeSystem::TargetLangCode);
+
+ if (!cppClass->isNamespace()) {
+ // Static methods
+ if (!staticMethods.isEmpty())
+ s << INDENT << "// Static methods" << endl;
+
+ foreach (QString funcName, staticMethods)
+ s << INDENT << "python_cls.staticmethod(\"" << funcName << "\");" << endl;
+ }
+
+ // qHash usage
+ if (!cppClass->typeEntry()->hashFunction().isEmpty())
+ writeHashFunction(s, cppClass);
+
+ // implicity conversions
+ writeImplicitlyConversion(s, cppClass);
+
+ // register object/value type
+ if (!cppClass->isNamespace()) {
+ QString className = cppClass->qualifiedCppName();
+ const char* funcName = (cppClass->typeEntry()->isObject() || !isCopyable(cppClass)) ? "object" : "value";
+ s << INDENT
+ << "type_manager::instance().register_"
+ << funcName
+ << "_type<" << className << " >(\""
+ << cppClass->qualifiedCppName() << (cppClass->typeEntry()->isObject() ? "*" : "") << "\");\n";
+ }
+ s << '}' << endl;
+}
+
+void CppGenerator::writeConstructor(QTextStream& s, const AbstractMetaFunction* func)
+{
+ s << INDENT << "python_cls.def(";
+ writeConstructorInitialization(s, func);
+ s << ");" << endl;
+}
+
+void CppGenerator::writeFunctionArgsDef(QTextStream &sOut,
+ const AbstractMetaFunction *cppFunction)
+{
+ bool hasDefaultValue = false;
+ int argUsed = 0;
+ QString aux;
+ QTextStream s(&aux);
+
+ foreach (const AbstractMetaArgument *arg, cppFunction->arguments()) {
+ if (cppFunction->argumentRemoved(arg->argumentIndex() + 1))
+ continue;
+
+ if (argUsed > 0)
+ s << ", ";
+
+ if (!m_disableNamedArgs)
+ s << "python::arg(\"" << arg->argumentName() << "\")";
+ else
+ s << "python::arg(0)";
+
+ if (!arg->defaultValueExpression().isEmpty()) {
+ QString defaultValue = arg->defaultValueExpression();
+ bool isPointer = arg->type()->isObject() ||
+ arg->type()->isQObject() ||
+ arg->type()->isNativePointer();
+
+ if (isPointer && defaultValue == "0") {
+ defaultValue = "python::object()";
+ } else if (arg->type()->isFlags()) {
+ defaultValue = " (int) " + defaultValue;
+ } else if (arg->type()->isEnum()) {
+ QString enumName = arg->type()->minimalSignature();
+ QRegExp reg("(.*::)");
+ reg.indexIn(enumName);
+ if (!defaultValue.startsWith(reg.cap(1)))
+ defaultValue = reg.cap(1) + defaultValue;
+ }
+
+ s << "=" << defaultValue;
+ hasDefaultValue = true;
+ }
+ argUsed++;
+ }
+
+ if (hasDefaultValue || ((argUsed > 0) && !m_disableNamedArgs))
+ sOut << "," << endl << INDENT << INDENT << "(" << aux << ")";
+}
+
+void CppGenerator::writeNormalMethodDef(QTextStream& s, const AbstractMetaFunction* func)
+{
+ s << INDENT << '{' << endl;
+ {
+ Indentation indentation(INDENT);
+ QString wrapperClassName = getWrapperName(func->ownerClass());
+ bool needDefaultFunction = func->isVirtual() && !func->isAbstract() && !func->ownerClass()->hasPrivateDestructor();
+ QString castName;
+
+ if (needDefaultFunction)
+ castName = writeFunctionCast(s, func, "_default", func->implementingClass()->qualifiedCppName());
+ else
+ castName = writeFunctionCast(s, func);
+
+ s << INDENT << "python_cls.def(\"" << func->name() << "\", ";
+
+ if (needDefaultFunction) { // add the default function
+ s << castName << "(&" << wrapperClassName << "::" << func->originalName() << "_default)";
+ } else {
+ if (func->isAbstract())
+ s << "python::pure_virtual";
+ s << '(' << castName << '(' << getMethodPointerString(func) << "))";
+ }
+
+ QString functionPolicy = getFunctionCallPolicy(func);
+ if (!functionPolicy.isEmpty())
+ s << ", " << functionPolicy;
+
+ writeFunctionArgsDef(s, func);
+ s << ");" << endl;
+ }
+ s << INDENT << '}' << endl;
+}
+
+void CppGenerator::writeModifiedMethodDef(QTextStream& s, const AbstractMetaFunction* func)
+{
+ s << INDENT << '{' << endl;
+ {
+ Indentation indentation(INDENT);
+ QString castName = writeFunctionCast(s, func);
+ s << INDENT
+ << "python_cls.def(\""
+ << func->name() << "\", "
+ << castName
+ << "(&" << func->implementingClass()->name()
+ << "_" << func->originalName()
+ << "_modified)";
+ QString functionPolicy = getFunctionCallPolicy(func);
+ if (!functionPolicy.isEmpty())
+ s << ", " << functionPolicy;
+
+ writeFunctionArgsDef(s, func);
+ s << ");" << endl;
+ }
+ s << INDENT << '}' << endl;
+}
+
+QString CppGenerator::operatorFunctionName(const AbstractMetaFunction *cppFunction)
+{
+ QString funcName = QString("%1_operator_%2_")
+ .arg(cppFunction->arguments()[0]->type()->name())
+ .arg(cppFunction->arguments()[1]->type()->name());
+
+ if (cppFunction->name().contains(">>")) {
+ funcName += "rshift";
+ } else if (cppFunction->name().contains("<<")) {
+ funcName += "lshift";
+ } else {
+ //TODO: implemente support to others operators
+ return QString();
+ }
+
+ return funcName;
+}
+
+void CppGenerator::writeGlobalOperatorOverloadImpl(QTextStream& s, const AbstractMetaFunction* cppFunction)
+{
+ Indentation indent(INDENT);
+ QString operatorStr;
+
+ if (cppFunction->name().contains(">>")) {
+ operatorStr = " >> ";
+ } else if (cppFunction->name().contains("<<")) {
+ operatorStr = " << ";
+ } else {
+ //TODO: implemente support to others operators
+ return;
+ }
+
+ QString funcName = operatorFunctionName(cppFunction);
+ bool reverse = cppFunction->isReverseOperator();
+
+ const AbstractMetaClass *klass = cppFunction->ownerClass();
+ s << "python::object " << funcName << "(";
+ writeFunctionArguments(s, cppFunction, SkipDefaultValues | SkipRemovedArguments);
+ s << ")" << endl << "{" << endl
+ << INDENT << cppFunction->arguments()[reverse]->argumentName()
+ << operatorStr << cppFunction->arguments()[!reverse]->argumentName() << ";" << endl
+ << INDENT << "return python::object(PySide::ptr(&"
+ << cppFunction->arguments()[reverse]->argumentName() << "));" << endl
+ << "}" << endl;
+}
+
+void CppGenerator::writeGlobalOperatorOverload(QTextStream &s, const AbstractMetaFunction *cppFunction)
+{
+ QString funcName = operatorFunctionName(cppFunction);
+ if (funcName.isEmpty())
+ return;
+
+ bool reverse = cppFunction->isReverseOperator();
+ QString operatorStr;
+ if (cppFunction->name().contains(">>")) {
+ operatorStr = QString("__%1rshift__").arg(reverse ? "r" : "");
+ } else if (cppFunction->name().contains("<<")) {
+ operatorStr = QString("__%1lshift__").arg(reverse ? "r" : "");
+ } else {
+ //TODO: implemente support to others operators
+ return;
+ }
+
+ s << INDENT << "python_cls.def(\"" << operatorStr << "\", " << funcName << ");\n";
+}
+
+QString CppGenerator::getOperatorArgumentTypeName(const AbstractMetaFunction *cppFunction, int argumentIndex)
+{
+ AbstractMetaType* type = cppFunction->arguments()[argumentIndex]->type();
+ if (type->name() == cppFunction->implementingClass()->name())
+ return QLatin1String("python::self");
+
+ QString typeName = translateType(type, cppFunction->implementingClass(),
+ (Option)(ExcludeReference));
+ return type->isPrimitive() ? "(" + typeName + ")(0)" : "python::other<" + typeName + " >()";
+}
+
+void CppGenerator::writeOperatorOverload(QTextStream& s, const AbstractMetaFunction* cppFunction)
+{
+ static QRegExp operatorRegex("operator(.+)");
+
+ if (!operatorRegex.exactMatch(cppFunction->originalName())) {
+ qWarning("What kind of operator is that!? %s",
+ cppFunction->originalName().toLocal8Bit().data());
+ return;
+ }
+
+ QString op(operatorRegex.cap(1));
+ if (op == "=" || op == "[]") {
+ // = is handled by type boost and type conversions, [] by someone...
+ return;
+ }
+
+ // no args == member unary operator
+ if (!cppFunction->arguments().count()) {
+ // check if it is a name instead of an operator symbol
+ // this means it is a conversion operator that will be ignored for now
+ static QRegExp ConversionOperatorRegex("[A-Za-z]+");
+ if (ConversionOperatorRegex.indexIn(op) < 0)
+ s << INDENT << "python_cls.def(" << op << "python::self);" << endl;
+ return;
+ }
+
+ //this because global operators use first arg with current class
+ if (cppFunction->isInGlobalScope()) {
+ writeGlobalOperatorOverload(s, cppFunction);
+ return;
+ }
+
+ QString operand1, operand2;
+ if (cppFunction->arguments().count() == 1) {
+ operand1 = "python::self";
+ operand2 = getOperatorArgumentTypeName(cppFunction, 0);
+ } else {
+ operand1 = getOperatorArgumentTypeName(cppFunction, 0);
+ operand2 = getOperatorArgumentTypeName(cppFunction, 1);
+ }
+ s << INDENT << "python_cls.def(" << operand1 << ' ' << op << ' ' << operand2 << ");\n";
+}
+
+void CppGenerator::finishGeneration()
+{
+ //Generate boost wrapper file
+ QString classFiles;
+ QTextStream sClassFiles(&classFiles);
+ QString classPythonDefines;
+ QTextStream sClassPythonDefines(&classPythonDefines);
+
+ Indentation indent(INDENT);
+
+ foreach (AbstractMetaClass *cls, classes()) {
+ if (!shouldGenerate(cls) || cls->enclosingClass())
+ continue;
+
+ if (m_packageName.isEmpty())
+ m_packageName = cls->package();
+
+ QString wrapperName = getWrapperName(cls);
+ QString boostFilename;
+ boostFilename += wrapperName + ".hpp";
+ sClassFiles << "#include \"" << boostFilename << "\"" << endl;
+
+ QString define_str = wrapperName + "::";
+ define_str += "define_python_class();";
+
+ sClassPythonDefines << INDENT << define_str << endl;
+ }
+
+ QString moduleFileName(outputDirectory() + "/" + subDirectoryForPackage(m_packageName));
+ moduleFileName += "/" + moduleName().toLower() + "_module_wrapper.cpp";
+
+ QFile file(moduleFileName);
+ if (file.open(QFile::WriteOnly)) {
+ QTextStream s(&file);
+
+ // write license comment
+ s << licenseComment() << endl;
+
+ s << "#include \"converter_register_" << moduleName().toLower();
+ s << ".hpp\"" << endl << endl;
+
+ s << classFiles << endl;
+
+ s << "using namespace boost;" << endl << endl;
+ s << "using namespace PySide;" << endl << endl;
+
+ s << "// forward decl. for global func. register\n";
+ s << "void register_global_functions_" << moduleName().toLower() << "();\n\n";
+
+ s << "BOOST_PYTHON_MODULE(" << moduleName() << ")" << endl;
+ s << "{" << endl;
+
+ foreach (QString requiredModule, TypeDatabase::instance()->requiredTargetImports()) {
+ s << INDENT << "if (";
+ s << "PyImport_ImportModule(\"" << requiredModule << "\") == NULL) {" << endl;
+ s << INDENT << INDENT << "PyErr_SetString(PyExc_ImportError,";
+ s << "\"could not import " << requiredModule << "\");" << endl;
+ s << INDENT << INDENT << "return;" << endl;
+ s << INDENT << "}" << endl;
+ }
+ s << endl;
+
+ s << INDENT << "register_type_converters_" << moduleName().toLower() << "();" << endl << endl
+ << classPythonDefines << endl
+ << INDENT << "register_global_functions_" << moduleName().toLower() << "();" << endl
+ << INDENT << "//Namespaces" << endl;
+
+
+ s << "}" << endl << endl;
+ }
+
+ writeGlobalFunctions();
+}
+
+void CppGenerator::writeGlobalFunctions()
+{
+ QString fileName = moduleName().toLower() + "_globals_wrapper.cpp";
+
+ FileOut fileOut(outputDirectory() + "/" + subDirectoryForPackage(m_packageName) + "/" + fileName);
+
+ QSet<QString> includes;
+ QString defsStr;
+ QTextStream defsStream(&defsStr);
+
+ foreach (AbstractMetaFunction* func, globalFunctions()) {
+ QString incFile = func->includeFile();
+ QRegExp regex("\\b" + moduleName() + "\\b");
+ //FIXME: this regex doesn't work with all cases, e.g.:
+ // moduleName() = local
+ // incFile = /usr/local/include/local
+ if (regex.indexIn(incFile) == -1)
+ continue;
+
+ int idx = incFile.indexOf(moduleName());
+ QString cleanPath = QDir::cleanPath(incFile.mid(idx));
+ if (!cleanPath.startsWith(moduleName()))
+ continue;
+
+ includes << cleanPath;
+ defsStream << INDENT << "{\n" << INDENT;
+ QString castName = writeFunctionCast(defsStream, func);
+ defsStream << INDENT << INDENT << "python::def(\"" << func->name();
+ defsStream << "\", " << castName << '(' << func->name() << ')';
+ if (func->type() && func->type()->isReference())
+ defsStream << ", python::return_internal_reference<>()";
+ defsStream << ");\n";
+ defsStream << INDENT << "}\n";
+ }
+
+ QTextStream& s = fileOut.stream;
+
+ // write license comment
+ s << licenseComment() << endl;
+
+ s << "#include \"pyside.hpp\"" << endl;
+
+ foreach (QString include, includes)
+ s << "#include <" << include << ">\n";
+
+ s << "using namespace boost;\n\n";
+ s << "using namespace PySide;\n\n";
+
+ // Add module level code snippets to 'Global' class
+ TypeSystemTypeEntry *moduleEntry = dynamic_cast<TypeSystemTypeEntry *>(
+ TypeDatabase::instance()->findType(m_packageName));
+ QString sEnd;
+ QTextStream snipEnd(&sEnd);
+ if (moduleEntry && moduleEntry->codeSnips().size() > 0) {
+ foreach (CodeSnip snip, moduleEntry->codeSnips()) {
+ if (snip.position == CodeSnip().Beginning)
+ snip.formattedCode(s, INDENT);
+ else
+ snip.formattedCode(snipEnd, INDENT);
+ }
+ }
+
+ s << "\nvoid register_global_functions_" << moduleName().toLower() << "() {\n";
+ { //global enums
+ QString name_space;
+
+ foreach (AbstractMetaEnum *cppEnum, globalEnums()) {
+ if (cppEnum)
+ writeEnum(s, cppEnum, name_space);
+ }
+ }
+ s << sEnd;
+ s << defsStr;
+ s << "}\n";
+}
+
diff --git a/cppgenerator.h b/cppgenerator.h
new file mode 100644
index 0000000..03d3743
--- /dev/null
+++ b/cppgenerator.h
@@ -0,0 +1,102 @@
+/*
+ * This file is part of the Boost Python Generator project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef CPPGENERATOR_H
+#define CPPGENERATOR_H
+
+#include "boostpythongenerator.h"
+
+/**
+* The CppGenerator generate the implementation of boost::python bindings classes.
+*/
+class CppGenerator : public BoostPythonGenerator
+{
+public:
+ void setDisableNamedArgs(bool disable)
+ {
+ m_disableNamedArgs = disable;
+ }
+
+ const char* name() const
+ {
+ return "CppGenerator";
+ }
+
+protected:
+ QString fileNameForClass(const AbstractMetaClass *cppClass) const;
+ void generateClass(QTextStream &s, const AbstractMetaClass *cppClass);
+ void finishGeneration();
+
+private:
+ void writePrelude(QTextStream &s, const AbstractMetaClass *cppClass);
+ void writeBoostDeclaration(QTextStream &s, const AbstractMetaClass *cppClass);
+
+ // method declaration writers
+ void writeConstructor(QTextStream &s, const AbstractMetaFunction *func);
+ void writeConstructorInitialization(QTextStream &s, const AbstractMetaFunction *func);
+ void writeNormalMethodDef(QTextStream &s, const AbstractMetaFunction *func);
+ void writeModifiedMethodDef(QTextStream &s, const AbstractMetaFunction *func);
+ void writeOperatorOverload(QTextStream &s, const AbstractMetaFunction *func);
+ void writeGlobalOperatorOverload(QTextStream &s, const AbstractMetaFunction *func);
+ void writeFunctionArgsDef(QTextStream &s_out, const AbstractMetaFunction *func);
+ void writeGlobalFunctions();
+ void writeDestructor(QTextStream &s, const AbstractMetaClass *cppClass);
+
+ // method implementation writers
+ void writeModifiedConstructorImpl(QTextStream &s, const AbstractMetaFunction *func);
+ void writeConstructorImpl(QTextStream &s, const AbstractMetaFunction *func);
+ void writeVirtualMethodImpl(QTextStream &s, const AbstractMetaFunction *func);
+ void writeVirtualMethodImplHead(QTextStream &s, const AbstractMetaFunction *func);
+ void writeVirtualMethodImplFoot(QTextStream &s, const AbstractMetaFunction *func);
+ void writePureVirtualMethodImplFoot(QTextStream &s, const AbstractMetaFunction *func);
+ void writeNonVirtualModifiedFunctionImpl(QTextStream &s, const AbstractMetaFunction *func);
+ void writeGlobalOperatorOverloadImpl(QTextStream& s, const AbstractMetaFunction* func);
+
+ // helper functions
+ QString writeFunctionCast(QTextStream& s, const AbstractMetaFunction* func, const QString& castNameSuffix = QString(), const QString& className = QString());
+ QString getFuncTypedefName(const AbstractMetaFunction *func) const;
+ QString getFunctionReturnType(const AbstractMetaFunction *func);
+ AbstractMetaFunction* findMainConstructor(const AbstractMetaClass *clazz);
+ QString getArgumentType(const AbstractMetaClass *cppClass, const AbstractMetaFunction *func, int idx);
+ QString operatorFunctionName(const AbstractMetaFunction *func);
+ QString getOperatorArgumentTypeName(const AbstractMetaFunction *func, int argumentIndex);
+
+ // call policy related
+ QString verifyDefaultReturnPolicy(const AbstractMetaFunction *func, const QString &callPolicy);
+ QString getFunctionCallPolicy(const AbstractMetaFunction *func);
+
+ // enum related
+ void writeEnums(QTextStream &s, const AbstractMetaClass *cppClass, bool useNamespace);
+ void writeEnum(QTextStream &s, const AbstractMetaEnum *cppEnum, const QString &nameSpace);
+ // write implicitly conversions
+ void writeImplicitlyConversion(QTextStream &s, const AbstractMetaClass *cppClass);
+ void writeVirtualDefaultFunction(QTextStream &s, const AbstractMetaFunction *arg2);
+
+ void writeHashFunction(QTextStream &s, const AbstractMetaClass *cppClass);
+ QString baseClassName(const QString &name);
+
+ bool m_disableNamedArgs;
+};
+
+#endif // CPPGENERATOR_H
+
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..f9fe2f0
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,88 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ -rm -rf _build/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
+ @echo
+ @echo "Build finished. The HTML pages are in _build/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) _build/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in _build/dirhtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in _build/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) _build/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in _build/qthelp, like this:"
+ @echo "# qcollectiongenerator _build/qthelp/BoostPythonGenerator.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile _build/qthelp/BoostPythonGenerator.qhc"
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in _build/latex."
+ @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+ "run these through (pdf)latex."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes
+ @echo
+ @echo "The overview file is in _build/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in _build/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in _build/doctest/output.txt."
diff --git a/doc/_static/basic.css b/doc/_static/basic.css
new file mode 100644
index 0000000..2509c22
--- /dev/null
+++ b/doc/_static/basic.css
@@ -0,0 +1,417 @@
+/**
+ * Sphinx stylesheet -- basic theme
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+/* -- main layout ----------------------------------------------------------- */
+
+div.documentwrapper {
+ float: left;
+ width: 100%;
+}
+
+div.bodywrapper {
+ margin: 0 0 0 230px;
+}
+
+div.clearer {
+ clear: both;
+}
+
+/* -- relbar ---------------------------------------------------------------- */
+
+div.related {
+ width: 100%;
+ font-size: 90%;
+}
+
+div.related h3 {
+ display: none;
+}
+
+div.related ul {
+ margin: 0;
+ padding: 0 0 0 0px;
+ list-style: none;
+}
+
+div.related li {
+ float: left;
+ display: inline;
+ padding-right:17px;
+ padding-left:10px;
+ background-image:url(images/bread_crumb.png);
+ background-position:right;
+ background-repeat:no-repeat;
+}
+
+div.related li.right {
+ float: right;
+ margin-right: 5px;
+ padding: 0 0 0 0px;
+ background-image:none;
+}
+
+/* -- sidebar --------------------------------------------------------------- */
+
+div.sphinxsidebarwrapper {
+ padding: 10px 5px 0 10px;
+}
+
+div.sphinxsidebar {
+ float: left;
+ width: 230px;
+ margin-left: -100%;
+ font-size: 90%;
+}
+
+div.sphinxsidebar ul {
+ list-style: none;
+}
+
+div.sphinxsidebar ul ul,
+div.sphinxsidebar ul.want-points {
+ margin-left: 20px;
+ list-style: square;
+}
+
+div.sphinxsidebar ul ul {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+div.sphinxsidebar form {
+ margin-top: 10px;
+}
+
+img {
+ border: 0;
+}
+
+/* -- search page ----------------------------------------------------------- */
+
+ul.search {
+ margin: 10px 0 0 20px;
+ padding: 0;
+}
+
+ul.search li {
+ padding: 5px 0 5px 20px;
+ background-image: url(file.png);
+ background-repeat: no-repeat;
+ background-position: 0 7px;
+}
+
+ul.search li a {
+ font-weight: bold;
+}
+
+ul.search li div.context {
+ color: #888;
+ margin: 2px 0 0 30px;
+ text-align: left;
+}
+
+ul.keywordmatches li.goodmatch a {
+ font-weight: bold;
+}
+
+/* -- index page ------------------------------------------------------------ */
+
+table.contentstable {
+ text-align: left;
+ width: 90%;
+}
+
+table.contentstable p.biglink {
+ line-height: 150%;
+}
+
+a.biglink {
+ font-size: 1.3em;
+}
+
+span.linkdescr {
+ text-align: left;
+ padding-top: 5px;
+ font-size: 90%;
+}
+
+/* -- general index --------------------------------------------------------- */
+
+table.indextable td {
+ text-align: left;
+ vertical-align: top;
+}
+
+table.indextable dl, table.indextable dd {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+table.indextable tr.pcap {
+ height: 10px;
+}
+
+table.indextable tr.cap {
+ margin-top: 10px;
+ background-color: #f2f2f2;
+}
+
+img.toggler {
+ margin-right: 3px;
+ margin-top: 3px;
+ cursor: pointer;
+}
+
+/* -- general body styles --------------------------------------------------- */
+
+a.headerlink {
+ visibility: hidden;
+}
+
+h1:hover > a.headerlink,
+h2:hover > a.headerlink,
+h3:hover > a.headerlink,
+h4:hover > a.headerlink,
+h5:hover > a.headerlink,
+h6:hover > a.headerlink,
+dt:hover > a.headerlink {
+ visibility: visible;
+}
+
+div.body p.caption {
+ text-align: inherit;
+}
+
+div.body td {
+ text-align: left;
+}
+
+.field-list ul {
+ padding-left: 1em;
+}
+
+.first {
+ margin-top: 0 !important;
+}
+
+p.rubric {
+ margin-top: 30px;
+ font-weight: bold;
+}
+
+/* -- sidebars -------------------------------------------------------------- */
+
+div.sidebar {
+ margin: 0 0 0.5em 1em;
+ border: 1px solid #ddb;
+ padding: 7px 7px 0 7px;
+ background-color: #ffe;
+ width: 40%;
+ float: right;
+}
+
+p.sidebar-title {
+ font-weight: bold;
+}
+
+/* -- topics ---------------------------------------------------------------- */
+
+div.topic {
+ border: 1px solid #ccc;
+ padding: 7px 7px 0 7px;
+ margin: 10px 0 10px 0;
+}
+
+p.topic-title {
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 10px;
+}
+
+/* -- admonitions ----------------------------------------------------------- */
+
+div.admonition {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding: 7px;
+}
+
+div.admonition dt {
+ font-weight: bold;
+}
+
+div.admonition dl {
+ margin-bottom: 0;
+}
+
+p.admonition-title {
+ margin: 0px 10px 5px 0px;
+ font-weight: bold;
+}
+
+div.body p.centered {
+ text-align: center;
+ margin-top: 25px;
+}
+
+/* -- tables ---------------------------------------------------------------- */
+
+table.docutils {
+ border: 0;
+ border-collapse: collapse;
+}
+
+table.docutils td, table.docutils th {
+ padding: 2px 8px 2px 8px;
+ border-top: 0;
+ border-left: 0;
+ border-right: 0;
+ border-bottom: 1px solid #aaa;
+}
+
+table.field-list td, table.field-list th {
+ border: 0 !important;
+}
+
+table.footnote td, table.footnote th {
+ border: 0 !important;
+}
+
+th {
+ text-align: left;
+ padding-right: 5px;
+}
+
+/* -- other body styles ----------------------------------------------------- */
+
+dl {
+ margin-bottom: 15px;
+}
+
+dd p {
+ margin-top: 0px;
+}
+
+dd ul, dd table {
+ margin-bottom: 10px;
+}
+
+dd {
+ margin-top: 3px;
+ margin-bottom: 10px;
+ margin-left: 30px;
+}
+
+dt:target, .highlight {
+ background-color: #fbe54e;
+}
+
+dl.glossary dt {
+ font-weight: bold;
+ font-size: 1.1em;
+}
+
+.field-list ul {
+ margin: 0;
+ padding-left: 1em;
+}
+
+.field-list p {
+ margin: 0;
+}
+
+.refcount {
+ color: #060;
+}
+
+.optional {
+ font-size: 1.3em;
+}
+
+.versionmodified {
+ font-style: italic;
+}
+
+.system-message {
+ background-color: #fda;
+ padding: 5px;
+ border: 3px solid red;
+}
+
+.footnote:target {
+ background-color: #ffa
+}
+
+/* -- code displays --------------------------------------------------------- */
+
+pre {
+ overflow: auto;
+}
+
+td.linenos pre {
+ padding: 5px 0px;
+ border: 0;
+ background-color: transparent;
+ color: #aaa;
+}
+
+table.highlighttable {
+ margin-left: 0.5em;
+}
+
+table.highlighttable td {
+ padding: 0 0.5em 0 0.5em;
+}
+
+tt.descname {
+ background-color: transparent;
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+tt.descclassname {
+ background-color: transparent;
+}
+
+tt.xref, a tt {
+ background-color: transparent;
+ font-weight: bold;
+}
+
+h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
+ background-color: transparent;
+}
+
+/* -- math display ---------------------------------------------------------- */
+
+img.math {
+ vertical-align: middle;
+}
+
+div.math p {
+ text-align: center;
+}
+
+span.eqno {
+ float: right;
+}
+
+/* -- printout stylesheet --------------------------------------------------- */
+
+@media print {
+ div.document,
+ div.documentwrapper,
+ div.bodywrapper {
+ margin: 0;
+ width: 100%;
+ }
+
+ div.sphinxsidebar,
+ div.related,
+ div.footer,
+ #top-link {
+ display: none;
+ }
+}
diff --git a/doc/_static/bindingexample.tar.bz2 b/doc/_static/bindingexample.tar.bz2
new file mode 100644
index 0000000..bf1fdea
--- /dev/null
+++ b/doc/_static/bindingexample.tar.bz2
Binary files differ
diff --git a/doc/_static/default.css b/doc/_static/default.css
new file mode 100644
index 0000000..721ceb7
--- /dev/null
+++ b/doc/_static/default.css
@@ -0,0 +1,248 @@
+/**
+ * Sphinx stylesheet -- default theme
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+@import url("basic.css");
+
+/* -- page layout ----------------------------------------------------------- */
+
+body {
+ font-family: sans-serif;
+ font-size: 100%;
+ background-color: #000000;
+ color: #000;
+ margin: 0;
+ padding: 0;
+}
+
+div.document {
+ background-image:url(images/side_background.jpg);
+ background-repeat:repeat-y;
+ background-color:#ffd800;
+}
+
+div.body {
+ position:relative;
+ background-color:#fff;
+ color: #000000;
+ padding: 0 20px 30px 20px;
+}
+
+div.footer {
+ color: #ffffff;
+ width: 100%;
+ padding: 9px 0 9px 0;
+ text-align: center;
+ font-size: 75%;
+}
+
+div.footer a {
+ color: #ffffff;
+ text-decoration: underline;
+}
+
+div.related {
+ background-image:url(images/top_background.jpg);
+ background-repeat:repeat-x;
+ background-color: #d7aa00;
+ line-height:33px;
+ height:33px;
+ color: #000000;
+}
+
+div.related a {
+ color: #000000;
+}
+
+div.related img {
+ padding-top:3px;
+}
+
+div.sphinxsidebar {
+}
+
+div.sphinxsidebar h3 {
+ font-family: Arial, Verdana, sans-serif;
+ color: #000000;
+ font-size: 1.4em;
+ font-weight: normal;
+ margin: 0;
+ padding: 0;
+}
+
+div.sphinxsidebar h3 a {
+ color: #000000;
+}
+
+div.sphinxsidebar h4 {
+ font-family: Arial, Verdana, sans-serif;
+ color: #000000;
+ font-size: 1.3em;
+ font-weight: normal;
+ margin: 5px 0 0 0;
+ padding: 0;
+}
+
+div.sphinxsidebar p {
+ color: #ffffff;
+}
+
+div.sphinxsidebar p.topless {
+ margin: 5px 10px 10px 10px;
+}
+
+div.sphinxsidebar ul {
+ margin: 10px;
+ padding: 0;
+ color: #ffffff;
+}
+
+div#searchbox p.searchtip {
+ color:#000000;
+ font-size:90%;
+ padding-top:50px;
+}
+
+div#searchbox {
+ background-image:url(images/background_search.jpg);
+ background-repeat:no-repeat;
+ background-position:center;
+ border:none;
+}
+
+div.sphinxsidebar a {
+ color: #009491;
+}
+
+
+/* -- body styles ----------------------------------------------------------- */
+
+a {
+ color: #009491;
+ text-decoration: underline;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+div.body p, div.body dd, div.body li {
+ text-align: left;
+ line-height: 130%;
+}
+
+div.body h1 {
+ font-family: Arial, Verdana, sans-serif;
+ background-color: #f2f2f2;
+ font-weight: normal;
+ color: #20435c;
+ border-bottom: 1px solid #ccc;
+ margin: 20px -20px 10px -20px;
+ padding: 3px 0 3px 10px;
+}
+
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+ font-family: Arial, Verdana, Helvetica, sans-serif;
+ font-size:12px;
+ font-weight:normal;
+ border-left-width: 1px;
+ border-right-width: 1px;
+ border-top-width: 1px;
+ border-bottom-width: 2px;
+ border-style: solid;
+ border-left-color: #b1b1b1;
+ border-right-color: #b1b1b1;
+ border-top-color: #b1b1b1;
+ border-bottom-color: #009491;
+ background-color: #e0e0e0;
+ padding-left:5px;
+}
+
+div.body h1 { margin-top: 0; font-size: 200%; }
+div.body h2 { font-size: 120%; }
+div.body h3 { font-size: 115%; }
+div.body h4 { font-size: 110%; }
+div.body h5 { font-size: 105%; }
+div.body h6 { font-size: 100%; }
+
+a.headerlink {
+ color: #c60f0f;
+ font-size: 0.8em;
+ padding: 0 4px 0 4px;
+ text-decoration: none;
+}
+
+a.headerlink:hover {
+ background-color: #c60f0f;
+ color: white;
+}
+
+div.body p, div.body dd, div.body li {
+ text-align: left;
+ line-height: 130%;
+}
+
+div.admonition p.admonition-title + p {
+ display: inline;
+}
+
+div.note {
+ background-color: #eee;
+ border: 1px solid #ccc;
+}
+
+div.seealso {
+ background-color: #ffc;
+ border: 1px solid #ff6;
+}
+
+div.topic {
+ background-color: #eee;
+}
+
+div.warning {
+ background-color: #ffe4e4;
+ border: 1px solid #f66;
+}
+
+p.admonition-title {
+ display: inline;
+}
+
+p.admonition-title:after {
+ content: ":";
+}
+
+input[type=text]{
+ background-color: #009491;
+ font: 11px verdana, arial, helvetica, sans-serif;
+ color:#FFFFFF;
+ width: 150px;
+ height: 18px;
+ border: 1px solid #009491;
+ margin-left:13px;
+ margin-top:15px;
+ margin-bottom:4px;
+ border:none;
+}
+
+pre {
+ padding: 5px;
+ background-color: #eeffcc;
+ color: #333333;
+ line-height: 120%;
+ border: 1px solid #ac9;
+ border-left: none;
+ border-right: none;
+}
+
+tt {
+ background-color: #ecf0f3;
+ padding: 0 1px 0 1px;
+ font-size: 0.95em;
+}
diff --git a/doc/_static/images/._background_search.jpg b/doc/_static/images/._background_search.jpg
new file mode 100755
index 0000000..d5c689c
--- /dev/null
+++ b/doc/_static/images/._background_search.jpg
Binary files differ
diff --git a/doc/_static/images/._bread_crumb.png b/doc/_static/images/._bread_crumb.png
new file mode 100755
index 0000000..46b8591
--- /dev/null
+++ b/doc/_static/images/._bread_crumb.png
Binary files differ
diff --git a/doc/_static/images/._button_search.jpg b/doc/_static/images/._button_search.jpg
new file mode 100755
index 0000000..d5c689c
--- /dev/null
+++ b/doc/_static/images/._button_search.jpg
Binary files differ
diff --git a/doc/_static/images/._side_background.jpg b/doc/_static/images/._side_background.jpg
new file mode 100755
index 0000000..a79b91c
--- /dev/null
+++ b/doc/_static/images/._side_background.jpg
Binary files differ
diff --git a/doc/_static/images/._top_background.jpg b/doc/_static/images/._top_background.jpg
new file mode 100755
index 0000000..d5c689c
--- /dev/null
+++ b/doc/_static/images/._top_background.jpg
Binary files differ
diff --git a/doc/_static/images/background_search.jpg b/doc/_static/images/background_search.jpg
new file mode 100644
index 0000000..c0481c5
--- /dev/null
+++ b/doc/_static/images/background_search.jpg
Binary files differ
diff --git a/doc/_static/images/bg.jpg b/doc/_static/images/bg.jpg
new file mode 100644
index 0000000..2ceb195
--- /dev/null
+++ b/doc/_static/images/bg.jpg
Binary files differ
diff --git a/doc/_static/images/bread_crumb.png b/doc/_static/images/bread_crumb.png
new file mode 100644
index 0000000..f7ebd20
--- /dev/null
+++ b/doc/_static/images/bread_crumb.png
Binary files differ
diff --git a/doc/_static/images/button_search.png b/doc/_static/images/button_search.png
new file mode 100644
index 0000000..0160b81
--- /dev/null
+++ b/doc/_static/images/button_search.png
Binary files differ
diff --git a/doc/_static/images/side_background.jpg b/doc/_static/images/side_background.jpg
new file mode 100644
index 0000000..6e66675
--- /dev/null
+++ b/doc/_static/images/side_background.jpg
Binary files differ
diff --git a/doc/_static/images/top_background.jpg b/doc/_static/images/top_background.jpg
new file mode 100644
index 0000000..aafe1f7
--- /dev/null
+++ b/doc/_static/images/top_background.jpg
Binary files differ
diff --git a/doc/_templates/index.html b/doc/_templates/index.html
new file mode 100644
index 0000000..296aae2
--- /dev/null
+++ b/doc/_templates/index.html
@@ -0,0 +1,32 @@
+{% extends "layout.html" %}
+{% set title = 'Overview' %}
+{% block body %}
+ <h1>BoostPythonGenerator {{ version }}</h1>
+
+ <p>BoostPythonGenerator is a tool that eases the development of Python bindings for Qt-based
+ libraries by automating most of the process. It relies heavily on the ApiExtractor library
+ to parse the header files and manipulate the classes information while generating the code.
+ This generated code uses the
+ <a href="http://www.boost.org/doc/libs/1_39_0/libs/python/doc/index.html">Boost::Python library</a>
+ in order to bridge the C++ library and Python.</p>
+
+ <p>BoostPythonGenerator is based on the
+ <a href="http://labs.trolltech.com/page/Projects/QtScript/Generator">QtScriptGenerator</a> project.</p>
+
+ <h2>Documentation</h2>
+ <table class="contentstable" align="center" style="margin-left: 30px"><tr>
+ <td width="50%">
+ <p class="biglink"><a class="biglink" href="{{ pathto("overview") }}">Overview</a><br/>
+ <span class="linkdescr">how generator works</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("tutorial/introduction") }}">Tutorial</a><br/>
+ <span class="linkdescr">start here</span></p>
+ </td>
+ <td width="50%">
+ <p class="biglink"><a class="biglink" href="{{ pathto("compiling/compiling") }}">Compiling/Installing</a><br/>
+ <span class="linkdescr">how to compile and install BoostPythonGenerator</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">Contents</a><br/>
+ <span class="linkdescr">for a complete overview</span></p>
+ </td></tr>
+ </table>
+
+{% endblock %}
diff --git a/doc/_templates/layout.html b/doc/_templates/layout.html
new file mode 100644
index 0000000..12fed4d
--- /dev/null
+++ b/doc/_templates/layout.html
@@ -0,0 +1,34 @@
+{% extends "!layout.html" %}
+{% block rootrellink %}
+ <!--<li><img src="{{ pathto('_static/py.png', 1) }}" alt=""
+ style="vertical-align: middle; margin-top: -1px"/></li>-->
+ <li><a href="{{ pathto('index') }}">{{ shorttitle }}</a>{{ reldelim1 }}</li>
+{% endblock %}
+{% set reldelim1 = '' %}
+{% block extrahead %}
+ <!--<link rel="shortcut icon" type="image/png" href="{{ pathto('_static/py.png', 1) }}" />-->
+{{ super() }}
+{% endblock %}
+
+{% block sidebarsearch %}
+ <div id="searchbox" style="display: none">
+ <h3>Quick search</h3>
+ <form class="search" action="search.html" method="get">
+ <div style="width:195px;">
+ <div style="float:left;">
+ <input type="text" name="q" size="18" />
+ </div>
+ <div style="float:right; padding-top:14px; ">
+ <input type="image" src="{{ pathto('_static/images/button_search.png', 1) }}"/>
+ </div>
+ </div>
+ <input type="hidden" name="check_keywords" value="yes" />
+ <input type="hidden" name="area" value="default" />
+ </form>
+ <p class="searchtip" style="font-size: 90%">
+ Enter search terms or a module, class or function name.
+ </p>
+ </div>
+ <script type="text/javascript">$('#searchbox').show(0);</script>
+{% endblock %}
+
diff --git a/doc/compiling/cmake-primer.rst b/doc/compiling/cmake-primer.rst
new file mode 100644
index 0000000..7769005
--- /dev/null
+++ b/doc/compiling/cmake-primer.rst
@@ -0,0 +1,72 @@
+
+.. _cmake-primer:
+
+************
+CMake primer
+************
+
+This chapter is a basic introduction to CMake, the build system used by PySide
+and the boost binding generator.
+
+The practical steps will focus on how to use cmake on a Unix-like (GNU/Linux)
+environment.
+
+
+Configuring
+===========
+
+Project file - CMakeLists.txt
+-----------------------------
+
+CMake parses the file CMakeLists.txt for information about the project,
+like project name, dependencies, what should be compiled, what should be
+shipped.
+
+
+CMake variables
+---------------
+
+CMake can have its default behavior modified by providing some
+
+* ``CMAKE_INSTALL_PREFIX=<some path here>`` sets the install prefix to
+ the specified path.
+* ``CMAKE_MODULE_PATH=<some path here>`` sets the extra directories
+ where CMake will try to find its modules.
+* ``CMAKE_TOOLCHAIN_FILE=<file path>`` sets the path to the file that
+ describes the toolchain used to compile this project. It is very useful
+ when using CMake with icecc to speedup compilation.
+
+You can define a variable using the ``-D<VARIABLE>`` switch like the example
+below.
+
+* ``-DCMAKE_BUILD_TYPE=Release|Debug`` sets the building behavior. Default
+ value is *Release*.
+
+Invoking CMake
+--------------
+
+After writing the CMakeLists.txt and deciding which flags will be used,
+you can invoke CMake using::
+
+ cmake <CMake flags> <path to toplevel CMakeLists.txt file>
+
+For example, if you use the ``build/`` folder to build the project and
+want it to be installed into ``/opt/sandbox/``, use the following lines::
+
+ cd build/
+ cmake -DCMAKE_INSTALL_PREFIX=/opt/sandbox ..
+
+CMake will process the project file and write the output files in the
+current directory
+
+Building
+========
+
+After the configuration process, the Makefiles are written and you can build
+the project using :program:`make`.
+
+Installing
+==========
+
+As in the building process, ``make install`` will install the files into
+the target directory.
diff --git a/doc/compiling/compiling.rst b/doc/compiling/compiling.rst
new file mode 100644
index 0000000..638efa9
--- /dev/null
+++ b/doc/compiling/compiling.rst
@@ -0,0 +1,9 @@
+Compiling
+*********
+
+.. toctree::
+ :maxdepth: 3
+
+ cmake-primer
+ setup-apiextractor
+ setup-generator
diff --git a/doc/compiling/setup-apiextractor.rst b/doc/compiling/setup-apiextractor.rst
new file mode 100644
index 0000000..5443f46
--- /dev/null
+++ b/doc/compiling/setup-apiextractor.rst
@@ -0,0 +1,48 @@
+
+.. _api-extractor:
+
+**************
+API Extractor
+**************
+
+Overview
+========
+
+The **API Extractor** library is used by the binding generator to
+parse the header and typesystem files to create an internal
+representation of the API. It is based on the QtScriptGenerator
+codebase.
+
+Getting the sources
+===================
+
+* Download URL: http://www.pyside.org/downloads/
+
+Build requirements
+==================
+
+* Qt4.5 development headers and libraries >= 4.5.0
+* libboost-graph >= 1.38.0
+* cmake >= 2.6.0
+
+Building and installing
+=======================
+
+To build and install just follow the generic cmake instructions in section
+:ref:`cmake-primer`.
+
+Debian packaging
+================
+
+In order to compile this package in a debian environment, make sure the
+following packages are installed:
+
+* debhelper (>= 5)
+* cdbs
+* cmake (>= 2.6.0)
+* libboost-graph1.38-dev (>= 1.38.0)
+* libqt4-dev (>= 4.5)
+
+And then you can build the package using::
+
+ $ dpkg-buildpackage -rfakeroot
diff --git a/doc/compiling/setup-generator.rst b/doc/compiling/setup-generator.rst
new file mode 100644
index 0000000..d58f983
--- /dev/null
+++ b/doc/compiling/setup-generator.rst
@@ -0,0 +1,49 @@
+
+.. _boost-python-generator:
+
+***********************
+Boost::Python Generator
+***********************
+
+Overview
+=========================================
+
+The **Boost::Python Generator** (A.K.A. :program:`boostpythongenerator`) is
+the program that creates the bindings source files from Qt headers and
+auxiliary files (typesystems, ``global.h`` and glue files). It makes
+heavy use of the :ref:`api-extractor` library.
+
+
+Getting the sources
+===================
+
+* Download URL: http://www.pyside.org/downloads/
+
+Build requirements
+==================
+
++ CMake >= 2.6.0
++ Qt4.5 libraries and development headers >= 4.5.0
++ :ref:`api-extractor` + development headers
+
+Building and installing
+=======================
+
+To build and install just follow the generic cmake instructions in
+section :ref:`cmake-primer`.
+
+Debian packaging
+================
+
+In order to compile this package in a debian environment, make sure the
+following packages are installed:
+
+* debhelper (>= 5)
+* cdbs
+* cmake (>= 2.6.0)
+* libqt4-dev (>= 4.5)
+* libapiextractor-dev (>= 0.1)
+
+And then you can build the package using::
+
+ $ dpkg-buildpackage -rfakeroot
diff --git a/doc/conf.py b/doc/conf.py
new file mode 100644
index 0000000..8d196e4
--- /dev/null
+++ b/doc/conf.py
@@ -0,0 +1,188 @@
+# -*- coding: utf-8 -*-
+#
+# BoostPythonGenerator documentation build configuration file, created by
+# sphinx-quickstart on Wed Apr 22 15:04:20 2009.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.append(os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.ifconfig', 'sphinx.ext.refcounting', 'sphinx.ext.coverage']
+
+rst_epilog = """
+.. |project| replace:: BoostPythonGenerator
+"""
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+source_encoding = 'utf-8'
+
+# The master toctree document.
+#master_doc = 'contents'
+
+# General information about the project.
+project = u'BoostPythonGenerator'
+copyright = u'2009, Nokia Corporation'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '0.1'
+# The full version, including alpha/beta/rc tags.
+release = '0.1'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# List of directories, relative to source directory, that shouldn't be searched
+# for source files.
+exclude_trees = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. Major themes that come with
+# Sphinx are currently 'default' and 'sphinxdoc'.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {
+#}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = { '' : ''}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+html_additional_pages = { 'index' : 'index.html'}
+
+# If false, no module index is generated.
+#html_use_modindex = True
+
+# If false, no index is generated.
+html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+html_show_sourcelink = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
diff --git a/doc/contents.rst b/doc/contents.rst
new file mode 100644
index 0000000..5574c7a
--- /dev/null
+++ b/doc/contents.rst
@@ -0,0 +1,9 @@
+Table of contents
+*****************
+.. toctree::
+ :numbered:
+ :maxdepth: 3
+
+ overview.rst
+ tutorial/introduction.rst
+ compiling/compiling.rst
diff --git a/doc/dependency-pyside.svg b/doc/dependency-pyside.svg
new file mode 100644
index 0000000..786bdb8
--- /dev/null
+++ b/doc/dependency-pyside.svg
@@ -0,0 +1,527 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="900"
+ height="560"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ version="1.0"
+ sodipodi:docname="dependency-pyside.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/tmp/dependency-pyside.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path3270"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(0.8,0,0,0.8,10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lend"
+ style="overflow:visible">
+ <path
+ id="path3679"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.79440331"
+ inkscape:cx="-36.66006"
+ inkscape:cy="372.04724"
+ inkscape:document-units="px"
+ inkscape:current-layer="svg2"
+ showgrid="false"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-width="1278"
+ inkscape:window-height="949"
+ inkscape:window-x="0"
+ inkscape:window-y="0">
+ <sodipodi:guide
+ orientation="1,0"
+ position="384.28571,590"
+ id="guide2601" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="678.57143,491.42857"
+ id="guide2603" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="78.571429,257.14286"
+ id="guide2605" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="93.571429,280.71429"
+ id="guide7565" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="148.57143,216.42857"
+ id="guide7567" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-78.088635,-190.95252)" />
+ <g
+ id="g5394"
+ transform="translate(6.1314759,14.304617)">
+ <g
+ transform="translate(-65.84289,-190.95252)"
+ id="g5205">
+ <g
+ id="g5171">
+ <rect
+ rx="9.3643799"
+ y="338.7739"
+ x="678.57141"
+ height="73.281754"
+ width="274.54263"
+ id="rect2393"
+ style="fill:#aaeeff;fill-rule:evenodd;stroke:#006078;stroke-width:0.96620417px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ ry="13.104657" />
+ <text
+ id="text2395"
+ y="355.93701"
+ x="683.46539"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="355.93701"
+ x="683.46539"
+ id="tspan2397"
+ sodipodi:role="line">boost::python</tspan></text>
+ <text
+ id="text2399"
+ y="371.60172"
+ x="683.46539"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="371.60172"
+ x="683.46539"
+ id="tspan2401"
+ sodipodi:role="line">1.38.0</tspan></text>
+ <text
+ id="text2403"
+ y="387.14166"
+ x="683.46539"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan2435"
+ y="387.14166"
+ x="683.46539"
+ sodipodi:role="line">headers and libraries - compile-time and run-time</tspan></text>
+ <text
+ id="text2413"
+ y="402.4646"
+ x="683.46539"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="402.4646"
+ x="683.46539"
+ id="tspan2415"
+ sodipodi:role="line">Boost Software License 1.0</tspan></text>
+ </g>
+ <g
+ id="g5193">
+ <rect
+ rx="8.3239012"
+ y="342.86383"
+ x="78.571426"
+ height="73.282379"
+ width="274.18781"
+ id="rect2417"
+ style="fill:#b3ff80;fill-rule:evenodd;stroke:#2a7800;stroke-width:0.96558368px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ ry="9.2689295" />
+ <text
+ id="text2419"
+ y="359.67014"
+ x="88.822823"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="359.67014"
+ x="88.822823"
+ id="tspan2421"
+ sodipodi:role="line">Qt 4.5</tspan></text>
+ <text
+ id="text2423"
+ y="375.33484"
+ x="88.822823"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="375.33484"
+ x="88.822823"
+ id="tspan2425"
+ sodipodi:role="line">4.5</tspan></text>
+ <text
+ id="text2427"
+ y="390.87479"
+ x="88.822823"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="390.87479"
+ x="88.822823"
+ id="tspan2429"
+ sodipodi:role="line">headers and libraries - compile-time and run-time</tspan></text>
+ <text
+ id="text2431"
+ y="400.84058"
+ x="88.822823"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="400.84058"
+ x="88.822823"
+ id="tspan2433"
+ sodipodi:role="line">GNU General Public License v3 /</tspan><tspan
+ y="411.1687"
+ x="88.822823"
+ sodipodi:role="line"
+ id="tspan2472">GNU Lesser General Public Licence v2.1</tspan></text>
+ </g>
+ <g
+ id="g5120">
+ <rect
+ y="496.43558"
+ x="384.28571"
+ height="73.281754"
+ width="274.54263"
+ id="rect2441"
+ style="fill:#e9ddaf;fill-rule:evenodd;stroke:#5f5019;stroke-width:0.96620417px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ ry="13.104635"
+ rx="10.404889" />
+ <text
+ id="text2443"
+ y="513.59869"
+ x="389.17969"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="513.59869"
+ x="389.17969"
+ id="tspan2445"
+ sodipodi:role="line">libapiextractor</tspan></text>
+ <text
+ id="text2447"
+ y="529.26337"
+ x="389.17969"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="529.26337"
+ x="389.17969"
+ id="tspan2449"
+ sodipodi:role="line">0.1</tspan></text>
+ <text
+ id="text2451"
+ y="544.80334"
+ x="389.17969"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan2453"
+ y="544.80334"
+ x="389.17969"
+ sodipodi:role="line">headers and libraries - compile-time and run-time</tspan></text>
+ <text
+ id="text2455"
+ y="560.12628"
+ x="389.17969"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="560.12628"
+ x="389.17969"
+ id="tspan2457"
+ sodipodi:role="line">LGPL version 2.1</tspan></text>
+ </g>
+ <g
+ id="g5131">
+ <rect
+ y="340.72134"
+ x="384.28571"
+ height="73.281754"
+ width="274.54263"
+ id="rect2459"
+ style="fill:#e9ddaf;fill-rule:evenodd;stroke:#5f5019;stroke-width:0.96620417px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ ry="10.309408"
+ rx="9.3644047" />
+ <text
+ id="text2461"
+ y="357.88449"
+ x="389.17969"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="357.88449"
+ x="389.17969"
+ id="tspan2463"
+ sodipodi:role="line">BoostPythonGenerator</tspan></text>
+ <text
+ id="text2465"
+ y="373.54916"
+ x="389.17969"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="373.54916"
+ x="389.17969"
+ id="tspan2467"
+ sodipodi:role="line">0.1</tspan></text>
+ <text
+ id="text2469"
+ y="389.08914"
+ x="389.17969"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan2471"
+ y="389.08914"
+ x="389.17969"
+ sodipodi:role="line">Binary executable - compile-time</tspan></text>
+ <text
+ id="text2473"
+ y="404.41208"
+ x="389.17969"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="404.41208"
+ x="389.17969"
+ id="tspan2475"
+ sodipodi:role="line">LGPL version 2.1</tspan></text>
+ </g>
+ <g
+ id="g5142">
+ <rect
+ y="191.43562"
+ x="384.28571"
+ height="73.281754"
+ width="274.54263"
+ id="rect2523"
+ style="fill:#e9ddaf;fill-opacity:1;fill-rule:evenodd;stroke:#5f5019;stroke-width:0.96620417px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ ry="14.285714" />
+ <text
+ id="text2525"
+ y="208.59874"
+ x="389.17966"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="208.59874"
+ x="389.17966"
+ id="tspan2527"
+ sodipodi:role="line">Qt Python bindings</tspan></text>
+ <text
+ id="text2529"
+ y="224.26344"
+ x="389.17966"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="224.26344"
+ x="389.17966"
+ id="tspan2531"
+ sodipodi:role="line">0.1</tspan></text>
+ <text
+ id="text2533"
+ y="239.80339"
+ x="389.17966"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan2535"
+ y="239.80339"
+ x="389.17966"
+ sodipodi:role="line">Target</tspan></text>
+ <text
+ id="text2537"
+ y="255.12633"
+ x="389.17966"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="255.12633"
+ x="389.17966"
+ id="tspan2539"
+ sodipodi:role="line">LGPL version 2.1</tspan></text>
+ </g>
+ <g
+ id="g5182">
+ <rect
+ rx="10.404877"
+ y="648.57843"
+ x="384.28571"
+ height="73.281754"
+ width="274.54263"
+ id="rect2563"
+ style="fill:#aaeeff;fill-rule:evenodd;stroke:#006078;stroke-width:0.96620417px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ ry="11.287985" />
+ <text
+ id="text2565"
+ y="665.74158"
+ x="389.17969"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="665.74158"
+ x="389.17969"
+ id="tspan2567"
+ sodipodi:role="line">boost::graph</tspan></text>
+ <text
+ id="text2569"
+ y="681.40625"
+ x="389.17969"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="681.40625"
+ x="389.17969"
+ id="tspan2571"
+ sodipodi:role="line">1.38.0</tspan></text>
+ <text
+ id="text2573"
+ y="696.94623"
+ x="389.17969"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan2575"
+ y="696.94623"
+ x="389.17969"
+ sodipodi:role="line">headers and libraries - compile-time and run-time</tspan></text>
+ <text
+ id="text2577"
+ y="712.26917"
+ x="389.17969"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="712.26917"
+ x="389.17969"
+ id="tspan2579"
+ sodipodi:role="line">Boost Software License 1.0</tspan></text>
+ </g>
+ </g>
+ <path
+ inkscape:connector-type="polyline"
+ id="path2869"
+ d="M 212.85114,151.42852 L 368.56822,74.247959"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-type="polyline"
+ id="path2871"
+ d="M 663.60462,147.33826 L 517.61788,74.247959"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-type="polyline"
+ id="path2877"
+ d="M 443.4684,149.28571 L 443.46839,74.247959"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-type="polyline"
+ id="path2879"
+ d="M 443.4684,304.99994 L 443.4684,223.53367"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-type="polyline"
+ id="path2881"
+ d="M 443.4684,457.14279 L 443.4684,379.2479"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-mid:none;marker-end:none;stroke-opacity:1" />
+ <rect
+ ry="17.142857"
+ y="293.85626"
+ x="0.48279184"
+ height="124.28571"
+ width="211.42857"
+ id="rect7541"
+ style="fill:#e3e2db;stroke:#000000;stroke-opacity:1" />
+ <text
+ id="text7543"
+ y="325.44049"
+ x="70.482788"
+ style="font-size:20.61732101px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="325.44049"
+ x="70.482788"
+ id="tspan7545"
+ sodipodi:role="line">Boost</tspan></text>
+ <text
+ id="text7547"
+ y="358.37042"
+ x="70.482788"
+ style="font-size:20.61732101px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="358.37042"
+ x="70.482788"
+ id="tspan7549"
+ sodipodi:role="line">Qt Software</tspan></text>
+ <text
+ id="text7551"
+ y="394.07593"
+ x="70.482788"
+ style="font-size:20.61732101px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="394.07593"
+ x="70.482788"
+ id="tspan7553"
+ sodipodi:role="line">INdT/Nokia</tspan></text>
+ <rect
+ ry="6.4285707"
+ y="307.24911"
+ x="15.482792"
+ height="22.5"
+ width="43.163269"
+ id="rect7555"
+ style="fill:#aaeeff;fill-opacity:1;stroke:#000000;stroke-width:0.64285713;stroke-opacity:1" />
+ <rect
+ ry="6.4285707"
+ y="341.17767"
+ x="15.482792"
+ height="22.5"
+ width="43.163269"
+ id="rect7561"
+ style="fill:#b3ff80;fill-opacity:1;stroke:#000000;stroke-width:0.64285713;stroke-opacity:1" />
+ <rect
+ ry="6.4285707"
+ y="376.17767"
+ x="15.482792"
+ height="22.5"
+ width="43.163269"
+ id="rect7563"
+ style="fill:#e9ddaf;fill-opacity:1;stroke:#000000;stroke-width:0.64285713;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/doc/images/.directory b/doc/images/.directory
new file mode 100644
index 0000000..e65475f
--- /dev/null
+++ b/doc/images/.directory
@@ -0,0 +1,3 @@
+[Dolphin]
+ShowPreview=true
+Timestamp=2009,5,5,17,43,26
diff --git a/doc/images/bindinggen-development.png b/doc/images/bindinggen-development.png
new file mode 100644
index 0000000..3d64e76
--- /dev/null
+++ b/doc/images/bindinggen-development.png
Binary files differ
diff --git a/doc/images/bindinggen-development.svg b/doc/images/bindinggen-development.svg
new file mode 100644
index 0000000..3b6b3a2
--- /dev/null
+++ b/doc/images/bindinggen-development.svg
@@ -0,0 +1,543 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="640"
+ height="200"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ version="1.0"
+ sodipodi:docname="bindgen-development.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="bindinggen-development.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="EmptyDiamondL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="EmptyDiamondL"
+ style="overflow:visible">
+ <path
+ id="path3930"
+ d="M 0,-7.0710768 L -7.0710894,0 L 0,7.0710589 L 7.0710462,0 L 0,-7.0710768 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="scale(0.8,0.8)" />
+ </marker>
+ <marker
+ inkscape:stockid="EmptyTriangleInL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="EmptyTriangleInL"
+ style="overflow:visible">
+ <path
+ id="path3975"
+ d="M 5.77,0 L -2.88,5 L -2.88,-5 L 5.77,0 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,4.8,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Sstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Sstart"
+ style="overflow:visible">
+ <path
+ id="path3835"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(0.2,0,0,0.2,1.2,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend"
+ style="overflow:visible">
+ <path
+ id="path3832"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Tail"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Tail"
+ style="overflow:visible">
+ <g
+ id="g3859"
+ transform="scale(-1.2,-1.2)">
+ <path
+ id="path3861"
+ d="M -3.8048674,-3.9585227 L 0.54352094,0"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3863"
+ d="M -1.2866832,-3.9585227 L 3.0617053,0"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3865"
+ d="M 1.3053582,-3.9585227 L 5.6537466,0"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3867"
+ d="M -3.8048674,4.1775838 L 0.54352094,0.21974226"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3869"
+ d="M -1.2866832,4.1775838 L 3.0617053,0.21974226"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3871"
+ d="M 1.3053582,4.1775838 L 5.6537466,0.21974226"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ </g>
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible">
+ <path
+ id="path3636"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.0859375"
+ inkscape:cx="320"
+ inkscape:cy="136.17463"
+ inkscape:document-units="px"
+ inkscape:current-layer="g5658"
+ showgrid="false"
+ inkscape:window-width="1156"
+ inkscape:window-height="883"
+ inkscape:window-x="1396"
+ inkscape:window-y="35"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <sodipodi:guide
+ orientation="1,0"
+ position="-557.55608,678.10875"
+ id="guide7299" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-1758.7331,-2056.8567)">
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot3229"
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ transform="translate(4.1137413,-2.3429609)"><flowRegion
+ id="flowRegion3231"><rect
+ id="rect3233"
+ width="125.74072"
+ height="40.5849"
+ x="388.45547"
+ y="279.5423" /></flowRegion><flowPara
+ id="flowPara3235" /></flowRoot> <g
+ id="g5658"
+ transform="translate(6.5767925,7.0112479)">
+ <g
+ id="g5634">
+ <g
+ id="g6271"
+ transform="translate(1086.3689,746.93837)">
+ <g
+ transform="matrix(0,-1,1,0,-294.81158,2953.0504)"
+ id="g6252">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 1586.5317,1300.2858 L 1586.6222,1389.8124"
+ id="path11089"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path2758"
+ d="M 1586.7489,1389.4756 L 1594.7468,1380.3688"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path2760"
+ d="M 1586.6031,1389.5063 L 1578.6052,1380.3994"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ </g>
+ </g>
+ </g>
+ <g
+ transform="translate(134.35978,44.472131)"
+ id="g2777">
+ <rect
+ style="fill:#addc52;fill-opacity:1;stroke:#6ca400;stroke-width:0.82399696;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect5172"
+ width="185.49777"
+ height="75.08918"
+ x="2047.775"
+ y="2029.4594"
+ ry="3.0323718"
+ rx="2.6724329" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="2140.5562"
+ y="2062.9375"
+ id="text5174"><tspan
+ sodipodi:role="line"
+ x="2140.5562"
+ y="2062.9375"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ id="tspan5176">Qt bindings</tspan><tspan
+ id="tspan6109"
+ sodipodi:role="line"
+ x="2140.5562"
+ y="2084.457"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">(generated code)</tspan></text>
+ </g>
+ <g
+ transform="translate(141.86951,-31.391207)"
+ id="g3216">
+ <rect
+ style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:0.64492828;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3625"
+ width="185.67708"
+ height="75.268074"
+ x="1829.1727"
+ y="2105.2332"
+ ry="2.3353095"
+ rx="2.1257713" />
+ <text
+ xml:space="preserve"
+ style="font-size:38.71272278px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="1921.9705"
+ y="2136.9409"
+ id="text3627"
+ transform="scale(1.0000266,0.9999734)"><tspan
+ id="tspan3697"
+ sodipodi:role="line"
+ x="1921.9705"
+ y="2136.9409"
+ style="font-size:21.29199791px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold">generator</tspan><tspan
+ sodipodi:role="line"
+ x="1921.9705"
+ y="2163.5559"
+ style="font-size:21.29199791px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ id="tspan2464">front-end</tspan></text>
+ </g>
+ <g
+ id="g5641">
+ <g
+ id="g5465"
+ transform="translate(874.42628,746.93837)">
+ <g
+ transform="matrix(0,-1,1,0,-294.81158,2953.0504)"
+ id="g5467">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 1586.5317,1300.2858 L 1586.6222,1389.8124"
+ id="path5469"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path5471"
+ d="M 1586.7489,1389.4756 L 1594.7468,1380.3688"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path5473"
+ d="M 1586.6031,1389.5063 L 1578.6052,1380.3994"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ </g>
+ </g>
+ </g>
+ <g
+ transform="translate(-194.79968,-212.08495)"
+ id="g5440">
+ <rect
+ rx="1.2158648"
+ ry="2.9911308"
+ y="2285.8806"
+ x="1953.809"
+ height="75.360634"
+ width="185.76964"
+ id="rect3166"
+ style="fill:#dfe994;fill-opacity:1;stroke:#d5f400;stroke-width:0.55236381;stroke-opacity:1" />
+ <text
+ id="text3168"
+ y="2328.8809"
+ x="2046.646"
+ style="font-size:27.94354057px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#4c5800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ style="font-size:19.56047821px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#4c5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="2328.8809"
+ x="2046.646"
+ sodipodi:role="line"
+ id="tspan5424">API Extractor</tspan></text>
+ </g>
+ <g
+ transform="translate(-102.30216,-279.71223)"
+ id="g5541">
+ <path
+ sodipodi:type="arc"
+ style="fill:#f28888;fill-opacity:1;stroke:#d5f400;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:3, 3;stroke-dashoffset:0;stroke-opacity:1"
+ id="path5535"
+ sodipodi:cx="255.10791"
+ sodipodi:cy="326.69064"
+ sodipodi:rx="38.848923"
+ sodipodi:ry="38.848923"
+ d="M 293.95683,326.69064 A 38.848923,38.848923 0 1 1 216.25899,326.69064 A 38.848923,38.848923 0 1 1 293.95683,326.69064 z"
+ transform="matrix(0.4405339,0,0,0.4405339,1842.2283,2282.9708)" />
+ <text
+ xml:space="preserve"
+ style="font-size:27.62000275px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="1946.3259"
+ y="2435.7"
+ id="text5537"><tspan
+ sodipodi:role="line"
+ id="tspan5539"
+ x="1946.3259"
+ y="2435.7"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:FreeMono;-inkscape-font-specification:FreeMono Bold">1</tspan></text>
+ </g>
+ <g
+ transform="translate(52.589867,-352.69787)"
+ id="g5546">
+ <path
+ sodipodi:type="arc"
+ style="fill:#f28888;fill-opacity:1;stroke:#d5f400;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:3, 3;stroke-dashoffset:0;stroke-opacity:1"
+ id="path5548"
+ sodipodi:cx="255.10791"
+ sodipodi:cy="326.69064"
+ sodipodi:rx="38.848923"
+ sodipodi:ry="38.848923"
+ d="M 293.95683,326.69064 A 38.848923,38.848923 0 1 1 216.25899,326.69064 A 38.848923,38.848923 0 1 1 293.95683,326.69064 z"
+ transform="matrix(0.4405339,0,0,0.4405339,1842.2283,2282.9708)" />
+ <text
+ xml:space="preserve"
+ style="font-size:27.62000275px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="1946.3259"
+ y="2435.7"
+ id="text5550"><tspan
+ sodipodi:role="line"
+ id="tspan5552"
+ x="1946.3259"
+ y="2435.7"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:FreeMono;-inkscape-font-specification:FreeMono Bold">2</tspan></text>
+ </g>
+ <g
+ transform="matrix(0,-1,1,0,697.50638,3244.256)"
+ id="g5624">
+ <g
+ id="g5626"
+ transform="matrix(0,-1,1,0,-294.81158,2953.0504)">
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path5628"
+ d="M 1586.5317,1348.2858 L 1586.6222,1389.8124"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 1586.7489,1389.4756 L 1594.7468,1380.3688"
+ id="path5630"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 1586.6031,1389.5063 L 1578.6052,1380.3994"
+ id="path5632"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ </g>
+ </g>
+ <g
+ transform="translate(5.3442137,15.993306)"
+ id="g5459">
+ <rect
+ rx="2.4652832"
+ ry="2.9818845"
+ y="2151.3206"
+ x="1965.7682"
+ height="75.127686"
+ width="185.53668"
+ id="rect3485"
+ style="fill:#b2e994;fill-opacity:1;stroke:#56f400;stroke-width:0.78531456;stroke-opacity:1" />
+ <text
+ id="text3487"
+ y="2184.2461"
+ x="2059.1909"
+ style="font-size:27.94354057px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#1f5800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan2509"
+ style="font-size:19.56047821px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#1f5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="2184.2461"
+ x="2059.1909"
+ sodipodi:role="line">typesystem</tspan><tspan
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#1f5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="2205.1477"
+ x="2059.1909"
+ sodipodi:role="line"
+ id="tspan5432">(handwritten)</tspan></text>
+ </g>
+ <g
+ transform="matrix(0,-1,1,0,908.50929,3242.9612)"
+ id="g5648">
+ <g
+ id="g5650"
+ transform="matrix(0,-1,1,0,-294.81158,2953.0504)">
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path5652"
+ d="M 1586.5317,1348.2858 L 1586.6222,1389.8124"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 1586.7489,1389.4756 L 1594.7468,1380.3688"
+ id="path5654"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 1586.6031,1389.5063 L 1578.6052,1380.3994"
+ id="path5656"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ </g>
+ </g>
+ <g
+ transform="translate(299.78191,21.148391)"
+ id="g2771">
+ <rect
+ style="fill:#cce994;fill-opacity:1;stroke:#a1f400;stroke-width:0.62429351;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2733"
+ width="185.69771"
+ height="75.288704"
+ x="1882.2529"
+ y="2146.085"
+ ry="2.2607138"
+ rx="2.0576432" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#3a5800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="1975.134"
+ y="2180.2722"
+ id="text2735"><tspan
+ sodipodi:role="line"
+ x="1975.134"
+ y="2180.2722"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#3a5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ id="tspan2737">injected code</tspan><tspan
+ id="tspan2743"
+ sodipodi:role="line"
+ x="1975.134"
+ y="2201.7917"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#3a5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">(handwritten)</tspan></text>
+ </g>
+ <g
+ transform="translate(200.4676,-222.96766)"
+ id="g5554">
+ <path
+ sodipodi:type="arc"
+ style="fill:#f28888;fill-opacity:1;stroke:#d5f400;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:3, 3;stroke-dashoffset:0;stroke-opacity:1"
+ id="path5556"
+ sodipodi:cx="255.10791"
+ sodipodi:cy="326.69064"
+ sodipodi:rx="38.848923"
+ sodipodi:ry="38.848923"
+ d="M 293.95683,326.69064 A 38.848923,38.848923 0 1 1 216.25899,326.69064 A 38.848923,38.848923 0 1 1 293.95683,326.69064 z"
+ transform="matrix(0.4405339,0,0,0.4405339,1842.2283,2282.9708)" />
+ <text
+ xml:space="preserve"
+ style="font-size:27.62000275px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="1946.3259"
+ y="2435.7"
+ id="text5558"><tspan
+ sodipodi:role="line"
+ id="tspan5560"
+ x="1946.3259"
+ y="2435.7"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:FreeMono;-inkscape-font-specification:FreeMono Bold">3</tspan></text>
+ </g>
+ <g
+ transform="translate(413.633,-206.84535)"
+ id="g5562">
+ <path
+ sodipodi:type="arc"
+ style="fill:#f28888;fill-opacity:1;stroke:#d5f400;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:3, 3;stroke-dashoffset:0;stroke-opacity:1"
+ id="path5564"
+ sodipodi:cx="255.10791"
+ sodipodi:cy="326.69064"
+ sodipodi:rx="38.848923"
+ sodipodi:ry="38.848923"
+ d="M 293.95683,326.69064 A 38.848923,38.848923 0 1 1 216.25899,326.69064 A 38.848923,38.848923 0 1 1 293.95683,326.69064 z"
+ transform="matrix(0.4405339,0,0,0.4405339,1842.2283,2282.9708)" />
+ <text
+ xml:space="preserve"
+ style="font-size:27.62000275px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="1946.3259"
+ y="2435.7"
+ id="text5566"><tspan
+ sodipodi:role="line"
+ id="tspan5568"
+ x="1946.3259"
+ y="2435.7"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:FreeMono;-inkscape-font-specification:FreeMono Bold">4</tspan></text>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/images/boostgenarch.png b/doc/images/boostgenarch.png
new file mode 100644
index 0000000..001b844
--- /dev/null
+++ b/doc/images/boostgenarch.png
Binary files differ
diff --git a/doc/images/boostgenarch.svg b/doc/images/boostgenarch.svg
new file mode 100644
index 0000000..8a5f74b
--- /dev/null
+++ b/doc/images/boostgenarch.svg
@@ -0,0 +1,711 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="1050.42"
+ height="397.94467"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ version="1.0"
+ sodipodi:docname="boostgenarch.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="boostgenarch.png"
+ inkscape:export-xdpi="56.549999"
+ inkscape:export-ydpi="56.549999">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="EmptyDiamondL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="EmptyDiamondL"
+ style="overflow:visible">
+ <path
+ id="path3930"
+ d="M 0,-7.0710768 L -7.0710894,0 L 0,7.0710589 L 7.0710462,0 L 0,-7.0710768 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="scale(0.8,0.8)" />
+ </marker>
+ <marker
+ inkscape:stockid="EmptyTriangleInL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="EmptyTriangleInL"
+ style="overflow:visible">
+ <path
+ id="path3975"
+ d="M 5.77,0 L -2.88,5 L -2.88,-5 L 5.77,0 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,4.8,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Sstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Sstart"
+ style="overflow:visible">
+ <path
+ id="path3835"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(0.2,0,0,0.2,1.2,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend"
+ style="overflow:visible">
+ <path
+ id="path3832"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Tail"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Tail"
+ style="overflow:visible">
+ <g
+ id="g3859"
+ transform="scale(-1.2,-1.2)">
+ <path
+ id="path3861"
+ d="M -3.8048674,-3.9585227 L 0.54352094,0"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3863"
+ d="M -1.2866832,-3.9585227 L 3.0617053,0"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3865"
+ d="M 1.3053582,-3.9585227 L 5.6537466,0"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3867"
+ d="M -3.8048674,4.1775838 L 0.54352094,0.21974226"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3869"
+ d="M -1.2866832,4.1775838 L 3.0617053,0.21974226"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3871"
+ d="M 1.3053582,4.1775838 L 5.6537466,0.21974226"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ </g>
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible">
+ <path
+ id="path3636"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.5155842"
+ inkscape:cx="525.21002"
+ inkscape:cy="198.97234"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1680"
+ inkscape:window-height="973"
+ inkscape:window-x="1280"
+ inkscape:window-y="25"
+ showguides="true"
+ inkscape:guide-bbox="true" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-109.91989,-748.26874)">
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot3229"
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ transform="translate(2.0918751e-6,-6.0000008)"><flowRegion
+ id="flowRegion3231"><rect
+ id="rect3233"
+ width="125.74072"
+ height="40.5849"
+ x="388.45547"
+ y="279.5423" /></flowRegion><flowPara
+ id="flowPara3235" /></flowRoot> <g
+ id="g3406"
+ transform="translate(-2.6095003,-1.3051758e-5)">
+ <rect
+ rx="4.1757755"
+ ry="5.4922562"
+ y="756.909"
+ x="123.11251"
+ height="380.66443"
+ width="470.24225"
+ id="rect3609"
+ style="fill:#e4fae3;fill-opacity:0.65882353;stroke:#8eff89;stroke-width:0.87503546;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ transform="scale(1.0000266,0.9999734)"
+ id="text3601"
+ y="785.98743"
+ x="354.32269"
+ style="font-size:38.71272278px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan3605"
+ style="font-size:27.09890556px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="785.98743"
+ x="354.32269"
+ sodipodi:role="line"><tspan
+ id="tspan2508"
+ style="font-weight:bold">API Extractor</tspan><tspan
+ id="tspan2510"
+ style="font-size:22px"> (Generator Back-End)</tspan></tspan></text>
+ <g
+ transform="matrix(0.9678438,0,0,0.9677923,-160.77317,253.92619)"
+ id="g3709">
+ <rect
+ style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:0.69825613;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2821"
+ width="198.90968"
+ height="93.892342"
+ x="305.2475"
+ y="807.38849"
+ ry="2.6812849"
+ rx="2.1703238" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="405.17499"
+ y="831.81903"
+ id="text3611"><tspan
+ id="tspan3687"
+ sodipodi:role="line"
+ x="405.17499"
+ y="831.81903"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold">TypeDatabase</tspan><tspan
+ id="tspan5641"
+ sodipodi:role="line"
+ x="405.17499"
+ y="853.33856"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">parses typesystem</tspan><tspan
+ id="tspan3689"
+ sodipodi:role="line"
+ x="405.17499"
+ y="873.33856"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">and stores information</tspan></text>
+ </g>
+ <g
+ transform="matrix(0.9678438,0,0,0.9677923,33.530997,29.623658)"
+ id="g3728">
+ <rect
+ style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:0.54871088;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3625"
+ width="117.15066"
+ height="86.355225"
+ x="133.25664"
+ y="809.36938"
+ ry="2.6793056"
+ rx="1.3412292" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="191.58197"
+ y="838.75159"
+ id="text3627"><tspan
+ sodipodi:role="line"
+ x="191.58197"
+ y="838.75159"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ id="tspan3631">Parser</tspan><tspan
+ id="tspan3695"
+ sodipodi:role="line"
+ x="191.58197"
+ y="860.27112"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">parses the</tspan><tspan
+ id="tspan3697"
+ sodipodi:role="line"
+ x="191.58197"
+ y="880.27112"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">lib headers</tspan></text>
+ </g>
+ <g
+ transform="matrix(0.9678438,0,0,0.9677923,67.17479,-62.939246)"
+ id="g3763">
+ <rect
+ style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:0.79775763;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3737"
+ width="244.82956"
+ height="101.59812"
+ x="267.06232"
+ y="905.13727"
+ ry="3.1522403"
+ rx="2.4096873" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="389.39117"
+ y="931.86993"
+ id="text3739"><tspan
+ sodipodi:role="line"
+ x="389.39117"
+ y="931.86993"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ id="tspan3741">ApiExtractor</tspan><tspan
+ id="tspan2523"
+ sodipodi:role="line"
+ x="389.39117"
+ y="953.38947"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">commands the parsing and</tspan><tspan
+ id="tspan2517"
+ sodipodi:role="line"
+ x="389.39117"
+ y="973.38947"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">building of the data model</tspan><tspan
+ id="tspan2519"
+ sodipodi:role="line"
+ x="389.39117"
+ y="993.38947"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">and calls the user generators</tspan></text>
+ </g>
+ <g
+ transform="matrix(0.9678438,0,0,0.9677923,-18.729241,25.76123)"
+ id="g9183">
+ <rect
+ style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:0.70975834;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect9158"
+ width="202.60791"
+ height="83.543121"
+ x="398.08612"
+ y="1051.0632"
+ ry="2.5920558"
+ rx="2.3196087" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="499.39008"
+ y="1078.575"
+ id="text9160"><tspan
+ sodipodi:role="line"
+ x="499.39008"
+ y="1078.575"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ id="tspan9162">Generator</tspan><tspan
+ id="tspan9168"
+ sodipodi:role="line"
+ x="499.39008"
+ y="1100.0945"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">base class for front-end</tspan><tspan
+ id="tspan9176"
+ sodipodi:role="line"
+ x="499.39008"
+ y="1120.0945"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">output classes</tspan></text>
+ </g>
+ <rect
+ rx="4.3700728"
+ ry="5.4919772"
+ y="756.91852"
+ x="603.24152"
+ height="380.64514"
+ width="549.11475"
+ id="rect9190"
+ style="fill:#cbe990;fill-opacity:0.51184836;stroke:#6ca400;stroke-width:0.89513886;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ transform="scale(1.0000266,0.9999734)"
+ id="text9192"
+ y="785.98743"
+ x="907.21234"
+ style="font-size:38.71272278px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan9194"
+ style="font-size:27.09890556px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="785.98743"
+ x="907.21234"
+ sodipodi:role="line"><tspan
+ id="tspan2512"
+ style="font-weight:bold">boostpythongenerator</tspan><tspan
+ id="tspan2514"
+ style="font-size:22px"> (Front-End)</tspan></tspan></text>
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path9241"
+ d="M 563.24815,1086.3017 L 756.17483,1086.2141"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#EmptyTriangleInL);stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ <g
+ transform="matrix(0.9678438,0,0,0.9677923,-53.053078,32.316629)"
+ id="g9234">
+ <rect
+ style="fill:#addc52;fill-opacity:1;stroke:#6ca400;stroke-width:0.73640609;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect9206"
+ width="218.17299"
+ height="83.517967"
+ x="694.6994"
+ y="1044.8701"
+ ry="2.5912752"
+ rx="2.4978092" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="803.78589"
+ y="1072.3693"
+ id="text9208"><tspan
+ sodipodi:role="line"
+ x="803.78589"
+ y="1072.3693"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ id="tspan9210">BoostGenerator</tspan><tspan
+ id="tspan9218"
+ sodipodi:role="line"
+ x="803.78589"
+ y="1093.8888"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">common functionality</tspan><tspan
+ id="tspan9222"
+ sodipodi:role="line"
+ x="803.78589"
+ y="1113.8888"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">for all generators</tspan></text>
+ </g>
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path9873"
+ d="M 520.90636,976.05583 L 540.21434,975.96825"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path9875"
+ d="M 540.21912,918.88309 L 540.30671,975.90002"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#EmptyDiamondL);stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ <g
+ transform="matrix(0.9678438,0,0,0.9677923,-69.696202,32.316631)"
+ id="g11669">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.03325212;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 1238.687,822.30296 L 1238.7775,1044.4792"
+ id="path11089"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.03325212;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 654.1163,822.6964 L 1238.9792,822.6059"
+ id="path11656"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.97947711;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 1204.3853,823.2094 L 1204.359,950.47279"
+ id="path11658"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.97947711;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 1057.8933,822.98518 L 1057.867,857.1068"
+ id="path11660"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ </g>
+ <g
+ transform="matrix(0.9678438,0,0,0.9677923,-69.696202,32.316631)"
+ id="g11664">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.03325212;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#EmptyTriangleInL);stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 927.80296,1086.6352 L 998.0099,1086.5447"
+ id="path11083"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.03325212;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 948.33557,992.88246 L 977.67216,992.79196"
+ id="path11654"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99674439;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 947.88456,937.33484 L 948.0104,1086.0336"
+ id="path11662"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ </g>
+ <g
+ transform="matrix(0.9678438,0,0,0.9677923,-94.860111,47.801308)"
+ id="g10490">
+ <rect
+ style="fill:#addc52;fill-opacity:1;stroke:#6ca400;stroke-width:0.79788101;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect10463"
+ width="256.302"
+ height="83.458473"
+ x="991.64471"
+ y="935.10797"
+ ry="2.5894294"
+ rx="2.9343388" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="1119.7955"
+ y="962.57739"
+ id="text10465"><tspan
+ sodipodi:role="line"
+ x="1119.7955"
+ y="962.57739"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ id="tspan10467">CppGenerator</tspan><tspan
+ id="tspan10469"
+ sodipodi:role="line"
+ x="1119.7955"
+ y="984.09692"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">writes main body of code</tspan><tspan
+ id="tspan10471"
+ sodipodi:role="line"
+ x="1119.7955"
+ y="1004.0969"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">for the binding classes</tspan></text>
+ </g>
+ <g
+ transform="matrix(0.9678438,0,0,0.9677923,-70.620184,48.023961)"
+ id="g10483">
+ <rect
+ style="fill:#addc52;fill-opacity:1;stroke:#6ca400;stroke-width:0.79788101;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect10473"
+ width="256.302"
+ height="83.458473"
+ x="992.59943"
+ y="1028.6698"
+ ry="2.5894294"
+ rx="2.9343388" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="1120.7501"
+ y="1056.1392"
+ id="text10475"><tspan
+ sodipodi:role="line"
+ x="1120.7501"
+ y="1056.1392"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ id="tspan10477">ConverterGenerator</tspan><tspan
+ id="tspan10481"
+ sodipodi:role="line"
+ x="1120.7501"
+ y="1077.6587"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">writes converters for classes</tspan><tspan
+ id="tspan10508"
+ sodipodi:role="line"
+ x="1120.7501"
+ y="1097.6587"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">with Python equivalents</tspan></text>
+ </g>
+ <g
+ transform="matrix(0.9678438,0,0,0.9677923,-128.77856,45.865724)"
+ id="g10497">
+ <rect
+ style="fill:#addc52;fill-opacity:1;stroke:#6ca400;stroke-width:0.79788101;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect10444"
+ width="256.302"
+ height="83.458473"
+ x="990.69006"
+ y="843.45557"
+ ry="2.5894294"
+ rx="2.9343388" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="1118.8409"
+ y="870.92499"
+ id="text10446"><tspan
+ sodipodi:role="line"
+ x="1118.8409"
+ y="870.92499"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ id="tspan10448">HppGenerator</tspan><tspan
+ id="tspan10452"
+ sodipodi:role="line"
+ x="1118.8409"
+ y="892.44452"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">writes headers for the</tspan><tspan
+ id="tspan10456"
+ sodipodi:role="line"
+ x="1118.8409"
+ y="912.44452"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">binding classes</tspan></text>
+ </g>
+ <g
+ transform="matrix(0.7300473,0,0,0.7300085,224.93105,280.6603)"
+ id="g2762">
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path2758"
+ d="M 1238.8766,1044.0556 L 1249.4796,1031.9824"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.36981082;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path2760"
+ d="M 1238.6833,1044.0962 L 1228.0803,1032.023"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.36981082;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ </g>
+ <g
+ transform="matrix(0.7300473,0,0,0.7300085,191.62705,189.94594)"
+ id="g2766">
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path2768"
+ d="M 1238.8766,1044.0556 L 1249.4796,1031.9824"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.36981082;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path2770"
+ d="M 1238.6833,1044.0962 L 1228.0803,1032.023"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.36981082;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ </g>
+ <g
+ transform="matrix(0.7300473,0,0,0.7300085,49.80626,99.273761)"
+ id="g2772">
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path2774"
+ d="M 1238.8766,1044.0556 L 1249.4796,1031.9824"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.36981082;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path2776"
+ d="M 1238.6833,1044.0962 L 1228.0803,1032.023"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.36981082;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ </g>
+ <g
+ transform="translate(-5.7111906,0)"
+ id="g3397">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;marker-start:none;stroke-opacity:1;display:inline"
+ d="M 234.14728,897.65591 L 234.08039,1034.5389"
+ id="path3685"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <g
+ id="g3385"
+ transform="translate(-19.531521,268.55504)">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 253.61706,628.77816 L 249.34863,640.58185"
+ id="path2799"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 253.67366,628.77816 L 257.94209,640.58185"
+ id="path2559"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ </g>
+ <g
+ id="g3391"
+ transform="matrix(1,0,0,-1,-19.531521,1663.0776)">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 253.61706,628.77816 L 249.34863,640.58185"
+ id="path3393"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 253.67366,628.77816 L 257.94209,640.58185"
+ id="path3395"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ </g>
+ </g>
+ <g
+ transform="matrix(0.9678438,0,0,0.9677923,-92.060029,-109.98534)"
+ id="g3809">
+ <rect
+ style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:1.00168562;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3785"
+ width="332.48172"
+ height="82.830231"
+ x="302.83319"
+ y="1068.9153"
+ ry="3.1461167"
+ rx="3.8065021" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="469.03497"
+ y="1095.5493"
+ id="text3787"><tspan
+ id="tspan3791"
+ sodipodi:role="line"
+ x="469.03497"
+ y="1095.5493"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold">AbstractMetaBuilder</tspan><tspan
+ sodipodi:role="line"
+ x="469.03497"
+ y="1117.0688"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ id="tspan3807">builds the data model with information</tspan><tspan
+ id="tspan2545"
+ sodipodi:role="line"
+ x="469.03497"
+ y="1137.0688"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">from headers and binding directives</tspan><tspan
+ id="tspan3795"
+ sodipodi:role="line"
+ x="469.03497"
+ y="1157.0688"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans" /></text>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/images/boostqtarch.png b/doc/images/boostqtarch.png
new file mode 100644
index 0000000..a82f970
--- /dev/null
+++ b/doc/images/boostqtarch.png
Binary files differ
diff --git a/doc/images/boostqtarch.svg b/doc/images/boostqtarch.svg
new file mode 100644
index 0000000..9fbb382
--- /dev/null
+++ b/doc/images/boostqtarch.svg
@@ -0,0 +1,226 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="350"
+ height="220"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ version="1.0"
+ sodipodi:docname="boostqtarch.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="boostqtarch.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible">
+ <path
+ id="path3636"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.4812981"
+ inkscape:cx="145.70936"
+ inkscape:cy="94.089827"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1278"
+ inkscape:window-height="951"
+ inkscape:window-x="1592"
+ inkscape:window-y="29"
+ showguides="true"
+ inkscape:guide-bbox="true" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-61.076804,-301.50489)">
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot3229"
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ transform="translate(2.0918751e-6,-6.0000008)"><flowRegion
+ id="flowRegion3231"><rect
+ id="rect3233"
+ width="125.74072"
+ height="40.5849"
+ x="388.45547"
+ y="279.5423" /></flowRegion><flowPara
+ id="flowPara3235" /></flowRoot> <g
+ id="g3010"
+ transform="matrix(0.9508755,0,0,0.9508755,11.317746,20.273572)">
+ <g
+ transform="translate(0,-9.7919846e-6)"
+ id="g2952">
+ <rect
+ style="fill:#dfe994;fill-opacity:1;stroke:#d5f400;stroke-width:0.7162478;stroke-opacity:1"
+ id="rect3166"
+ width="349.23203"
+ height="67.403336"
+ x="61.417336"
+ y="377.74161"
+ ry="2.6752985"
+ rx="2.285728" />
+ <text
+ xml:space="preserve"
+ style="font-size:29.38717079px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#4c5800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="236.08904"
+ y="397.98755"
+ id="text3168"><tspan
+ sodipodi:role="line"
+ x="236.08904"
+ y="397.98755"
+ style="font-size:20.57102013px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#4c5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ id="tspan3176">Boost::Python</tspan><tspan
+ sodipodi:role="line"
+ x="236.08904"
+ y="418.35535"
+ style="font-size:15.20761585px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#4c5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ id="tspan2880">helper library to interface with CPython API</tspan><tspan
+ id="tspan2922"
+ sodipodi:role="line"
+ x="236.08904"
+ y="437.36487"
+ style="font-size:15.20761585px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#4c5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">and expose C++ entities to Python</tspan></text>
+ </g>
+ <g
+ transform="translate(0,-9.7025776e-6)"
+ id="g2959">
+ <rect
+ style="fill:#addc52;fill-opacity:1;stroke:#6ca400;stroke-width:0.71624762;stroke-opacity:1"
+ id="rect3542"
+ width="349.23203"
+ height="67.403351"
+ x="61.417336"
+ y="301.84543"
+ ry="2.675298"
+ rx="2.285728" />
+ <text
+ xml:space="preserve"
+ style="font-size:29.38717079px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="236.5123"
+ y="322.09137"
+ id="text3544"><tspan
+ id="tspan3596"
+ sodipodi:role="line"
+ x="236.5123"
+ y="322.09137"
+ style="font-size:20.57102013px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">Qt-Python Bindings</tspan><tspan
+ sodipodi:role="line"
+ x="236.5123"
+ y="342.45917"
+ style="font-size:15.20761585px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ id="tspan12937">Qt classes and functions</tspan><tspan
+ sodipodi:role="line"
+ x="236.5123"
+ y="361.46869"
+ style="font-size:15.20761585px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ id="tspan2411">exported to Python</tspan></text>
+ </g>
+ <g
+ id="g2998">
+ <g
+ id="g2986">
+ <rect
+ rx="2.285728"
+ ry="2.675298"
+ y="453.63776"
+ x="61.417336"
+ height="67.403336"
+ width="172.02341"
+ id="rect3485"
+ style="fill:#b2e994;fill-opacity:1;stroke:#56f400;stroke-width:0.71624762;stroke-opacity:1" />
+ <text
+ id="text3487"
+ y="482.29712"
+ x="147.73038"
+ style="font-size:29.38717079px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#1f5800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ style="font-size:20.57102013px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#1f5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="482.29712"
+ x="147.73038"
+ sodipodi:role="line"
+ id="tspan3499">CPython</tspan><tspan
+ id="tspan2509"
+ style="font-size:20.57102013px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#1f5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="508.01089"
+ x="147.73038"
+ sodipodi:role="line">API</tspan></text>
+ </g>
+ <g
+ id="g2992">
+ <rect
+ rx="2.285728"
+ ry="2.675298"
+ y="453.63776"
+ x="239.30101"
+ height="67.403351"
+ width="172.02295"
+ id="rect2459"
+ style="fill:#cce994;fill-opacity:1;stroke:#a1f400;stroke-width:0.71624762;stroke-opacity:1" />
+ <text
+ id="text2461"
+ y="481.97067"
+ x="324.86047"
+ style="font-size:29.38717079px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#3a5800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ style="font-size:20.57102013px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#3a5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="481.97067"
+ x="324.86047"
+ sodipodi:role="line"
+ id="tspan2467">Qt4</tspan><tspan
+ id="tspan2490"
+ style="font-size:20.57102013px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#3a5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="507.68445"
+ x="324.86047"
+ sodipodi:role="line">Libraries</tspan></text>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/overview.rst b/doc/overview.rst
new file mode 100644
index 0000000..1220197
--- /dev/null
+++ b/doc/overview.rst
@@ -0,0 +1,46 @@
+.. _gen-overview:
+
+******************
+Generator Overview
+******************
+
+In a few words, the Generator is a utility that parses a collecion of header and
+typesystem files, generating other files (code, documentation, etc.) as result.
+
+Creating new bindings
+=====================
+
+.. figure:: images/bindinggen-development.png
+ :scale: 80
+ :align: center
+
+ Creating new bindings
+
+Each module of the generator system has an specific role.
+
+1. Provide enough data about the classes and functions.
+2. Generate valid code, with modifications from typesystems and injected codes.
+3. Modify the API to expose the objects in a Python-friendly way.
+4. Insert customizations where handwritten code is needed.
+
+.. figure:: images/boostqtarch.png
+ :scale: 80
+ :align: center
+
+ Runtime architecture
+
+The newly created binding will run on top of Boost.Python library which takes
+care of interfacing Python and the underlying C++ library.
+
+Handwritten inputs
+==================
+
+Creating new bindings involves creating two pieces of "code": the typesystem and
+the inject code.
+
+:typesystem: XML files that provides the developer with a tool to customize the
+ way that the generators will see the classes and functions. For
+ example, functions can be renamed, have its signature changed and
+ many other actions.
+:inject code: allows the developer to insert handwritten code where the generated
+ code is not suitable or needs some customization.
diff --git a/doc/tutorial/bindinglibfoo.rst b/doc/tutorial/bindinglibfoo.rst
new file mode 100644
index 0000000..87b7e48
--- /dev/null
+++ b/doc/tutorial/bindinglibfoo.rst
@@ -0,0 +1,77 @@
+.. highlight:: xml
+
+.. _gentut-bindinglibfoo:
+
+Binding libfoo with the Generator
+=================================
+
+In order to create bindings for a library based on Qt4 a number of components
+must be available on the system.
+
+ + Qt4 library (with headers and pkg-config .pc files for development -- the
+ ``-dev`` packages in a Debian distribution).
+ + Qt4 Python bindings made with :program:`boostpythongenerator`.
+ + Typesystems for the Qt4 Python bindings.
+ + Headers for the library to be bound.
+
+With the items listed above the developer must write the components from
+where the generator will gather information to create the binding source code.
+
+ + Typesystem file describing the way the binding must be done.
+ + **global.h** including all the **libfoo** headers and defining required macros.
+ + A build system to direct the process of generating, compiling and linking the
+ binding.
+
+The directory structure for the binding project could be something like the tree
+shown below:
+
+::
+
+ foobinding/
+ |-- data/
+ `-- module_dir/
+ `-- glue/
+
+
+The **data** directory should contain the **global.h** and the typesystem
+file. This typesystem need to refer to the ones used to create the Qt4 bindings,
+commonly located on **/usr/share/PySide/typesystem**, the exact location
+can be checked with pkg-config:
+
+::
+
+ $ pkg-config pyside --variable=typesystemdir
+
+
+The **module_dir** directory is the place where the sources generated should
+be placed. It starts empty except for the build instructions file (Makefile,
+Makefile.am, CMakeLists.txt, etc). The realname of this directory must be the
+same written in the typesystem file:
+
+::
+
+ <typesystem package="module_dir">
+
+
+If there is any need for handwritten source code longer than a couple of lines,
+making them unconfortable to be put on the typesystem xml file, the sources
+could be orderly placed in a **glue** directory, also referred in the
+new binding typesystem.
+
+When writing the typesystem file (more on this later) there is no need to refer
+to the other required typesystem files with absolute paths, the locations where
+they can be found could be passed to the generator through a command line
+option (``--typesystem-paths=PATH1:PATH2:[...]``) or the environment variable
+**TYPESYSTEMPATH**.
+
+For **libfoo** no glue code will be needed so this directory is not used,
+the other directories are created with proper names.
+
+::
+
+ foobinding/
+ |-- data/global.h
+ | `-- typesystem_foo.xml
+ `-- foo/
+ `-- Makefile
+
diff --git a/doc/tutorial/buildingthebinding.rst b/doc/tutorial/buildingthebinding.rst
new file mode 100644
index 0000000..b5bec28
--- /dev/null
+++ b/doc/tutorial/buildingthebinding.rst
@@ -0,0 +1,132 @@
+.. _gentut-buildingthebinding:
+
+Building The Binding
+====================
+
+As mentioned before the build system used must perform the following tasks
+in the correct order:
+
+ + Gather data about locations of headers and external needed typesystems.
+ + Run the generator with the correct parameters.
+ + Compile and link the binding.
+
+The first and last are the usual, being the second the only novelty in the
+process.
+
+Running the Generator
+---------------------
+
+The generator is called with the following parameters and options:
+
+::
+
+ $ boostpythongenerator global_headers.h \
+ --include-paths=$(PATHS_TO_HEADERS)) \
+ --typesystem-paths=$(PATHS_TO_TYPESYSTEMS) \
+ --output-directory=. \
+ typesystem.xml
+
+Notice that the variables for include and typesystem paths could be determined
+at build time with the pkg-config tool.
+
+Collecting information with pkg-config
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The Qt4 bindings include compile and build information through the pkg-config
+mechanism. The pkg-config name for Qt4 Python bindings is **pyside** and a
+simple ``pkg-config pyside --cflags --libs`` will retrieve the information
+needed to build the new binding.
+
+The Qt4 bindings file ``pyside.pc`` for the use of pkg-config requires
+the ``.pc`` files from Qt4 to be installed. If the library is in an unusual
+location, e.g. ``/opt/qt45``, remember to export it to the ``PKG_CONFIG_PATH``
+environment variable.
+For example: ``export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/opt/qt45/lib/pkgconfig``
+
+There is a vital information also available through pkg-config:
+the **typesystemdir** variable. It is used like this:
+``pkg-config pyside --variable=typesystemdir`` This provides information
+where to find the typesystem files used to create the Qt4 bindings, and as said
+before the binding being created needs this to complement its own binding
+information for the generation proccess.
+
+Makefile
+--------
+
+Below is a plain Makefile for the binding project.
+
+**foobinding/foo/Makefile**
+::
+
+ LIBFOO_DIR = ../../libfoo
+ LIBS = -lboost_python `python-config --libs` \
+ `pkg-config pyside --libs` \
+ -lfoo -L$(LIBFOO_DIR) \
+ -lpthread -ldl -lutil
+ CXXFLAGS = -I/usr/share/qt4/mkspecs/linux-g++ -I. \
+ -I$(LIBFOO_DIR) \
+ `pkg-config pyside --cflags` \
+ -I`python-config --includes` \
+ -I/usr/include/boost/python
+ QT4TYPESYSTEM_DIR = `pkg-config --variable=typesystemdir pyside`
+ QT4HEADER_DIRS = `pkg-config --variable=includedir QtCore`:`pkg-config --variable=includedir QtCore`/..
+
+ SOURCES = foo_globals_wrapper.cpp foo_module_wrapper.cpp math_wrapper.cpp
+ OBJECTS = foo_globals_wrapper.o foo_module_wrapper.o math_wrapper.o
+
+ all: generate compile link
+
+ generate:
+ boostpythongenerator ../data/global.h \
+ --include-paths=$(LIBFOO_DIR):$(QT4HEADER_DIRS):/usr/include \
+ --typesystem-paths=../data:$(QT4TYPESYSTEM_DIR) \
+ --output-directory=.. \
+ ../data/typesystem_foo.xml
+
+ compile: $(SOURCES)
+ g++ -Wall -fPIC -DPIC $(CXXFLAGS) -c foo_globals_wrapper.cpp
+ g++ -Wall -fPIC -DPIC $(CXXFLAGS) -c foo_module_wrapper.cpp
+ g++ -Wall -fPIC -DPIC $(CXXFLAGS) -c math_wrapper.cpp
+
+ link:
+ g++ -shared -Wl,-soname,foo.so -o foo.so $(LIBS) $(OBJECTS)
+
+ test:
+ LD_LIBRARY_PATH=$(LIBFOO_DIR):$LD_LIBRARY_PATH python -c \
+ "import PySide.QtCore; import foo; print dir(foo); m = foo.Math(); print \"5 squared is %d\" % m.squared(5)"
+
+ clean:
+ rm -rf *.o *.so *.?pp *.log
+
+
+Keep in mind that the Makefile above expects the ``libfoo`` and
+``foobinding`` directories to be in the same level in the directory
+hierarchy, remember to change any path references accordingly if
+you choose to change things.
+
+**Warning:**
+ The order in which the link flags are passed matters.
+ **libboost_python** must come first, otherwise weeping
+ and gnashing of teeth will follow.
+
+Testing the Binding
+-------------------
+Now compile the binding with ``make``:
+
+::
+
+ $ cd foobinding/foo
+ $ make
+
+To test if the new binding is working (it can pass the build phase but still
+blow up at runtime) start up a Python terminal and import it by the name.
+
+::
+
+ $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/libfoo/shared/object/dir
+ $ export PYTHONPATH=$PYTHONPATH:/path/to/foo/python/module/file/dir
+ $ python
+ >> import foo
+ >> print dir(foo)
+ >> m = foo.Math()
+ >> print m.squared(5)
diff --git a/doc/tutorial/globalheader.rst b/doc/tutorial/globalheader.rst
new file mode 100644
index 0000000..d1ac239
--- /dev/null
+++ b/doc/tutorial/globalheader.rst
@@ -0,0 +1,36 @@
+.. highlight:: cpp
+
+.. _gentut-globalheader:
+
+The Global Header
+=================
+
+Besides the information provided by the typesystem, the generator needs to
+gather more data from the library headers containing the classes to be exposed
+in Python. If there is a header that include all the others (or just one, as is
+the case of **libfoo**) this could be passed directly to the generator.
+
+If such a file is not available, or only a subset of the library is desired, or
+if some flags must be defined before parsing the library headers, then a
+``global.h`` file must be provided.
+
+The use of a ``global.h`` file is preferred if some macros must be defined
+before the parser gather data from the headers. For example, if ``NULL`` is not
+defined and it is used as a default paramater for some constructor or method,
+the parser will not recognize it.
+
+The solve this create a ``global.h`` including all the desired headers and the
+defined (and undefined) flags as follows:
+
+**foobinding/data/global.h**
+::
+
+ #undef QT_NO_STL
+ #undef QT_NO_STL_WCHAR
+
+ #ifndef NULL
+ #define NULL 0
+ #endif
+
+ #include <foo.h>
+
diff --git a/doc/tutorial/images/generatorworkings.png b/doc/tutorial/images/generatorworkings.png
new file mode 100644
index 0000000..d35a565
--- /dev/null
+++ b/doc/tutorial/images/generatorworkings.png
Binary files differ
diff --git a/doc/tutorial/images/generatorworkings.svg b/doc/tutorial/images/generatorworkings.svg
new file mode 100644
index 0000000..85a7782
--- /dev/null
+++ b/doc/tutorial/images/generatorworkings.svg
@@ -0,0 +1,392 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="680"
+ height="280"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="generatorworkings.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="generatorworkings.png"
+ inkscape:export-xdpi="86.970001"
+ inkscape:export-ydpi="86.970001"
+ version="1.0">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path4293"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(0.8,0,0,0.8,10,0)" />
+ </marker>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3235">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop3237" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop3239" />
+ </linearGradient>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lend"
+ style="overflow:visible">
+ <path
+ id="path3282"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="6.1230318e-14 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3235"
+ id="linearGradient3241"
+ x1="-29.816929"
+ y1="320.97046"
+ x2="191.17912"
+ y2="322.7244"
+ gradientUnits="userSpaceOnUse" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.4420481"
+ inkscape:cx="361.95624"
+ inkscape:cy="122.34225"
+ inkscape:document-units="px"
+ inkscape:current-layer="g3297"
+ showgrid="false"
+ inkscape:window-width="1279"
+ inkscape:window-height="944"
+ inkscape:window-x="391"
+ inkscape:window-y="38"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <sodipodi:guide
+ orientation="1,0"
+ position="-228.99296,-21.575354"
+ id="guide3165" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(291.86879,-366.35864)">
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="324.86121"
+ y="308.08389"
+ id="text3395"
+ transform="translate(-28.960129,110.67739)"><tspan
+ sodipodi:role="line"
+ id="tspan3397"
+ x="324.86121"
+ y="308.08389" /></text>
+ <g
+ id="g3254">
+ <g
+ id="g3297"
+ transform="translate(15,11.795533)">
+ <rect
+ style="fill:#e4fae3;fill-opacity:0.65882353;stroke:#8eff89;stroke-width:0.52055138;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3609"
+ width="323.15158"
+ height="216.66933"
+ x="-151.9006"
+ y="364.42294"
+ ry="7.354454"
+ rx="5.3701153" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1;display:inline"
+ d="M 195.16416,473.16835 L 149.88745,473.08346"
+ id="path3285"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc"
+ inkscape:connection-start="#g3276" />
+ <g
+ id="g3276"
+ transform="translate(-47.379381,-25.682818)">
+ <rect
+ ry="11.816782"
+ rx="12.0209"
+ y="462.87637"
+ x="242.78513"
+ height="72.257683"
+ width="163.85461"
+ id="rect2461"
+ style="fill:#9dcdf9;fill-opacity:1;stroke:#0084ff;stroke-width:0.48317167;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ id="text2463"
+ y="494.80786"
+ x="324.45514"
+ style="font-size:144px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ style="font-size:22px;text-align:center;text-anchor:middle"
+ y="494.80786"
+ x="324.45514"
+ id="tspan2465"
+ sodipodi:role="line">binding</tspan><tspan
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;font-family:FreeMono;-inkscape-font-specification:FreeMono"
+ y="519.56543"
+ x="324.45514"
+ sodipodi:role="line"
+ id="tspan3018">source code</tspan></text>
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1;display:inline"
+ d="M -130.41272,567.21015 L -180.20217,584.91297"
+ id="path3054"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1;display:inline"
+ d="M -129.57075,528.12072 L -181.18287,504.96225"
+ id="path3056"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <g
+ id="g3147"
+ transform="translate(74.301071,9.8268847)">
+ <g
+ transform="translate(62.764666,-13.729771)"
+ id="g2986">
+ <rect
+ style="fill:#fafcc5;fill-opacity:1;stroke:#f9ff00;stroke-width:0.3511245;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2970"
+ width="115.38314"
+ height="55.650036"
+ x="-430.1297"
+ y="481.9653"
+ rx="11.184198"
+ ry="13.895926" />
+ <text
+ xml:space="preserve"
+ style="font-size:144px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-371.96939"
+ y="505.29422"
+ id="text2972"><tspan
+ id="tspan2976"
+ sodipodi:role="line"
+ x="-371.96939"
+ y="505.29422"
+ style="font-size:16px;text-align:center;text-anchor:middle">typesystem</tspan><tspan
+ id="tspan2980"
+ sodipodi:role="line"
+ x="-371.96939"
+ y="525.29419"
+ style="font-size:16px;text-align:center;text-anchor:middle">descriptions</tspan></text>
+ </g>
+ <g
+ transform="translate(74.533053,61.297656)"
+ id="g3020">
+ <rect
+ style="fill:#fafcc5;fill-opacity:1;stroke:#f9ff00;stroke-width:0.36426121;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3022"
+ width="91.833252"
+ height="75.250854"
+ x="-418.35477"
+ y="472.16489"
+ rx="9.1466599"
+ ry="12.17058" />
+ <text
+ xml:space="preserve"
+ style="font-size:144px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-372.64865"
+ y="494.13867"
+ id="text3024"><tspan
+ id="tspan3026"
+ sodipodi:role="line"
+ x="-372.64865"
+ y="494.13867"
+ style="font-size:16px;text-align:center;text-anchor:middle">custom</tspan><tspan
+ id="tspan3028"
+ sodipodi:role="line"
+ x="-372.64865"
+ y="513.88837"
+ style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;font-family:FreeMono;-inkscape-font-specification:FreeMono">source</tspan><tspan
+ id="tspan3030"
+ sodipodi:role="line"
+ x="-372.64865"
+ y="536.38837"
+ style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;font-family:FreeMono;-inkscape-font-specification:FreeMono">code</tspan></text>
+ </g>
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1;display:inline"
+ d="M -40.946515,396.85213 L -179.16818,396.16834"
+ id="path3098"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <g
+ id="g3141"
+ transform="translate(66.255107,-6.2939423)">
+ <rect
+ ry="11.897643"
+ rx="9.5758715"
+ y="381.30014"
+ x="-342.70132"
+ height="47.647366"
+ width="98.790642"
+ id="rect2415"
+ style="fill:#fafcc5;fill-opacity:1;stroke:#f9ff00;stroke-width:0.30063155;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ id="text2417"
+ y="401.08865"
+ x="-293.63803"
+ style="font-size:144px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ style="font-size:16px;text-align:center;text-anchor:middle"
+ y="401.08865"
+ x="-293.63803"
+ id="tspan2419"
+ sodipodi:role="line">library</tspan><tspan
+ style="font-size:16px;text-align:center;text-anchor:middle"
+ y="421.08865"
+ x="-293.63803"
+ sodipodi:role="line"
+ id="tspan2949">headers</tspan></text>
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1;display:inline"
+ d="M 33.165609,503.00316 L 32.819729,546.19947"
+ id="path3167"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1;display:inline"
+ d="M 33.145722,443.9261 L 32.799842,391.41316"
+ id="path3169"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <g
+ id="g2944"
+ transform="translate(85.554958,3.1233551)">
+ <rect
+ rx="6.8840375"
+ ry="10.365664"
+ y="371.05527"
+ x="-125.40932"
+ height="44.903805"
+ width="101.06483"
+ id="rect3625"
+ style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:0.36750945;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ transform="scale(1.0000266,0.9999734)"
+ id="text3627"
+ y="401.12787"
+ x="-75.810593"
+ style="font-size:38.71272278px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ style="font-size:21.29199791px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ y="401.12787"
+ x="-75.810593"
+ sodipodi:role="line"
+ id="tspan3697">Parser</tspan></text>
+ </g>
+ <g
+ id="g3093"
+ transform="translate(-22.960524,10.08797)">
+ <rect
+ ry="8.5151205"
+ rx="9.4630651"
+ y="433.92093"
+ x="9.3588104"
+ height="58.626995"
+ width="163.91852"
+ id="rect2446"
+ style="fill:#b2d7b5;fill-opacity:1;stroke:#34ff34;stroke-width:0.20534486;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.69008268" />
+ <text
+ id="text2448"
+ y="457.49274"
+ x="90.813187"
+ style="font-size:144px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ style="font-size:22px;font-weight:bold;text-align:center;text-anchor:middle"
+ y="457.49274"
+ x="90.813187"
+ id="tspan2450"
+ sodipodi:role="line">Generator</tspan><tspan
+ style="font-size:22px;font-weight:bold;text-align:center;text-anchor:middle"
+ y="484.99274"
+ x="90.813187"
+ sodipodi:role="line"
+ id="tspan3340">Backend</tspan></text>
+ </g>
+ <g
+ id="g3160"
+ transform="translate(94.301071,19.633862)">
+ <rect
+ rx="5.7330456"
+ ry="8.3964748"
+ y="506.2883"
+ x="-225.62247"
+ height="44.764942"
+ width="192.46243"
+ id="rect2933"
+ style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:0.50637114;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ transform="scale(1.0000266,0.9999734)"
+ id="text2935"
+ y="534.47565"
+ x="-128.93036"
+ style="font-size:38.71272278px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ style="font-size:21.29199791px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ y="534.47565"
+ x="-128.93036"
+ sodipodi:role="line"
+ id="tspan2937">TypeDatabase</tspan></text>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/tutorial/introduction.rst b/doc/tutorial/introduction.rst
new file mode 100644
index 0000000..62372af
--- /dev/null
+++ b/doc/tutorial/introduction.rst
@@ -0,0 +1,32 @@
+Binding Generation Tutorial
+***************************
+
+This tutorial intends to describe the process of binding creation with
+BoostPythonGenerator and using a very simple Qt4 based library will be used as an
+example.
+
+The image below shows the inputs needed to generate the binding source code.
+
+.. image:: images/generatorworkings.png
+
+Putting in words, the user provides the headers for the library along with a
+typesystem file describing how the classes will be exposed in the target
+language, as well as any needed custom source code to be merged with
+the generated source code.
+
+This tutorial will go through the steps needed to have the binding
+being able to be imported and used from a Python program. The tutorial
+source code is available as a tar ball `here <../_static/bindingexample.tar.bz2>`_.
+
+**NOTE:** the binding generator is intended to be used with Qt4 based libraries
+only, at least for the time being.
+
+.. toctree::
+ :maxdepth: 3
+
+ libfoo
+ bindinglibfoo
+ typesystemcreation
+ globalheader
+ buildingthebinding
+
diff --git a/doc/tutorial/libfoo.rst b/doc/tutorial/libfoo.rst
new file mode 100644
index 0000000..7624657
--- /dev/null
+++ b/doc/tutorial/libfoo.rst
@@ -0,0 +1,68 @@
+.. highlight:: cpp
+
+.. _gentut-libfoo:
+
+Creating the foo library
+=========================
+
+In this section it will be presented the code and the build instructions for a
+very simple Qt4 based library. It will be used as the subject for this tutorial.
+
+The Source Code
+---------------
+
+There is only one class on this foo library plus a ``.pro`` file which means
+that the build system used will be Trolltech's **qmake**.
+
+Put the files below in a directory called **libfoo**. Be aware that this
+directory will be refered by the binding Makefile presented in a next section
+of this tutorial. If you want to use other names or paths change the binding
+Makefile accordingly. Blind copy'n'paste shortens your life.
+
+**libfoo/foo.h**
+::
+
+ #ifndef FOO_H
+ #define FOO_H
+
+ #include <QtCore/QtCore>
+
+ class Math : public QObject
+ {
+ Q_OBJECT
+ public:
+ Math() {}
+ virtual ~Math() {}
+ int squared(int x);
+ };
+ #endif // FOO_H
+
+
+**libfoo/foo.cpp**
+::
+
+ #include "foo.h"
+
+ int Math::squared(int x)
+ {
+ return x * x;
+ }
+
+
+**libfoo/foo.pro**
+::
+
+ TEMPLATE = lib
+ TARGET = foo
+ DEPENDPATH += .
+ INCLUDEPATH += .
+ HEADERS += foo.h
+ SOURCES += foo.cpp
+
+To build the lib:
+
+::
+
+ $ cd libfoo
+ $ qmake
+ $ make
diff --git a/doc/tutorial/typesystemcreation.rst b/doc/tutorial/typesystemcreation.rst
new file mode 100644
index 0000000..ae33ccb
--- /dev/null
+++ b/doc/tutorial/typesystemcreation.rst
@@ -0,0 +1,135 @@
+.. highlight:: xml
+
+.. _gentut-typesystem:
+
+Creating the Typesystem Description
+===================================
+
+The typesystem is an specification used when mapping a C++ based library onto a
+corresponding Python module. The specification is a handwritten XML document
+listing the types that will be available in the generated binding, alterations
+to classes and function signatures to better suit the target language,
+and listing the components that should be rejected for the binding.
+
+**PySide** uses a typesystem format similar to the ones used by **QtJambi** and
+**QtScript**, thoroughly described in the page *"The Qt Jambi Type System"*. [#]_
+
+The divergences between **PySide** and QtScript/QtJambi typesystems will be
+highlighted whenever they appear. Things to be aware of when writing
+a typesystem will be also mentioned.
+
+Describing **libfoo** for Python Audiences
+------------------------------------------
+
+All typesystem files start with the root ``typesystem`` tag. The
+``package`` attribute carries the name of the package as it will be seen
+from Python.
+
+Right after that, all the typesystem files providing information required for
+the generation process are included in the same fashion as header files in C.
+
+**foobinding/data/typesystem_foo.xml**
+::
+
+ <?xml version="1.0"?>
+ <typesystem package="foo">
+ <load-typesystem name="typesystem_core.xml" generate="no"/>
+ <object-type name="Math"/>
+ </typesystem>
+
+
+The inclusion of other typesystem files is achieved with the
+``load-typesystem`` tag. The ``generate`` attribute must be set to ``"no"``
+otherwise the generator will try to create more source code for the already
+existing bindings included for reference.
+
+The C++ classes derived from **QObject** intended to be exposed in the target
+language are described with ``object-type`` tags.
+
+
+For this example binding just specifying the name of the class does the trick,
+since the generator system will automatically catch the methods with arguments
+and return value of types known. These types can be described in the same
+typesystem file or in the ones referenced with the ``load-typesystem`` tag.
+
+In more complex situations method signatures can be changed or rejected with
+other tags that can be checked out in the typesystem reference.
+
+
+Other Common Cases and Differences
+----------------------------------
+
+What follows now is some common uses of the typesystem capabilities. All of them
+can be seen in the Qt4 typesystem files. They are not used for this binding
+tutorial example, so if you just want to have things working ASAP, move along.
+
+Templates
+~~~~~~~~~
+
+To ease the process of writing custom code for the binding, recurring pieces of
+code can be turned generic with the typesystem template mechanism.
+They are declared in a way similar to this snippet:
+
+::
+
+ <template name="only_bool*_fix">
+ bool ok;
+ %RETURN_TYPE retval = self.%FUNCTION_NAME(&ok);
+ </template>
+
+And is used as in this example:
+
+::
+
+ <inject-code class="native" position="beginning">
+ <insert-template name="only_bool*_fix"/>
+ </inject-code>
+
+
+The ``typesystem_template.xml`` file from the Qt4 bindings can be used as a
+good resource for examples of this. Check also the QtJambi documentation on
+typesystem templates. [#]_
+
+Non-QObject Derived Classes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Even in a Qt4 based library it is common to find classes that doesn't
+pertain to the QObject hierarchy, these must be declared as ``value-type``:
+
+::
+
+ <value-type name="RectOrSomethingLikeThat"/>
+
+
+Unused Tags
+~~~~~~~~~~~
+
+Some tags defined in the QtScript/QtJambi typesystem has no effect in **PySide**
+typesystem, they are:
+
+ + conversion-rule
+ + argument-map
+
+Changes to ``"inject-code"`` Tag
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can pass a file name to the **inject-code** tag so the file contents will
+be injected in the generated code.
+
+The ``class`` attribute value ``java`` was changed to ``target``, while
+``native`` remained the same.
+
+Global Functions
+~~~~~~~~~~~~~~~~
+
+The BoostPythonGenerator supports global functions, you can also reject these functions using
+the **rejection** tag like is done to reject classes. Just pass an empty string to
+the class attribute.
+
+::
+
+ <rejection class="" function-name="qt_noop"/>
+
+
+.. [#] http://doc.trolltech.com/qtjambi-4.4/html/com/trolltech/qt/qtjambi-typesystem.html
+.. [#] http://doc.trolltech.com/qtjambi-4.4/html/com/trolltech/qt/qtjambi-typesystem.html#using-code-templates
diff --git a/docgenerator.cpp b/docgenerator.cpp
new file mode 100644
index 0000000..fd80ac5
--- /dev/null
+++ b/docgenerator.cpp
@@ -0,0 +1,1371 @@
+/*
+ * This file is part of the Boost Python Generator project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "docgenerator.h"
+#include <reporthandler.h>
+#include <qtdocparser.h>
+#include <algorithm>
+#include <QtCore/QStack>
+#include <QtCore/QTextStream>
+#include <QtCore/QXmlStreamReader>
+#include <QtCore/QFile>
+#include <QtCore/QDir>
+#include <boost/graph/graph_concepts.hpp>
+
+static Indentor INDENT;
+
+namespace
+{
+
+static bool functionSort(const AbstractMetaFunction *func1, const AbstractMetaFunction *func2)
+{
+ return func1->name() < func2->name();
+}
+
+QString createRepeatedChar(int i, char c)
+{
+ QString out;
+ for (int j = 0; j < i; ++j)
+ out += c;
+
+ return out;
+}
+
+QString escape(QString& str)
+{
+ return str
+ .replace("*", "\\*")
+ .replace("_", "\\_");
+}
+
+QString escape(const QStringRef& strref)
+{
+ QString str = strref.toString();
+ return escape(str);
+}
+
+}
+
+QtXmlToSphinx::QtXmlToSphinx(DocGenerator* generator, const QString& doc, const QString& context)
+ : m_context(context), m_generator(generator), m_insideBold(false), m_insideItalic(false)
+{
+ m_handlerMap.insert("heading", &QtXmlToSphinx::handleHeadingTag);
+ m_handlerMap.insert("brief", &QtXmlToSphinx::handleParaTag);
+ m_handlerMap.insert("para", &QtXmlToSphinx::handleParaTag);
+ m_handlerMap.insert("italic", &QtXmlToSphinx::handleItalicTag);
+ m_handlerMap.insert("bold", &QtXmlToSphinx::handleBoldTag);
+ m_handlerMap.insert("see-also", &QtXmlToSphinx::handleSeeAlsoTag);
+ m_handlerMap.insert("snippet", &QtXmlToSphinx::handleSnippetTag);
+ m_handlerMap.insert("dots", &QtXmlToSphinx::handleDotsTag);
+ m_handlerMap.insert("codeline", &QtXmlToSphinx::handleDotsTag);
+ m_handlerMap.insert("table", &QtXmlToSphinx::handleTableTag);
+ m_handlerMap.insert("header", &QtXmlToSphinx::handleRowTag);
+ m_handlerMap.insert("row", &QtXmlToSphinx::handleRowTag);
+ m_handlerMap.insert("item", &QtXmlToSphinx::handleItemTag);
+ m_handlerMap.insert("argument", &QtXmlToSphinx::handleArgumentTag);
+ m_handlerMap.insert("teletype", &QtXmlToSphinx::handleArgumentTag);
+ m_handlerMap.insert("link", &QtXmlToSphinx::handleLinkTag);
+ m_handlerMap.insert("inlineimage", &QtXmlToSphinx::handleImageTag);
+ m_handlerMap.insert("image", &QtXmlToSphinx::handleImageTag);
+ m_handlerMap.insert("list", &QtXmlToSphinx::handleListTag);
+ m_handlerMap.insert("term", &QtXmlToSphinx::handleTermTag);
+ m_handlerMap.insert("raw", &QtXmlToSphinx::handleRawTag);
+ m_handlerMap.insert("underline", &QtXmlToSphinx::handleItalicTag);
+ m_handlerMap.insert("superscript", &QtXmlToSphinx::handleSuperScriptTag);
+ m_handlerMap.insert("code", &QtXmlToSphinx::handleCodeTag);
+ m_handlerMap.insert("legalese", &QtXmlToSphinx::handleCodeTag);
+ m_handlerMap.insert("section", &QtXmlToSphinx::handleAnchorTag);
+ m_handlerMap.insert("quotefile", &QtXmlToSphinx::handleQuoteFileTag);
+
+ // ignored tags
+ m_handlerMap.insert("generatedlist", &QtXmlToSphinx::handleIgnoredTag);
+ m_handlerMap.insert("tableofcontents", &QtXmlToSphinx::handleIgnoredTag);
+ m_handlerMap.insert("quotefromfile", &QtXmlToSphinx::handleIgnoredTag);
+ m_handlerMap.insert("skipto", &QtXmlToSphinx::handleIgnoredTag);
+ m_handlerMap.insert("target", &QtXmlToSphinx::handleIgnoredTag);
+
+ // useless tags
+ m_handlerMap.insert("description", &QtXmlToSphinx::handleUselessTag);
+ m_handlerMap.insert("definition", &QtXmlToSphinx::handleUselessTag);
+ m_handlerMap.insert("printuntil", &QtXmlToSphinx::handleUselessTag);
+ m_handlerMap.insert("relation", &QtXmlToSphinx::handleUselessTag);
+
+ m_result = transform(doc);
+}
+
+void QtXmlToSphinx::pushOutputBuffer()
+{
+ QString* buffer = new QString();
+ m_buffers << buffer;
+ m_output.setString(buffer);
+}
+
+QString QtXmlToSphinx::popOutputBuffer()
+{
+ Q_ASSERT(!m_buffers.isEmpty());
+ QString* str = m_buffers.pop();
+ QString strcpy(*str);
+ delete str;
+ m_output.setString(m_buffers.isEmpty() ? 0 : m_buffers.top());
+ return strcpy;
+}
+
+
+QString QtXmlToSphinx::transform(const QString& doc)
+{
+ Q_ASSERT(m_buffers.isEmpty());
+ Indentation indentation(INDENT);
+ if (doc.trimmed().isEmpty())
+ return doc;
+
+ pushOutputBuffer();
+
+ QXmlStreamReader reader(doc);
+
+ while (!reader.atEnd()) {
+ QXmlStreamReader::TokenType token = reader.readNext();
+ if (reader.hasError()) {
+ m_output << INDENT << "XML Error: " + reader.errorString() + "\n" + doc;
+ ReportHandler::warning("XML Error: " + reader.errorString() + "\n" + doc);
+ break;
+ }
+
+ if (token == QXmlStreamReader::StartElement) {
+ QStringRef tagName = reader.name();
+ TagHandler handler = m_handlerMap.value(tagName.toString(), &QtXmlToSphinx::handleUnknownTag);
+ if (!m_handlers.isEmpty() && ( (m_handlers.top() == &QtXmlToSphinx::handleIgnoredTag) ||
+ (m_handlers.top() == &QtXmlToSphinx::handleRawTag)) )
+ handler = &QtXmlToSphinx::handleIgnoredTag;
+
+ m_handlers.push(handler);
+ }
+ if (!m_handlers.isEmpty())
+ (this->*(m_handlers.top()))(reader);
+
+ if (token == QXmlStreamReader::EndElement) {
+ m_handlers.pop();
+ m_lastTagName = reader.name().toString();
+ }
+ }
+ m_output.flush();
+ QString retval = popOutputBuffer();
+ Q_ASSERT(m_buffers.isEmpty());
+ return retval;
+}
+
+QString QtXmlToSphinx::readFromLocation(QString& location, QString& identifier)
+{
+ QFile inputFile;
+ inputFile.setFileName(location);
+ if (!inputFile.open(QIODevice::ReadOnly)) {
+ ReportHandler::warning("Couldn't read code snippet file: "+inputFile.fileName());
+ return QString();
+ }
+
+ QRegExp searchString("//!\\s*\\[" + identifier + "\\]");
+ QRegExp codeSnippetCode("//!\\s*\\[[\\w\\d\\s]+\\]");
+ QString code;
+ QString line;
+ bool identifierIsEmpty = identifier.isEmpty();
+ bool getCode = false;
+
+ while (!inputFile.atEnd()) {
+ line = inputFile.readLine();
+ if (identifierIsEmpty)
+ code += line;
+ else if (getCode && !line.contains(searchString))
+ code += line.replace(codeSnippetCode, "");
+ else if (line.contains(searchString))
+ if (getCode)
+ break;
+ else
+ getCode = true;
+ }
+
+ if (code.isEmpty())
+ ReportHandler::warning("Code snippet file found ("+location+"), but snippet "+ identifier +" not found.");
+
+ return code;
+}
+
+void QtXmlToSphinx::handleHeadingTag(QXmlStreamReader& reader)
+{
+ static QString heading;
+ static char type;
+ static char types[] = { '-', '^' };
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement) {
+ int typeIdx = reader.attributes().value("level").toString().toInt();
+ if (typeIdx >= sizeof(types))
+ type = types[sizeof(types)-1];
+ else
+ type = types[typeIdx];
+ } else if (token == QXmlStreamReader::EndElement) {
+ m_output << createRepeatedChar(heading.length(), type) << endl << endl;
+ } else if (token == QXmlStreamReader::Characters) {
+ heading = escape(reader.text()).trimmed();
+ m_output << endl << endl << heading << endl;
+ }
+}
+
+void QtXmlToSphinx::handleParaTag(QXmlStreamReader& reader)
+{
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement) {
+ pushOutputBuffer();
+ } else if (token == QXmlStreamReader::EndElement) {
+ QString result = popOutputBuffer().simplified();
+ if (result.startsWith("**Warning:**"))
+ result.replace(0, 12, ".. warning:: ");
+ else if (result.startsWith("**Note:**"))
+ result.replace(0, 9, ".. note:: ");
+
+ m_output << INDENT << result << endl << endl;
+ } else if (token == QXmlStreamReader::Characters) {
+ QString text = escape(reader.text());
+ if (!m_output.string()->isEmpty()) {
+ QChar start = text[0];
+ QChar end = m_output.string()->at(m_output.string()->length() - 1);
+ if ((end == '*' || end == '`') && start != ' ' && !start.isPunct())
+ m_output << '\\';
+ }
+ m_output << INDENT << text;
+ }
+}
+
+void QtXmlToSphinx::handleItalicTag(QXmlStreamReader& reader)
+{
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement || token == QXmlStreamReader::EndElement) {
+ m_insideItalic = !m_insideItalic;
+ m_output << '*';
+ } else if (token == QXmlStreamReader::Characters) {
+ m_output << escape(reader.text()).trimmed();
+ }
+}
+
+void QtXmlToSphinx::handleBoldTag(QXmlStreamReader& reader)
+{
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement || token == QXmlStreamReader::EndElement) {
+ m_insideBold = !m_insideBold;
+ m_output << "**";
+ } else if (token == QXmlStreamReader::Characters) {
+ m_output << escape(reader.text()).trimmed();
+ }
+}
+
+void QtXmlToSphinx::handleArgumentTag(QXmlStreamReader& reader)
+{
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement || token == QXmlStreamReader::EndElement)
+ m_output << "``";
+ else if (token == QXmlStreamReader::Characters)
+ m_output << reader.text().toString().trimmed();
+}
+
+void QtXmlToSphinx::handleSeeAlsoTag(QXmlStreamReader& reader)
+{
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement)
+ m_output << INDENT << ".. seealso:: ";
+ else if (token == QXmlStreamReader::EndElement)
+ m_output << endl;
+}
+
+void QtXmlToSphinx::handleSnippetTag(QXmlStreamReader& reader)
+{
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement) {
+ bool consecutiveSnippet = m_lastTagName == "snippet" || m_lastTagName == "dots" || m_lastTagName == "codeline";
+ if (consecutiveSnippet) {
+ m_output.flush();
+ m_output.string()->chop(2);
+ }
+ QString location = reader.attributes().value("location").toString();
+ QString identifier = reader.attributes().value("identifier").toString();
+ location.prepend(m_generator->codeSnippetDir() + '/');
+ QString code = readFromLocation(location, identifier);
+ if (!consecutiveSnippet)
+ m_output << INDENT << "::\n\n";
+
+ Indentation indentation(INDENT);
+ if (code.isEmpty()) {
+ m_output << INDENT << "<Code snippet \"" << location << ':' << identifier << "\" not found>" << endl;
+ } else {
+ foreach (QString line, code.split("\n")) {
+ if (!QString(line).trimmed().isEmpty())
+ m_output << INDENT << line;
+
+ m_output << endl;
+ }
+ }
+ m_output << endl;
+ }
+}
+void QtXmlToSphinx::handleDotsTag(QXmlStreamReader& reader)
+{
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement) {
+ bool consecutiveSnippet = m_lastTagName == "snippet" || m_lastTagName == "dots" || m_lastTagName == "codeline";
+ if (consecutiveSnippet) {
+ m_output.flush();
+ m_output.string()->chop(2);
+ }
+ Indentation indentation(INDENT);
+ pushOutputBuffer();
+ m_output << INDENT;
+ int indent = reader.attributes().value("indent").toString().toInt();
+ for (int i = 0; i < indent; ++i)
+ m_output << ' ';
+ } else if (token == QXmlStreamReader::Characters) {
+ m_output << reader.text().toString();
+ } else if (token == QXmlStreamReader::EndElement) {
+ m_output << popOutputBuffer() << "\n\n\n";
+ }
+}
+
+void QtXmlToSphinx::handleTableTag(QXmlStreamReader& reader)
+{
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement) {
+ m_currentTable.clear();
+ m_tableHasHeader = false;
+ } else if (token == QXmlStreamReader::EndElement) {
+ // write the table on m_output
+ m_currentTable.enableHeader(m_tableHasHeader);
+ m_currentTable.normalize();
+ m_output << m_currentTable;
+ m_currentTable.clear();
+ }
+}
+
+void QtXmlToSphinx::handleTermTag(QXmlStreamReader& reader)
+{
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement) {
+ pushOutputBuffer();
+ } else if (token == QXmlStreamReader::Characters) {
+ m_output << reader.text().toString().replace("::", ".");
+ } else if (token == QXmlStreamReader::EndElement) {
+ TableCell cell;
+ cell.data = popOutputBuffer().trimmed();
+ m_currentTable << (TableRow() << cell);
+ }
+}
+
+
+void QtXmlToSphinx::handleItemTag(QXmlStreamReader& reader)
+{
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement) {
+ if (m_currentTable.isEmpty())
+ m_currentTable << TableRow();
+ TableRow& row = m_currentTable.last();
+ TableCell cell;
+ cell.colSpan = reader.attributes().value("colspan").toString().toShort();
+ cell.rowSpan = reader.attributes().value("rowspan").toString().toShort();
+ row << cell;
+ pushOutputBuffer();
+ } else if (token == QXmlStreamReader::EndElement) {
+ QString data = popOutputBuffer().trimmed();
+ if (!m_currentTable.isEmpty()) {
+ TableRow& row = m_currentTable.last();
+ if (!row.isEmpty())
+ row.last().data = data;
+ }
+ }
+}
+
+void QtXmlToSphinx::handleRowTag(QXmlStreamReader& reader)
+{
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement) {
+ m_tableHasHeader = reader.name() == "header";
+ m_currentTable << TableRow();
+ }
+}
+
+void QtXmlToSphinx::handleListTag(QXmlStreamReader& reader)
+{
+ // BUG We do not support a list inside a table cell
+ static QString listType;
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement) {
+ listType = reader.attributes().value("type").toString();
+ if (listType == "enum") {
+ m_currentTable << (TableRow() << "Constant" << "Description");
+ m_tableHasHeader = true;
+ }
+ INDENT.indent--;
+ } else if (token == QXmlStreamReader::EndElement) {
+ INDENT.indent++;
+ if (!m_currentTable.isEmpty()) {
+ if (listType == "bullet") {
+ m_output << endl;
+ foreach (TableCell cell, m_currentTable.first()) {
+ QStringList itemLines = cell.data.split('\n');
+ m_output << INDENT << "* " << itemLines.first() << endl;
+ for (int i = 1, max = itemLines.count(); i < max; ++i)
+ m_output << INDENT << " " << itemLines[i] << endl;
+ }
+ m_output << endl;
+ } else if (listType == "enum") {
+ m_currentTable.enableHeader(m_tableHasHeader);
+ m_currentTable.normalize();
+ m_output << m_currentTable;
+ }
+ }
+ m_currentTable.clear();
+ }
+}
+
+void QtXmlToSphinx::handleLinkTag(QXmlStreamReader& reader)
+{
+ static QString l_linktag;
+ static QString l_linkref;
+ static QString l_linktext;
+ static QString l_linktagending;
+ static QString l_type;
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement) {
+ l_linktagending = "` ";
+ if (m_insideBold) {
+ l_linktag.prepend("**");
+ l_linktagending.append("**");
+ } else if (m_insideItalic) {
+ l_linktag.prepend('*');
+ l_linktagending.append('*');
+ }
+ l_type = reader.attributes().value("type").toString();
+
+ // TODO: create a flag PROPERTY-AS-FUNCTION to ask if the properties
+ // are recognized as such or not in the binding
+ if (l_type == "property")
+ l_type = "function";
+
+ if (l_type == "typedef")
+ l_type = "class";
+
+ QString linkSource;
+ if (l_type == "function" || l_type == "class") {
+ linkSource = "raw";
+ } else if (l_type == "enum") {
+ linkSource = "enum";
+ } else if (l_type == "page") {
+ linkSource = "page";
+ } else {
+ linkSource = "href";
+ }
+
+ l_linkref = reader.attributes().value(linkSource).toString();
+ l_linkref.replace("::", ".");
+ l_linkref.remove("()");
+
+ if (l_type == "function" && !m_context.isEmpty()) {
+ l_linktag = " :meth:`";
+ QStringList rawlinklist = l_linkref.split(".");
+ if (rawlinklist.size() == 1 || rawlinklist[0] == m_context)
+ l_linkref.prepend("~" + m_context + '.');
+ } else if (l_type == "function" && m_context.isEmpty()) {
+ l_linktag = " :func:`";
+ } else if (l_type == "class") {
+ l_linktag = " :class:`";
+ } else if (l_type == "enum") {
+ l_linktag = " :attr:`";
+ } else if (l_type == "page" && l_linkref == m_generator->moduleName()) {
+ l_linktag = " :mod:`";
+ } else {
+ l_linktag = " :ref:`";
+ }
+
+ } else if (token == QXmlStreamReader::Characters) {
+ QString linktext = reader.text().toString();
+ linktext.replace("::", ".");
+ QString item = l_linkref.split(".").last();
+ if (l_linkref == linktext
+ || (l_linkref + "()") == linktext
+ || item == linktext
+ || (item + "()") == linktext)
+ l_linktext.clear();
+ else
+ l_linktext = linktext + QLatin1String("<");
+ } else if (token == QXmlStreamReader::EndElement) {
+ if (!l_linktext.isEmpty())
+ l_linktagending.prepend('>');
+ m_output << l_linktag << l_linktext << escape(l_linkref) << l_linktagending;
+ }
+}
+
+void QtXmlToSphinx::handleImageTag(QXmlStreamReader& reader)
+{
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement) {
+ QString href = reader.attributes().value("href").toString();
+ QDir dir(m_generator->outputDirectory() + '/' + m_generator->packageName().replace(".", "/"));
+ QString imgPath = dir.relativeFilePath(m_generator->libSourceDir() + "/doc/src/") + '/' + href;
+
+ if (reader.name() == "image")
+ m_output << INDENT << ".. image:: " << imgPath << endl << endl;
+ else
+ m_output << ".. image:: " << imgPath << ' ';
+ }
+}
+
+void QtXmlToSphinx::handleRawTag(QXmlStreamReader& reader)
+{
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement) {
+ QString format = reader.attributes().value("format").toString();
+ m_output << INDENT << ".. raw:: " << format.toLower() << endl << endl;
+ } else if (token == QXmlStreamReader::Characters) {
+ QStringList lst(reader.text().toString().split("\n"));
+ foreach(QString row, lst)
+ m_output << INDENT << INDENT << row << endl;
+ } else if (token == QXmlStreamReader::EndElement) {
+ m_output << endl << endl;
+ }
+}
+
+void QtXmlToSphinx::handleCodeTag(QXmlStreamReader& reader)
+{
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement) {
+ QString format = reader.attributes().value("format").toString();
+ m_output << INDENT << "::" << endl << endl;
+ INDENT.indent++;
+ } else if (token == QXmlStreamReader::Characters) {
+ QStringList lst(reader.text().toString().split("\n"));
+ foreach(QString row, lst)
+ m_output << INDENT << INDENT << row << endl;
+ } else if (token == QXmlStreamReader::EndElement) {
+ m_output << endl << endl;
+ INDENT.indent--;
+ }
+}
+
+void QtXmlToSphinx::handleUnknownTag(QXmlStreamReader& reader)
+{
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement)
+ ReportHandler::warning("Unknow QtDoc tag: \"" + reader.name().toString() + "\".");
+}
+
+void QtXmlToSphinx::handleSuperScriptTag(QXmlStreamReader& reader)
+{
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement) {
+ m_output << " :sup:`";
+ pushOutputBuffer();
+ } else if (token == QXmlStreamReader::Characters) {
+ m_output << reader.text().toString();
+ } else if (token == QXmlStreamReader::EndElement) {
+ m_output << popOutputBuffer();
+ m_output << '`';
+ }
+}
+
+void QtXmlToSphinx::handleIgnoredTag(QXmlStreamReader&)
+{
+}
+
+void QtXmlToSphinx::handleUselessTag(QXmlStreamReader&)
+{
+ // Tag "description" just marks the init of "Detailed description" title.
+ // Tag "definition" just marks enums. We have a different way to process them.
+}
+
+void QtXmlToSphinx::handleAnchorTag(QXmlStreamReader& reader)
+{
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::StartElement) {
+ QString anchor;
+ if (reader.attributes().hasAttribute("id"))
+ anchor = reader.attributes().value("id").toString();
+ else if (reader.attributes().hasAttribute("name"))
+ anchor = reader.attributes().value("name").toString();
+ if (!anchor.isEmpty() && m_opened_anchor != anchor) {
+ m_opened_anchor = anchor;
+ m_output << INDENT << ".. _" << m_context << "_" << anchor.toLower() << ":" << endl << endl;
+ }
+ } else if (token == QXmlStreamReader::EndElement) {
+ m_opened_anchor = "";
+ }
+}
+
+void QtXmlToSphinx::handleQuoteFileTag(QXmlStreamReader& reader)
+{
+ QXmlStreamReader::TokenType token = reader.tokenType();
+ if (token == QXmlStreamReader::Characters) {
+ QString location = reader.text().toString();
+ QString identifier = "";
+ location.prepend(m_generator->libSourceDir() + '/');
+ QString code = readFromLocation(location, identifier);
+
+ m_output << INDENT << "::\n\n";
+ Indentation indentation(INDENT);
+ if (code.isEmpty()) {
+ m_output << INDENT << "<Code snippet \"" << location << "\" not found>" << endl;
+ } else {
+ foreach (QString line, code.split("\n")) {
+ if (!QString(line).trimmed().isEmpty())
+ m_output << INDENT << line;
+
+ m_output << endl;
+ }
+ }
+ m_output << endl;
+ }
+}
+
+void QtXmlToSphinx::Table::normalize()
+{
+ if (m_normalized || isEmpty())
+ return;
+
+ int row;
+ int col;
+ QtXmlToSphinx::Table& self = *this;
+
+ // add col spans
+ for (row = 0; row < count(); ++row) {
+ for (col = 0; col < at(row).count(); ++col) {
+ QtXmlToSphinx::TableCell& cell = self[row][col];
+ if (cell.colSpan > 0) {
+ QtXmlToSphinx::TableCell newCell;
+ newCell.colSpan = -1;
+ for (int i = 0, max = cell.colSpan-1; i < max; ++i) {
+ self[row].insert(col+1, newCell);
+ }
+ cell.colSpan = 0;
+ col++;
+ }
+ }
+ }
+
+ // row spans
+ const int numCols = first().count();
+ for (col = 0; col < numCols; ++col) {
+ for (row = 0; row < count(); ++row) {
+ if (col < self[row].count()) {
+ QtXmlToSphinx::TableCell& cell = self[row][col];
+ if (cell.rowSpan > 0) {
+ QtXmlToSphinx::TableCell newCell;
+ newCell.rowSpan = -1;
+ int max = std::min(cell.rowSpan - 1, count());
+ cell.rowSpan = 0;
+ for (int i = 0; i < max; ++i) {
+ self[row+i+1].insert(col, newCell);
+ }
+ row++;
+ }
+ }
+ }
+ }
+ m_normalized = true;
+}
+
+QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table)
+{
+ if (table.isEmpty())
+ return s;
+
+ if (!table.isNormalized()) {
+ ReportHandler::warning("Attempt to print an unnormalized table!");
+ return s;
+ }
+
+ // calc width and height of each column and row
+ QVector<int> colWidths(table.first().count());
+ QVector<int> rowHeights(table.count());
+ for (int i = 0, maxI = table.count(); i < maxI; ++i) {
+ const QtXmlToSphinx::TableRow& row = table[i];
+ for (int j = 0, maxJ = row.count(); j < maxJ; ++j) {
+ QStringList rowLines = row[j].data.split('\n'); // cache this would be a good idea
+ foreach (QString str, rowLines)
+ colWidths[j] = std::max(colWidths[j], str.count());
+ rowHeights[i] = std::max(rowHeights[i], row[j].data.count('\n') + 1);
+ }
+ }
+
+ if (!*std::max_element(colWidths.begin(), colWidths.end()))
+ return s; // empty table (table with empty cells)
+
+ // create a horizontal line to be used later.
+ QString horizontalLine("+");
+ for (int i = 0, max = colWidths.count(); i < max; ++i) {
+ horizontalLine += createRepeatedChar(colWidths[i], '-');
+ horizontalLine += '+';
+ }
+
+ // write table rows
+ for (int i = 0, maxI = table.count(); i < maxI; ++i) { // for each row
+ const QtXmlToSphinx::TableRow& row = table[i];
+
+ // print line
+ s << INDENT << '+';
+ char c = (!i && table.hasHeader()) ? '=' : '-';
+ for (int col = 0, max = colWidths.count(); col < max; ++col) {
+ char c;
+ if (row[col].rowSpan == -1)
+ c = ' ';
+ else if (i == 1 && table.hasHeader())
+ c = '=';
+ else
+ c = '-';
+ s << createRepeatedChar(colWidths[col], c) << '+';
+ }
+ s << endl;
+
+
+ // Print the table cells
+ for (int rowLine = 0; rowLine < rowHeights[i]; ++rowLine) { // for each line in a row
+ for (int j = 0, maxJ = row.count(); j < maxJ; ++j) { // for each column
+ const QtXmlToSphinx::TableCell& cell = row[j];
+ QStringList rowLines = cell.data.split('\n'); // FIXME: Cache this!!!
+ if (!j) // First column, so we need print the identation
+ s << INDENT;
+
+ if (!j || !cell.colSpan)
+ s << '|';
+ else
+ s << ' ';
+ s << qSetFieldWidth(colWidths[j]) << left;
+ s << (rowLine < rowLines.count() ? rowLines[rowLine] : "");
+ s << qSetFieldWidth(0);
+ }
+ s << '|' << endl;
+ }
+ }
+ s << INDENT << horizontalLine << endl;
+ s << endl;
+ return s;
+}
+
+static QString getClassName(const AbstractMetaClass *cppClass) {
+ return cppClass->name().replace("::", ".");
+}
+
+static QString getFuncName(const AbstractMetaFunction *cppFunc) {
+ static bool hashInitialized = false;
+ static QHash<QString, QString> operatorsHash;
+ if (!hashInitialized) {
+ operatorsHash.insert("operator+", "__add__");
+ operatorsHash.insert("operator+=", "__iadd__");
+ operatorsHash.insert("operator-", "__sub__");
+ operatorsHash.insert("operator-=", "__isub__");
+ operatorsHash.insert("operator*", "__mul__");
+ operatorsHash.insert("operator*=", "__imul__");
+ operatorsHash.insert("operator/", "__div__");
+ operatorsHash.insert("operator/=", "__idiv__");
+ operatorsHash.insert("operator%", "__mod__");
+ operatorsHash.insert("operator%=", "__imod__");
+ operatorsHash.insert("operator<<", "__lshift__");
+ operatorsHash.insert("operator<<=", "__ilshift__");
+ operatorsHash.insert("operator>>", "__rshift__");
+ operatorsHash.insert("operator>>=", "__irshift__");
+ operatorsHash.insert("operator&", "__and__");
+ operatorsHash.insert("operator&=", "__iand__");
+ operatorsHash.insert("operator|", "__or__");
+ operatorsHash.insert("operator|=", "__ior__");
+ operatorsHash.insert("operator^", "__xor__");
+ operatorsHash.insert("operator^=", "__ixor__");
+ operatorsHash.insert("operator==", "__eq__");
+ operatorsHash.insert("operator!=", "__ne__");
+ operatorsHash.insert("operator<", "__lt__");
+ operatorsHash.insert("operator<=", "__le__");
+ operatorsHash.insert("operator>", "__gt__");
+ operatorsHash.insert("operator>=", "__ge__");
+ hashInitialized = true;
+ }
+
+ QHash<QString, QString>::const_iterator it = operatorsHash.find(cppFunc->name());
+ QString result = it != operatorsHash.end() ? it.value() : cppFunc->name();
+ return result.replace("::", ".");
+}
+
+QString DocGenerator::fileNameForClass(const AbstractMetaClass *cppClass) const
+{
+ return QString("%1.rst").arg(getClassName(cppClass));
+}
+
+void DocGenerator::writeFormatedText(QTextStream& s, const Documentation& doc, const AbstractMetaClass* metaClass)
+{
+ QString metaClassName;
+
+ if (metaClass)
+ metaClassName = getClassName(metaClass);
+
+ if (doc.format() == Documentation::Native) {
+ QtXmlToSphinx x(this, doc.value(), metaClassName);
+ s << x;
+ } else {
+ s << doc.value();
+ }
+
+ s << endl;
+}
+
+void DocGenerator::writeFunctionBrief(QTextStream &s,
+ const AbstractMetaClass *cppClass,
+ const AbstractMetaFunction *cppFunction)
+{
+ s << INDENT << "def :meth:`"
+ << cppFunction->name() << "<";
+ if (cppClass && cppClass->name() != cppFunction->name())
+ s << getClassName(cppClass) << '.';
+
+ s << cppFunction->name() << ">`"
+ << " (" << parseArgDocStyle(cppClass, cppFunction) << "):";
+}
+
+void DocGenerator::generateClass(QTextStream &s, const AbstractMetaClass *cppClass)
+{
+ QString doc;
+ QTextStream doc_s(&doc);
+
+ ReportHandler::debugSparse("Generating Documentation for " + cppClass->fullName());
+ s << ".. module:: " << packageName() << endl;
+ QString className = getClassName(cppClass);
+ s << ".. _" << className << ":" << endl << endl;
+
+ s << className << endl;
+ s << createRepeatedChar(className.count(), '*') << endl << endl;
+
+ s << ".. inheritance-diagram:: " << className << endl
+ << " :parts: 2" << endl << endl; // TODO: This would be a parameter in the future...
+
+ //Function list
+ AbstractMetaFunctionList functionList = filterFunctions(cppClass);
+ qSort(functionList.begin(), functionList.end(), functionSort);
+
+#if 0
+ if (functionList.size() > 0)
+ {
+ QtXmlToSphinx::Table functionTable;
+ QtXmlToSphinx::TableRow row;
+
+ s << "Functions\n"
+ "---------\n\n";
+
+
+ foreach (AbstractMetaFunction *func, functionList) {
+ if ((func->isConstructor() || func->isModifiedRemoved()) ||
+ (func->declaringClass() != cppClass))
+ continue;
+
+ QString rowString;
+ QTextStream rowStream(&rowString);
+
+ writeFunctionBrief(rowStream, cppClass, func);
+ row << rowString;
+ functionTable << row;
+ row.clear();
+ }
+ functionTable.normalize();
+ s << functionTable;
+ }
+
+#endif
+
+ doc_s << "Detailed Description\n"
+ "--------------------\n\n";
+
+ writeInjectDocumentation(doc_s, DocModification::Prepend, cppClass, 0);
+ writeFormatedText(doc_s, cppClass->documentation(), cppClass);
+
+
+ if (!cppClass->isNamespace()) {
+
+ writeConstructors(doc_s, cppClass);
+ writeEnums(doc_s, cppClass);
+ writeFields(doc_s, cppClass);
+
+ foreach (AbstractMetaFunction *func, functionList) {
+ if ((func->isConstructor() || func->isModifiedRemoved()) ||
+ (func->declaringClass() != cppClass))
+ continue;
+
+ if (func->isStatic())
+ doc_s << ".. staticmethod:: ";
+ else
+ doc_s << ".. method:: ";
+
+ writeFunction(doc_s, true, cppClass, func);
+ }
+ }
+
+ writeInjectDocumentation(doc_s, DocModification::Append, cppClass, 0);
+
+ writeFunctionList(s, doc, cppClass);
+
+ s << doc;
+}
+
+QString DocGenerator::parseFunctionDeclaration(const QString &doc, const AbstractMetaClass *cppClass)
+{
+ //.. method:: QObject.childEvent(arg__1)
+ //def :meth:`removeEventFilter<QObject.removeEventFilter>` (arg__1):
+
+ QString data = doc;
+ QString markup;
+
+ if (data.startsWith(".. method::"))
+ markup = ".. method::";
+ else if (data.startsWith(".. staticmethod::"))
+ markup = ".. staticmethod::";
+ else
+ return QString();
+
+ data = data.mid(markup.size()); //remove .. method::
+ data = data.mid(data.indexOf(".") + 1); //remove class name
+
+ QString methName = data.mid(0, data.indexOf("("));
+ QString methArgs = data.mid(data.indexOf("("));
+
+ data = QString("def :meth:`%1<%2.%3>` %4")
+ .arg(methName)
+ .arg(cppClass->name())
+ .arg(methName)
+ .arg(methArgs);
+
+ return data;
+}
+
+
+void DocGenerator::writeFunctionList(QTextStream &s, const QString &content, const AbstractMetaClass *cppClass)
+{
+ QStringList functionList;
+ QStringList staticFunctionList;
+
+ QStringList lst = content.split("\n");
+ foreach(QString row, lst) {
+ QString data = row.trimmed();
+ if (data.startsWith(".. method::")) {
+ functionList << parseFunctionDeclaration(data, cppClass);
+ }
+ else if (data.startsWith(".. staticmethod::")) {
+ staticFunctionList << parseFunctionDeclaration(data, cppClass);
+ }
+ }
+
+ if ((functionList.size() > 0) || (staticFunctionList.size() > 0))
+ {
+ QtXmlToSphinx::Table functionTable;
+ QtXmlToSphinx::TableRow row;
+
+ s << "Synopsis" << endl
+ << "--------" << endl << endl;
+
+ if (functionList.size() > 0) {
+ s << "Functions" << endl
+ << "^^^^^^^^^" << endl << endl;
+
+ qSort(functionList);
+ foreach (QString func, functionList) {
+ row << func;
+ functionTable << row;
+ row.clear();
+ }
+
+ functionTable.normalize();
+ s << functionTable << endl;
+ functionTable.clear();
+ }
+
+ if (staticFunctionList.size() > 0) {
+ s << "Static functions" << endl
+ << "^^^^^^^^^^^^^^^^" << endl;
+
+ qSort(staticFunctionList);
+ foreach (QString func, staticFunctionList) {
+ row << func;
+ functionTable << row;
+ row.clear();
+ }
+
+ functionTable.normalize();
+ s << functionTable << endl;
+ }
+ }
+}
+
+void DocGenerator::writeEnums(QTextStream& s, const AbstractMetaClass* cppClass)
+{
+ static const QString section_title(".. attribute:: ");
+
+ foreach (AbstractMetaEnum *en, cppClass->enums()) {
+ s << section_title << getClassName(cppClass) << "." << en->name() << endl << endl;
+ writeFormatedText(s, en->documentation(), cppClass);
+ }
+}
+
+void DocGenerator::writeFields(QTextStream &s, const AbstractMetaClass *cppClass)
+{
+ static const QString section_title(".. attribute:: ");
+
+ foreach (AbstractMetaField *field, cppClass->fields()) {
+ s << section_title << getClassName(cppClass) << "." << field->name() << endl << endl;
+ //TODO: request for member ‘documentation’ is ambiguous
+ writeFormatedText(s, field->AbstractMetaAttributes::documentation(), cppClass);
+ }
+}
+
+void DocGenerator::writeConstructors(QTextStream &s, const AbstractMetaClass *cppClass)
+{
+ static const QString sectionTitle = ".. class:: ";
+ static const QString sectionTitleSpace = QString(sectionTitle.size(), ' ');
+
+ AbstractMetaFunctionList lst = cppClass->queryFunctions(AbstractMetaClass::Constructors | AbstractMetaClass::Visible);
+
+ bool first = true;
+ QHash<QString, AbstractMetaArgument *> arg_map;
+
+ foreach(AbstractMetaFunction *func, lst) {
+ if (func->isModifiedRemoved())
+ continue;
+
+ if (first) {
+ first = false;
+ s << sectionTitle;
+ } else {
+ s << sectionTitleSpace;
+ }
+ writeFunction(s, false, cppClass, func);
+ foreach(AbstractMetaArgument *arg, func->arguments())
+ {
+ if (!arg_map.contains(arg->argumentName())) {
+ arg_map.insert(arg->argumentName(), arg);
+ }
+ }
+ }
+
+ s << endl;
+
+ foreach (AbstractMetaArgument *arg, arg_map.values()) {
+ Indentation indentation(INDENT);
+ writeParamerteType(s, cppClass, arg);
+ }
+
+ s << endl;
+
+ foreach (AbstractMetaFunction *func, lst) {
+ writeFormatedText(s, func->documentation(), cppClass);
+ }
+}
+
+QString DocGenerator::parseArgDocStyle(const AbstractMetaClass *cppClass, const AbstractMetaFunction *func)
+{
+ QString ret;
+ bool optional = false;
+
+ foreach (AbstractMetaArgument *arg, func->arguments()) {
+
+ if (func->argumentRemoved(arg->argumentIndex() + 1))
+ continue;
+
+ if (arg->argumentIndex() > 0)
+ ret += ",";
+
+ if (!arg->defaultValueExpression().isEmpty() && (!optional)) {
+ ret += "[";
+ optional = true;
+ }
+
+ ret += arg->argumentName();
+
+ if (optional)
+ ret += "=" + arg->defaultValueExpression();
+ }
+
+ if (optional)
+ ret += "]";
+
+ return ret;
+}
+
+void DocGenerator::writeDocSnips(QTextStream &s,
+ const CodeSnipList &codeSnips,
+ CodeSnip::Position position,
+ TypeSystem::Language language)
+{
+ Indentation indentation(INDENT);
+ QStringList invalidStrings;
+ const static QString startMarkup("[sphinx-begin]");
+ const static QString endMarkup("[sphinx-end]");
+
+ invalidStrings << "*" << "//" << "/*" << "*/";
+
+ foreach (CodeSnip snip, codeSnips) {
+ if ((snip.position != position) ||
+ !(snip.language & language))
+ continue;
+
+ QString code = snip.code();
+ while (code.contains(startMarkup) && code.contains(endMarkup)) {
+ int startBlock = code.indexOf(startMarkup) + startMarkup.size();
+ int endBlock = code.indexOf(endMarkup);
+
+ if ((startBlock == -1) || (endBlock == -1))
+ break;
+
+ QString codeBlock = code.mid(startBlock, endBlock - startBlock);
+ QStringList rows = codeBlock.split("\n");
+ int currenRow = 0;
+ int offset = 0;
+
+ foreach(QString row, rows) {
+ foreach(QString invalidString, invalidStrings) {
+ row = row.remove(invalidString);
+ }
+
+ if (row.trimmed().size() == 0) {
+ if (currenRow == 0)
+ continue;
+ else
+ s << endl;
+ }
+
+ if (currenRow == 0) {
+ //find offset
+ for (int i=0, i_max = row.size(); i < i_max; i++) {
+ if (row[i] == ' ')
+ offset++;
+ else if (row[i] == '\n')
+ offset = 0;
+ else
+ break;
+ }
+ }
+ row = row.mid(offset);
+ s << row << endl;
+ currenRow++;
+ }
+
+ code = code.mid(endBlock+endMarkup.size());
+ }
+ }
+}
+
+void DocGenerator::writeInjectDocumentation(QTextStream &s,
+ DocModification::Mode mode,
+ const AbstractMetaClass *cppClass,
+ const AbstractMetaFunction *func)
+{
+ Indentation indentation(INDENT);
+
+ foreach (DocModification mod, cppClass->typeEntry()->docModifications()) {
+ if (mod.mode() == mode) {
+ bool modOk = func ? mod.signature() == func->minimalSignature() : mod.signature().isEmpty();
+
+ if (modOk) {
+ Documentation doc;
+ Documentation::Format fmt;
+
+ if (mod.format == TypeSystem::NativeCode)
+ fmt = Documentation::Native;
+ else if (mod.format == TypeSystem::TargetLangCode)
+ fmt = Documentation::Target;
+ else
+ continue;
+
+ doc.setValue(mod.code() , fmt);
+ s << INDENT;
+ writeFormatedText(s, doc, cppClass);
+ }
+ }
+ }
+
+ s << endl;
+
+ if (func) {
+ writeDocSnips(s, getCodeSnips(func),
+ (mode == DocModification::Prepend ? CodeSnip::Beginning : CodeSnip::End),
+ TypeSystem::TargetLangCode);
+ } else {
+ writeDocSnips(s, cppClass->typeEntry()->codeSnips(),
+ (mode == DocModification::Prepend ? CodeSnip::Beginning : CodeSnip::End),
+ TypeSystem::TargetLangCode);
+ }
+}
+
+void DocGenerator::writeFunctionSignature(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func)
+{
+ if (!func->isConstructor())
+ s << getClassName(cppClass) << '.';
+ s << getFuncName(func) << "(" << parseArgDocStyle(cppClass, func) << ")";
+}
+
+QString DocGenerator::translateToPythonType(const AbstractMetaType *type, const AbstractMetaClass *cppClass)
+{
+ QString originalType = translateType(type, cppClass, Generator::ExcludeConst | Generator::ExcludeReference);
+ QString strType = originalType;
+
+ //remove "*"
+ strType.remove("*");
+ TypeEntry *te = TypeDatabase::instance()->findType(originalType.trimmed());
+ if (te) {
+ return te->targetLangName();
+ } else {
+ //remove <, >
+ strType.remove(">");
+ strType.remove("<");
+
+ //replace ::
+ strType.replace("::", ".");
+
+ //Translate ContainerType
+ if (strType.contains("QList") || strType.contains("QVector")) {
+ strType.replace("QList", "List of ");
+ strType.replace("QVector", "List of ");
+ } else if (strType.contains("QHash") || strType.contains("QMap")) {
+ strType.remove("QHash");
+ strType.remove("QMap");
+ QStringList types = strType.split(",");
+ strType = QString("Dictionary with keys of type %1 and values of type %2.")
+ .arg(types[0]).arg(types[1]);
+ }
+ return strType;
+ }
+}
+
+void DocGenerator::writeParamerteType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaArgument *arg)
+{
+ s << INDENT << ":param " << arg->argumentName() << ": "
+ << translateToPythonType(arg->type(), cppClass) << endl;
+}
+
+void DocGenerator::writeFunctionParametersType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction* func)
+{
+ Indentation indentation(INDENT);
+
+ s << endl;
+ foreach (AbstractMetaArgument *arg, func->arguments()) {
+
+ if (func->argumentRemoved(arg->argumentIndex() + 1))
+ continue;
+
+ writeParamerteType(s, cppClass, arg);
+ }
+
+ if (!func->isConstructor() && func->type()) {
+ s << INDENT << ":rtype: " << translateToPythonType(func->type(), cppClass) << endl;
+ }
+ s << endl;
+}
+
+void DocGenerator::writeFunction(QTextStream &s, bool writeDoc, const AbstractMetaClass *cppClass, const AbstractMetaFunction* func)
+{
+ writeFunctionSignature(s, cppClass, func);
+ s << endl;
+
+ if (writeDoc) {
+ s << endl;
+ writeFunctionParametersType(s, cppClass, func);
+ s << endl;
+ writeInjectDocumentation(s, DocModification::Prepend, cppClass, func);
+ writeFormatedText(s, func->documentation(), cppClass);
+ writeInjectDocumentation(s, DocModification::Append, cppClass, func);
+ }
+}
+
+void DocGenerator::finishGeneration()
+{
+ if (classes().isEmpty())
+ return;
+
+ QFile input(outputDirectory() + '/' + subDirectoryForPackage(packageName()) + "/index.rst");
+ input.open(QIODevice::WriteOnly);
+ QTextStream s(&input);
+
+ s << ".. module:: " << packageName() << endl << endl;
+
+ QString title = packageName() + " contents";
+ s << title << endl;
+ s << createRepeatedChar(title.length(), '*') << endl << endl;
+ s << ".. toctree::" << endl;
+
+ /* Avoid showing "Detailed Description for *every* class in toc tree */
+ Indentation indentation(INDENT);
+ s << INDENT << ":maxdepth: 1" << endl << endl;
+
+ QStringList classList;
+ foreach (AbstractMetaClass *cls, classes()) {
+ if (!shouldGenerate(cls))
+ continue;
+ classList << getClassName(cls);
+ }
+ classList.sort();
+
+ foreach (QString clazz, classList)
+ s << INDENT << clazz << endl;
+
+ s << endl << endl;
+
+ s << "Detailed Description" << endl;
+ s << "--------------------" << endl << endl;
+
+ if (m_moduleDoc.format() == Documentation::Native) {
+ QtXmlToSphinx x(this, m_moduleDoc.value(), moduleName());
+ s << x;
+ } else {
+ s << m_moduleDoc.value();
+ }
+}
+
+bool DocGenerator::prepareGeneration(const QMap<QString, QString>& args)
+{
+ BoostPythonGenerator::prepareGeneration(args);
+ m_libSourceDir = args.value("library-source-dir");
+ setOutputDirectory(args.value("documentation-out-dir"));
+ m_docDataDir = args.value("documentation-data-dir");
+ m_codeSnippetDir = args.value("documentation-code-snippets-dir", m_libSourceDir);
+
+ if (m_libSourceDir.isEmpty() || m_docDataDir.isEmpty()) {
+ ReportHandler::warning("Documentation data dir and/or Qt source dir not informed, "
+ "documentation will not be extracted from Qt sources.");
+ return false;
+ } else {
+ QtDocParser docParser;
+ docParser.setPackageName(packageName());
+ docParser.setDocumentationDataDirectory(m_docDataDir);
+ docParser.setLibrarySourceDirectory(m_libSourceDir);
+ foreach(AbstractMetaClass* cppClass, classes()) {
+ docParser.fillDocumentation(cppClass);
+ }
+ m_moduleDoc = docParser.retrieveModuleDocumentation();
+ return true;
+ }
+}
+
+
+QMap<QString, QString> DocGenerator::options() const
+{
+ QMap<QString, QString> options;
+ options.insert("library-source-dir", "Directory where library source code is located");
+ options.insert("documentation-out-dir", "The directory where the generated documentation files will be written");
+ options.insert("documentation-data-dir", "Directory with XML files generated by documentation tool (qdoc3 or Doxygen)");
+ options.insert("documentation-code-snippets-dir", "Directory used to search code snippets used by the documentation");
+ return options;
+}
+
diff --git a/docgenerator.h b/docgenerator.h
new file mode 100644
index 0000000..cef7fa7
--- /dev/null
+++ b/docgenerator.h
@@ -0,0 +1,212 @@
+/*
+ * This file is part of the Boost Python Generator project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#ifndef DOCGENERATOR_H
+#define DOCGENERATOR_H
+
+#include "boostpythongenerator.h"
+#include <QtCore/QStack>
+
+class QXmlStreamReader;
+class DocGenerator;
+
+class QtXmlToSphinx
+{
+public:
+ struct TableCell
+ {
+ short rowSpan;
+ short colSpan;
+ QString data;
+
+ TableCell(const QString& text = QString()) : rowSpan(0), colSpan(0), data(text) {}
+ TableCell(const char* text) : rowSpan(0), colSpan(0), data(text) {}
+ };
+
+ typedef QList<TableCell> TableRow;
+ class Table : public QList<TableRow>
+ {
+ public:
+ Table() : m_hasHeader(false), m_normalized(false)
+ {
+ }
+
+ void enableHeader(bool enable)
+ {
+ m_hasHeader = enable;
+ }
+
+ bool hasHeader() const
+ {
+ return m_hasHeader;
+ }
+
+ void normalize();
+
+ bool isNormalized() const
+ {
+ return m_normalized;
+ }
+
+ void clear() {
+ m_normalized = false;
+ QList<TableRow>::clear();
+ }
+
+ private:
+ bool m_hasHeader;
+ bool m_normalized;
+ };
+
+ QtXmlToSphinx(DocGenerator* generator, const QString& doc, const QString& context = QString());
+
+ QString result() const
+ {
+ return m_result;
+ }
+
+private:
+ QString transform(const QString& doc);
+
+ void handleHeadingTag(QXmlStreamReader& reader);
+ void handleParaTag(QXmlStreamReader& reader);
+ void handleItalicTag(QXmlStreamReader& reader);
+ void handleBoldTag(QXmlStreamReader& reader);
+ void handleArgumentTag(QXmlStreamReader& reader);
+ void handleSeeAlsoTag(QXmlStreamReader& reader);
+ void handleSnippetTag(QXmlStreamReader& reader);
+ void handleDotsTag(QXmlStreamReader& reader);
+ void handleLinkTag(QXmlStreamReader& reader);
+ void handleImageTag(QXmlStreamReader& reader);
+ void handleListTag(QXmlStreamReader& reader);
+ void handleTermTag(QXmlStreamReader& reader);
+ void handleSuperScriptTag(QXmlStreamReader& reader);
+ void handleQuoteFileTag(QXmlStreamReader& reader);
+
+ // table tagsvoid QtXmlToSphinx::handleValueTag(QXmlStreamReader& reader)
+
+ void handleTableTag(QXmlStreamReader& reader);
+ void handleRowTag(QXmlStreamReader& reader);
+ void handleItemTag(QXmlStreamReader& reader);
+ void handleRawTag(QXmlStreamReader& reader);
+ void handleCodeTag(QXmlStreamReader& reader);
+
+ void handleIgnoredTag(QXmlStreamReader& reader);
+ void handleUnknownTag(QXmlStreamReader& reader);
+ void handleUselessTag(QXmlStreamReader& reader);
+ void handleAnchorTag(QXmlStreamReader& reader);
+
+ typedef void (QtXmlToSphinx::*TagHandler)(QXmlStreamReader&);
+ QHash<QString, TagHandler> m_handlerMap;
+ QStack<TagHandler> m_handlers;
+ QTextStream m_output;
+ QString m_result;
+
+ QStack<QString*> m_buffers;
+
+
+ Table m_currentTable;
+ bool m_tableHasHeader;
+ QString m_context;
+ DocGenerator* m_generator;
+ bool m_insideBold;
+ bool m_insideItalic;
+ QString m_lastTagName;
+ QString m_opened_anchor;
+
+ QString readFromLocation(QString& location, QString& identifier);
+ void pushOutputBuffer();
+ QString popOutputBuffer();
+ void writeTable(Table& table);
+};
+
+inline QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx& xmlToSphinx)
+{
+ return s << xmlToSphinx.result();
+}
+
+QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table);
+
+/**
+* The DocGenerator generates documentation from library being binded.
+*/
+class DocGenerator : public BoostPythonGenerator
+{
+public:
+ virtual GeneratorType type() const
+ {
+ return DocumentationType;
+ }
+
+ QString libSourceDir() const
+ {
+ return m_libSourceDir;
+ }
+
+ virtual bool prepareGeneration(const QMap<QString, QString>& args);
+
+ const char* name() const
+ {
+ return "DocGenerator";
+ }
+
+ QMap<QString, QString> options() const;
+
+ QString codeSnippetDir() const
+ {
+ return m_codeSnippetDir;
+ }
+
+protected:
+ QString fileNameForClass(const AbstractMetaClass* cppClass) const;
+ void generateClass(QTextStream& s, const AbstractMetaClass* cppClass);
+ void finishGeneration();
+private:
+ void writeEnums(QTextStream& s, const AbstractMetaClass* cppClass);
+
+ void writeFields(QTextStream &s, const AbstractMetaClass *cppClass);
+ void writeArguments(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction *func);
+ void writeFunctionBrief(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction *cppFunction);
+ void writeFunctionSignature(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func);
+ void writeFunction(QTextStream& s, bool writeDoc, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func);
+ void writeFunctionParametersType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction* func);
+ void writeFunctionList(QTextStream &se, const QString &content, const AbstractMetaClass *cppClass);
+ void writeParamerteType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaArgument *arg);
+
+ void writeConstructors(QTextStream &s, const AbstractMetaClass *cppClass);
+ void writeFormatedText(QTextStream& s, const Documentation& doc, const AbstractMetaClass* metaclass = 0);
+ void writeInjectDocumentation(QTextStream &s, DocModification::Mode mode, const AbstractMetaClass *cppClass, const AbstractMetaFunction *func);
+ void writeDocSnips(QTextStream &s, const CodeSnipList &codeSnips, CodeSnip::Position position, TypeSystem::Language language);
+
+
+ QString parseArgDocStyle(const AbstractMetaClass *cppClass, const AbstractMetaFunction *func);
+ QString parseFunctionDeclaration(const QString &data, const AbstractMetaClass *cppClass);
+ QString translateToPythonType(const AbstractMetaType *type, const AbstractMetaClass *cppClass);
+
+ QString m_docDataDir;
+ QString m_libSourceDir;
+ QString m_codeSnippetDir;
+ QStringList m_functionList;
+ Documentation m_moduleDoc;
+};
+
+#endif // DOCGENERATOR_H
diff --git a/hppgenerator.cpp b/hppgenerator.cpp
new file mode 100644
index 0000000..4e7da11
--- /dev/null
+++ b/hppgenerator.cpp
@@ -0,0 +1,219 @@
+/*
+ * This file is part of the Boost Python Generator project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#include "hppgenerator.h"
+#include <apiextractor/reporthandler.h>
+
+#include <QtCore/QDir>
+#include <QtCore/QTextStream>
+#include <QtCore/QVariant>
+#include <QtCore/QRegExp>
+#include <QtCore/QDebug>
+
+static Indentor INDENT;
+
+QString HppGenerator::fileNameForClass(const AbstractMetaClass *cppClass) const
+{
+ return getWrapperName(cppClass) + QLatin1String(".hpp");
+}
+
+void HppGenerator::writeCopyCtor(QTextStream &s, const AbstractMetaClass *cppClass)
+{
+ s << INDENT << getWrapperName(cppClass) << "(const " << cppClass->qualifiedCppName() << "& self)"
+ << " : " << cppClass->qualifiedCppName() << "(self)" << endl
+ << INDENT << "{" << endl
+ << INDENT << "}" << endl;
+}
+
+void HppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *cppClass)
+{
+ ReportHandler::debugSparse("Generating header for " + cppClass->fullName());
+ Indentation indent(INDENT);
+
+ // write license comment
+ s << licenseComment() << endl;
+
+ QString wrapperName = HppGenerator::getWrapperName(cppClass);
+ // Header
+ s << "#ifndef __" << wrapperName.toUpper() << "__" << endl;
+ s << "#define __" << wrapperName.toUpper() << "__" << endl << endl;
+
+ s << "#include <pyside.hpp>" << endl;
+ //Includes
+ if (cppClass->typeEntry()->include().isValid())
+ s << cppClass->typeEntry()->include().toString() << endl << endl;
+
+ s << "using namespace PySide;" << endl << endl;
+
+ if (!cppClass->isPolymorphic() || cppClass->hasPrivateDestructor() || cppClass->isNamespace())
+ s << "namespace " << wrapperName << " {" << endl << endl;
+
+ if (cppClass->isNamespace()) {
+ s << INDENT << "struct Namespace {};" << endl;
+ } else {
+ QString className;
+ bool create_wrapper = canCreateWrapperFor(cppClass);
+ // detect the held type
+ QString held_type = cppClass->typeEntry()->heldTypeValue();
+ if (held_type.isEmpty() && create_wrapper)
+ held_type = "qptr";
+
+ writeCodeSnips(s, cppClass->typeEntry()->codeSnips(),
+ CodeSnip::Declaration, TypeSystem::NativeCode);
+
+ if (cppClass->isPolymorphic() && !cppClass->hasPrivateDestructor()) {
+ if (!held_type.isEmpty()) {
+ s << "// held type forward decalration" << endl;
+ s << "template<typename T> class " << held_type << ';' << endl;
+ }
+
+ // Class
+ s << "class PYSIDE_LOCAL " << wrapperName;
+ if (create_wrapper) {
+ s << " : public " << cppClass->qualifiedCppName() << ", public boost::python::wrapper<";
+ s << cppClass->qualifiedCppName() << '>';
+ }
+ s << endl;
+ s << "{" << endl;
+ }
+
+ writeCodeSnips(s, cppClass->typeEntry()->codeSnips(),
+ CodeSnip::Declaration, TypeSystem::ShellDeclaration);
+
+ if (cppClass->isPolymorphic() && !cppClass->hasPrivateDestructor()) {
+ s << endl << "private:" << endl;
+
+ if (cppClass->hasPrivateDestructor())
+ className = cppClass->qualifiedCppName();
+ else
+ className = wrapperName;
+ } else {
+ className = cppClass->qualifiedCppName();
+ }
+
+ // print the huge boost::python::class_ typedef
+ s << INDENT << "typedef boost::python::class_< " << className;
+
+ writeBaseClass(s, cppClass);
+
+ if (!held_type.isEmpty())
+ s << ", PySide::" << held_type << " < " << className << ", PySide::qptr_base::avoid_cache > ";
+
+ if (!isCopyable(cppClass))
+ s << ", boost::noncopyable";
+
+ s << " > class_type;" << endl;
+
+ if (cppClass->isPolymorphic() && !cppClass->hasPrivateDestructor()) {
+ s << "public:" << endl;
+
+ if (isCopyable(cppClass))
+ writeCopyCtor(s, cppClass);
+
+ foreach (AbstractMetaFunction *func, filterFunctions(cppClass))
+ writeFunction(s, func);
+
+ if (create_wrapper) {
+ //destructor
+ s << INDENT << "~" << wrapperName << "();" << endl;
+
+ if (cppClass->isQObject() && (cppClass->name() != "QObject"))
+ s << INDENT << "using QObject::parent;" << endl;
+ }
+ }
+
+ writeCodeSnips(s, cppClass->typeEntry()->codeSnips(),
+ CodeSnip::End, TypeSystem::ShellDeclaration);
+
+ }
+
+ QString staticKeyword = cppClass->isNamespace() ? QLatin1String("") : QLatin1String("static ");
+ s << INDENT;
+ if (cppClass->isPolymorphic() && !cppClass->hasPrivateDestructor()) {
+ s << "//static member used to export class" << endl;
+ s << INDENT << staticKeyword;
+ }
+ s << "void define_python_class() throw();" << endl << endl;
+
+ writeCodeSnips(s, cppClass->typeEntry()->codeSnips(),
+ CodeSnip::PrototypeInitialization, TypeSystem::NativeCode);
+
+
+ s << "};" << endl << endl;
+ s << "#endif // __" << wrapperName.toUpper() << "__" << endl << endl;
+}
+
+void HppGenerator::writeFunction(QTextStream &s, const AbstractMetaFunction* func)
+{
+ // pure virtual functions need a default implementation
+ if ((func->isPrivate() && !func->isConstructor()) || (func->isModifiedRemoved() && !func->isAbstract()))
+ return;
+
+ // do not write copy ctors here.
+ if (func->isCopyConstructor())
+ return;
+
+ if (func->isConstructor() || func->isAbstract() || func->isVirtual()) {
+ if (func->isVirtual() && !func->isAbstract() && !func->isConstructor()
+ && !func->ownerClass()->hasPrivateDestructor()
+ && func->implementingClass() == func->ownerClass()) {
+ s << INDENT << "static " << signatureForDefaultVirtualMethod(func, "", "_default", Generator::SkipName) << ';' << endl;
+ }
+
+ s << INDENT << functionSignature(func, "", "", Generator::OriginalTypeDescription | Generator::SkipName);
+ if (func->isModifiedRemoved() && func->isAbstract())
+ writeDefaultImplementation(s, func);
+ else
+ s << ';' << endl;
+ }
+}
+
+void HppGenerator::writeDefaultImplementation(QTextStream& s, const AbstractMetaFunction* func)
+{
+ QString returnValue;
+ if (func->type()) {
+ if (func->type()->isObject() || func->type()->isQObject() || func->type()->name() == "void")
+ returnValue = "0";
+ else
+ returnValue = functionReturnType(func) + "()";
+ }
+ s << " { return " << returnValue << "; }" << endl;
+}
+
+void HppGenerator::writeBaseClass(QTextStream& s, const AbstractMetaClass* cppClass)
+{
+ if (!cppClass->isNamespace() && !cppClass->isInterface()) {
+ QStringList baseClass = getBaseClasses(cppClass);
+
+ if (baseClass.isEmpty()) {
+ const ComplexTypeEntry *type = cppClass->typeEntry();
+ if (cppClass->name() != type->defaultSuperclass()) {
+ QString sc = type->defaultSuperclass();
+ if (!sc.isEmpty())
+ s << ", python::bases< " << sc << "> ";
+ }
+ } else {
+ s << ", boost::python::bases< " << baseClass.join(", ") << " > ";
+ }
+ }
+}
+
diff --git a/hppgenerator.h b/hppgenerator.h
new file mode 100644
index 0000000..8e0f5f0
--- /dev/null
+++ b/hppgenerator.h
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the Boost Python Generator project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef HPPGENERATOR_H
+#define HPPGENERATOR_H
+
+#include "boostpythongenerator.h"
+
+/**
+* The HppGenerator generate the declarations of boost::python bindings classes.
+*/
+class HppGenerator : public BoostPythonGenerator
+{
+protected:
+ QString fileNameForClass(const AbstractMetaClass* cppClass) const;
+ void generateClass(QTextStream& s, const AbstractMetaClass* cppClass);
+ void finishGeneration() {}
+ const char* name() const
+ {
+ return "HppGenerator";
+ }
+private:
+ void writeFunction(QTextStream& s, const AbstractMetaFunction* func);
+ void writePureVirtualEmptyImpl(QTextStream& , const AbstractMetaFunction* func);
+ void writeBaseClass(QTextStream& s, const AbstractMetaClass* cppClass);
+ void writeCopyCtor(QTextStream &s, const AbstractMetaClass* cppClass);
+ void writeDefaultImplementation(QTextStream& s, const AbstractMetaFunction* func);
+};
+
+#endif // HPPGENERATOR_H
+
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..9560eff
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the Boost Python Generator project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <QtCore/QCoreApplication>
+#include <apiextractor/apiextractor.h>
+#include "hppgenerator.h"
+#include "cppgenerator.h"
+#include "hppgenerator.h"
+#include "convertergenerator.h"
+#include "docgenerator.h"
+#include "boostpythongeneratorversion.h"
+#include <iostream>
+
+void showVersion(const char* apiextractor_version) {
+ using namespace std;
+
+ cout << "BoostPythonGenerator v" BOOSTPYTHONGENERATOR_VERSION << " using " << apiextractor_version << endl;
+ cout << "Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)" << endl;
+}
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv); // needed by qxmlpatterns
+
+ ApiExtractor extractor(argc, argv);
+ extractor.addGenerator(new HppGenerator);
+ extractor.addGenerator(new CppGenerator);
+ extractor.addGenerator(new ConverterGenerator);
+ extractor.addGenerator(new DocGenerator);
+ extractor.setVersionHandler(&showVersion);
+ return extractor.exec();
+}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000..9099adf
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,9 @@
+project(sphinxtabletest)
+
+# TODO
+set(sphinxtabletest_SRC sphinxtabletest.cpp)
+qt4_automoc(${sphinxtabletest_SRC})
+include_directories(${QT_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${boostpythongenerator_SOURCE_DIR})
+add_executable(sphinxtabletest ${sphinxtabletest_SRC})
+target_link_libraries(sphinxtabletest ${QT_QTTEST_LIBRARY} ${APIEXTRACTOR_LIBRARY} libboostpythongenerator)
+add_test("sphinxtable" sphinxtabletest)
diff --git a/tests/Makefile b/tests/Makefile
new file mode 100644
index 0000000..054d6f5
--- /dev/null
+++ b/tests/Makefile
@@ -0,0 +1,12 @@
+all:
+ (cd libfoo; $(MAKE))
+ (cd foobinding; $(MAKE))
+
+
+test:
+ LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):$(PWD)/libfoo PYTHONPATH=$(PYTHONPATH):$(PWD)/foobinding/foo python foo_test.py
+
+clean:
+ (cd libfoo; $(MAKE) clean)
+ (cd foobinding; $(MAKE) clean)
+
diff --git a/tests/foo_test.py b/tests/foo_test.py
new file mode 100644
index 0000000..45b7e80
--- /dev/null
+++ b/tests/foo_test.py
@@ -0,0 +1,105 @@
+
+'''Test cases for virtual methods called through generated bindings'''
+
+import unittest
+try:
+ from foo import Foo, Bar
+except:
+ import sys
+ print 'You need to set correct paths for libfoo and foo bindings'
+ import os
+ sys.exit(1)
+
+
+class DerivedFoo(Foo):
+
+ def __init__(self):
+ Foo.__init__(self)
+
+ def pureVirtual(self):
+ print 'DerivedFoo.pureVirtual'
+
+
+class VirtualMethods(unittest.TestCase):
+ '''Test case for virtual methods'''
+
+ def setUp(self):
+ self.foo = Foo()
+ self.bar = Bar()
+ self.derivedfoo = DerivedFoo()
+
+ def tearDown(self):
+ self.foo = None
+ self.bar = None
+ self.derivedfoo = None
+
+ def testDerivedClassVirtualMethod(self):
+ '''Test reinplemented virtual methods from derived class'''
+ called = True
+ try:
+ self.bar.unpureVirtual()
+ self.bar.pureVirtual()
+ except:
+ called = False
+ self.assertTrue(called)
+
+ def testBaseClassVirtualMethod(self):
+ '''Test virtual method from base class'''
+ called = True
+ try:
+ self.foo.unpureVirtual()
+ except:
+ called = False
+ self.assertTrue(called)
+
+
+ def testBaseClassPureVirtualMethod(self):
+ '''Test pure virtual method from base class'''
+ called = False
+ try:
+ self.foo.pureVirtual()
+ except:
+ called = False
+ self.assertFalse(called)
+
+ def testBaseClassIndirectCallToUnpureVirtualMethod(self):
+ '''Test call to unpure virtual method from C++ to Python'''
+ called = True
+ try:
+ self.foo.unpureVirtual()
+ except:
+ called = False
+ self.assertTrue(called)
+
+ def testDerivedClassIndirectCallToUnpureVirtualMethod(self):
+ '''Test call to unpure virtual method from C++ to Python'''
+ called = True
+ try:
+ self.bar.unpureVirtual()
+ except:
+ called = False
+ self.assertTrue(called)
+
+ def testCppDerivedClassIndirectCallToPureVirtualMethod(self):
+ '''Test call to pure virtual method from C++ to Python'''
+ called = False
+ try:
+ self.bar.callPureVirtual()
+ except:
+ called = False
+ self.assertFalse(called)
+
+
+ def testDerivedClassIndirectCallToPureVirtualMethod(self):
+ '''Test call to pure virtual method from C++ to Python'''
+ called = False
+ try:
+ self.derivedfoo.callPureVirtual()
+ except:
+ called = False
+ self.assertFalse(called)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/tests/foobinding/Makefile b/tests/foobinding/Makefile
new file mode 100644
index 0000000..30909ae
--- /dev/null
+++ b/tests/foobinding/Makefile
@@ -0,0 +1,13 @@
+all: generate
+ (cd foo; $(MAKE))
+
+generate:
+ boostpythongenerator --disable-named-arg global.h \
+ --include-paths=`pwd`/../libfoo \
+ --typesystem-paths=. --output-directory=. \
+ typesystem_foo.xml
+
+clean:
+ rm *.log .preprocessed.tmp foo/*.hpp foo/*.cpp -rf
+ (cd foo; $(MAKE) clean)
+
diff --git a/tests/foobinding/foo/Makefile b/tests/foobinding/foo/Makefile
new file mode 100644
index 0000000..4f6896f
--- /dev/null
+++ b/tests/foobinding/foo/Makefile
@@ -0,0 +1,21 @@
+CXX_FLAGS=-DBOOST_PYTHON_NO_PY_SIGNATURES -g -fPIC -I/usr/include/python2.5 -I../../libfoo `pkg-config pyside --cflags`
+CXX_LDFLAGS=-DBOOST_PYTHON_NO_PY_SIGNATURES -fPIC -shared -L../../libfoo -lfoo `pkg-config pyside --libs`
+
+all: foo_wrapper.o bar_wrapper.o foo_globals_wrapper.o foo_module_wrapper.o
+ g++ $(CXX_LDFLAGS) bar_wrapper.o foo_wrapper.o foo_globals_wrapper.o foo_module_wrapper.o -Wl,-soname,foo.so -o foo.so
+
+foo_wrapper.o: foo_wrapper.cpp foo_wrapper.hpp
+ g++ $(CXX_FLAGS) foo_wrapper.cpp -c
+
+bar_wrapper.o: bar_wrapper.cpp bar_wrapper.hpp
+ g++ $(CXX_FLAGS) bar_wrapper.cpp -c
+
+foo_globals_wrapper.o: foo_globals_wrapper.cpp
+ g++ $(CXX_FLAGS) foo_globals_wrapper.cpp -c
+
+foo_module_wrapper.o: foo_module_wrapper.cpp
+ g++ $(CXX_FLAGS) foo_module_wrapper.cpp -c
+
+clean:
+ rm *.o *.so -rf
+
diff --git a/tests/foobinding/global.h b/tests/foobinding/global.h
new file mode 100644
index 0000000..a23601a
--- /dev/null
+++ b/tests/foobinding/global.h
@@ -0,0 +1,2 @@
+#include "foo.h"
+#include "bar.h"
diff --git a/tests/foobinding/typesystem_foo.xml b/tests/foobinding/typesystem_foo.xml
new file mode 100644
index 0000000..e4289e4
--- /dev/null
+++ b/tests/foobinding/typesystem_foo.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<typesystem package="foo">
+ <object-type name="Foo"/>
+ <object-type name="Bar"/>
+</typesystem>
+
diff --git a/tests/libfoo/Makefile b/tests/libfoo/Makefile
new file mode 100644
index 0000000..eaf8f62
--- /dev/null
+++ b/tests/libfoo/Makefile
@@ -0,0 +1,15 @@
+all: foo.o bar.o
+ g++ -fPIC -shared foo.o bar.o -o libfoo.so
+
+foo.o: foo.h foo.cpp
+ g++ -fPIC foo.cpp -c
+
+bar.o: bar.h bar.cpp
+ g++ -fPIC bar.cpp -c
+
+test: main.cpp
+ g++ main.cpp -L. -lfoo -I. -o footest
+
+clean:
+ rm *.o *.so footest -rf
+
diff --git a/tests/libfoo/bar.cpp b/tests/libfoo/bar.cpp
new file mode 100644
index 0000000..a8f9712
--- /dev/null
+++ b/tests/libfoo/bar.cpp
@@ -0,0 +1,15 @@
+#include <iostream>
+#include "bar.h"
+
+using namespace std;
+
+void Bar::pureVirtual()
+{
+ cout << "Bar::pureVirtual()" << endl;
+}
+
+void Bar::unpureVirtual()
+{
+ cout << "Bar::unpureVirtual()" << endl;
+}
+
diff --git a/tests/libfoo/bar.h b/tests/libfoo/bar.h
new file mode 100644
index 0000000..4a73c2d
--- /dev/null
+++ b/tests/libfoo/bar.h
@@ -0,0 +1,15 @@
+#ifndef BAR_H
+#define BAR_H
+
+#include "foo.h"
+
+class Bar : public Foo
+{
+public:
+ Bar() {}
+ virtual ~Bar() {}
+ virtual void pureVirtual();
+ virtual void unpureVirtual();
+};
+#endif // BAR_H
+
diff --git a/tests/libfoo/foo.cpp b/tests/libfoo/foo.cpp
new file mode 100644
index 0000000..22be350
--- /dev/null
+++ b/tests/libfoo/foo.cpp
@@ -0,0 +1,17 @@
+#include <iostream>
+#include "foo.h"
+
+using namespace std;
+
+void Foo::unpureVirtual()
+{
+ cout << "Foo::unpureVirtual()" << endl;
+}
+
+void Foo::callPureVirtual()
+{
+ cout << "Foo::callPureVirtual() -- calling pureVirtual..." << endl;
+ this->pureVirtual();
+ cout << " -- pureVirtual called." << endl;
+}
+
diff --git a/tests/libfoo/foo.h b/tests/libfoo/foo.h
new file mode 100644
index 0000000..585b844
--- /dev/null
+++ b/tests/libfoo/foo.h
@@ -0,0 +1,14 @@
+#ifndef FOO_H
+#define FOO_H
+
+class Foo
+{
+public:
+ Foo() {}
+ virtual ~Foo() {}
+ virtual void pureVirtual() = 0;
+ virtual void unpureVirtual();
+ virtual void callPureVirtual();
+};
+#endif // FOO_H
+
diff --git a/tests/libfoo/main.cpp b/tests/libfoo/main.cpp
new file mode 100644
index 0000000..6f410ad
--- /dev/null
+++ b/tests/libfoo/main.cpp
@@ -0,0 +1,15 @@
+#include "foo.h"
+#include "bar.h"
+
+int
+main(int argv, char **argc)
+{
+ Bar bar;
+
+ bar.unpureVirtual();
+ bar.pureVirtual();
+ bar.callPureVirtual();
+
+ return 0;
+}
+
diff --git a/tests/sphinxtabletest.cpp b/tests/sphinxtabletest.cpp
new file mode 100644
index 0000000..058a3b5
--- /dev/null
+++ b/tests/sphinxtabletest.cpp
@@ -0,0 +1,269 @@
+/*
+* This file is part of the Boost Python Generator project.
+*
+* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*
+*/
+
+#include "sphinxtabletest.h"
+#include "docgenerator.h"
+#include <QtTest/QTest>
+#include <QDebug>
+
+QString SphinxTableTest::transformXml(const char* xml)
+{
+ return QtXmlToSphinx(m_generator, xml).result();
+}
+
+void SphinxTableTest::setUp()
+{
+ m_generator = new DocGenerator;
+}
+
+void SphinxTableTest::tearDown()
+{
+ delete m_generator;
+}
+
+void SphinxTableTest::testEmptyString()
+{
+ const char* xml = "";
+ QCOMPARE(transformXml(xml), QString());
+}
+
+void SphinxTableTest::testSimpleTable()
+{
+ const char* xml = "\
+<table>\
+ <header>\
+ <item>\
+ <para>Header 1</para>\
+ </item>\
+ <item>\
+ <para>Header 2</para>\
+ </item>\
+ </header>\
+ <row>\
+ <item>\
+ <para>1 1</para>\
+ </item>\
+ <item>\
+ <para>1 2</para>\
+ </item>\
+ </row>\
+ <row>\
+ <item>\
+ <para>2 1</para>\
+ </item>\
+ <item>\
+ <para>2 2</para>\
+ </item>\
+ </row>\
+</table>";
+ QCOMPARE(transformXml(xml), QString("\
+ +--------+--------+\n\
+ |Header 1|Header 2|\n\
+ +--------+--------+\n\
+ |1 1 |1 2 |\n\
+ +--------+--------+\n\
+ |2 1 |2 2 |\n\
+ +--------+--------+\n\
+\n"));
+}
+
+void SphinxTableTest::testColSpan()
+{
+ const char* xml = "\
+<table>\
+ <header>\
+ <item>\
+ <para>Header 1</para>\
+ </item>\
+ <item>\
+ <para>Header 2</para>\
+ </item>\
+ </header>\
+ <row>\
+ <item colspan=\"2\">\
+ <para>I'm a big text!</para>\
+ </item>\
+ </row>\
+ <row>\
+ <item>\
+ <para>2 1</para>\
+ </item>\
+ <item>\
+ <para>2 2</para>\
+ </item>\
+ </row>\
+</table>";
+ QCOMPARE(transformXml(xml), QString("\
+ +---------------+--------+\n\
+ |Header 1 |Header 2|\n\
+ +---------------+--------+\n\
+ |I'm a big text! |\n\
+ +---------------+--------+\n\
+ |2 1 |2 2 |\n\
+ +---------------+--------+\n\
+\n"));
+}
+
+
+void SphinxTableTest::testRowSpan()
+{
+ const char* xml = "\
+<table>\
+ <header>\
+ <item>\
+ <para>Header 1</para>\
+ </item>\
+ <item>\
+ <para>Header 2</para>\
+ </item>\
+ </header>\
+ <row>\
+ <item rowspan=\"2\">\
+ <para>1.1</para>\
+ </item>\
+ <item>\
+ <para>1.2</para>\
+ </item>\
+ </row>\
+ <row>\
+ <item>\
+ <para>2 2</para>\
+ </item>\
+ </row>\
+</table>";
+ QCOMPARE(transformXml(xml), QString("\
+ +--------+--------+\n\
+ |Header 1|Header 2|\n\
+ +--------+--------+\n\
+ |1.1 |1.2 |\n\
+ + +--------+\n\
+ | |2 2 |\n\
+ +--------+--------+\n\
+\n"));
+}
+
+
+void SphinxTableTest::testComplexTable()
+{
+ const char* xml = "\
+<table>\
+ <header>\
+ <item>\
+ <para>Header 1</para>\
+ </item>\
+ <item>\
+ <para>Header 2</para>\
+ </item>\
+ <item>\
+ <para>Header 3</para>\
+ </item>\
+ </header>\
+ <row>\
+ <item rowspan=\"2\">\
+ <para>1.1</para>\
+ </item>\
+ <item colspan=\"2\">\
+ <para>1.2</para>\
+ </item>\
+ </row>\
+ <row>\
+ <item>\
+ <para>2 2</para>\
+ </item>\
+ <item>\
+ <para>2 3</para>\
+ </item>\
+ </row>\
+</table>";
+ QCOMPARE(transformXml(xml), QString("\
+ +--------+--------+--------+\n\
+ |Header 1|Header 2|Header 3|\n\
+ +--------+--------+--------+\n\
+ |1.1 |1.2 |\n\
+ + +--------+--------+\n\
+ | |2 2 |2 3 |\n\
+ +--------+--------+--------+\n\
+\n"));
+}
+
+void SphinxTableTest::testRowSpan2()
+{
+ const char* xml = "\
+<table>\
+ <header>\
+ <item><para>h1</para></item>\
+ <item><para>h2</para></item>\
+ <item><para>h3</para></item>\
+ <item><para>h4</para></item>\
+ </header>\
+ <row>\
+ <item rowspan=\"6\"><para>A</para></item>\
+ <item rowspan=\"6\"><para>B</para></item>\
+ <item><para>C</para></item>\
+ <item><para>D</para></item>\
+ </row>\
+ <row>\
+ <item><para>E</para></item>\
+ <item><para>F</para></item>\
+ </row>\
+ <row>\
+ <item><para>E</para></item>\
+ <item><para>F</para></item>\
+ </row>\
+ <row>\
+ <item><para>E</para></item>\
+ <item><para>F</para></item>\
+ </row>\
+ <row>\
+ <item><para>E</para></item>\
+ <item><para>F</para></item>\
+ </row>\
+ <row>\
+ <item><para>E</para></item>\
+ <item><para>F</para></item>\
+ </row>\
+</table>";
+ QCOMPARE(transformXml(xml), QString("\
+ +--+--+--+--+\n\
+ |h1|h2|h3|h4|\n\
+ +--+--+--+--+\n\
+ |A |B |C |D |\n\
+ + + +--+--+\n\
+ | | |E |F |\n\
+ + + +--+--+\n\
+ | | |E |F |\n\
+ + + +--+--+\n\
+ | | |E |F |\n\
+ + + +--+--+\n\
+ | | |E |F |\n\
+ + + +--+--+\n\
+ | | |E |F |\n\
+ +--+--+--+--+\n\
+\n"));
+}
+
+
+
+QTEST_APPLESS_MAIN( SphinxTableTest )
+
+#include "sphinxtabletest.moc"
diff --git a/tests/sphinxtabletest.h b/tests/sphinxtabletest.h
new file mode 100644
index 0000000..163cc53
--- /dev/null
+++ b/tests/sphinxtabletest.h
@@ -0,0 +1,48 @@
+/*
+* This file is part of the Boost Python Generator project.
+*
+* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*
+*/
+
+#ifndef SPHINXTABLETEST_H
+#define SPHINXTABLETEST_H
+
+#include <QObject>
+
+class DocGenerator;
+class SphinxTableTest : public QObject {
+ Q_OBJECT
+
+private slots:
+ void setUp();
+ void tearDown();
+ void testEmptyString();
+ void testSimpleTable();
+ void testRowSpan();
+ void testColSpan();
+ void testComplexTable();
+ void testRowSpan2();
+private:
+ DocGenerator* m_generator;
+
+ QString transformXml(const char* xml);
+};
+
+#endif