diff --git a/.gitignore b/.gitignore index fa13dcc5..40d69886 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,3 @@ build .preprocessed.tmp .*.swp *.kdev4 -doc/_build diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f72ef81..ba40b23c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -include(icecc.cmake) +Include(icecc.cmake) project(shiboken) cmake_minimum_required(VERSION 2.6) @@ -6,22 +6,40 @@ cmake_minimum_required(VERSION 2.6) set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules/ ${CMAKE_MODULE_PATH}) -find_package(Qt4 4.5.0 REQUIRED) -find_package(ApiExtractor 0.8 REQUIRED) -find_package(GeneratorRunner 0.6.1 REQUIRED) -find_package(PythonLibs REQUIRED) -find_package(PythonInterpWithDebug REQUIRED) +find_package(Qt4 4.5.0) +find_package(ApiExtractor 0.10.11 REQUIRED) +find_package(GeneratorRunner 0.6.17 REQUIRED) add_definitions(${QT_DEFINITIONS}) -option(AVOID_PROTECTED_HACK "Avoid protected hack on generated bindings." FALSE) +set(shiboken_MAJOR_VERSION "1") +set(shiboken_MINOR_VERSION "1") +set(shiboken_MICRO_VERSION "1") +set(shiboken_VERSION "${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VERSION}.${shiboken_MICRO_VERSION}") + option(BUILD_TESTS "Build tests." TRUE) -option(ENABLE_VERSION_SUFFIX "Used to use current version in suffix to generated files. This is used to allow multiples versions installed simultaneous." FALSE) +option(USE_PYTHON3 "Use python3 libraries to build shiboken." FALSE) + +if (USE_PYTHON3) + find_package(Python3Libs) + find_package(Python3InterpWithDebug) + #use commom vars + set(PYTHONLIBS_FOUND ${PYTHON3LIBS_FOUND}) + set(PYTHON_LIBRARIES ${PYTHON3_LIBRARIES}) + set(PYTHON_INCLUDE_DIRS ${PYTHON3_INCLUDE_DIRS}) + set(PYTHON_DEBUG_LIBRARIES ${PYTHON3_DEBUG_LIBRARIES}) + set(PYTHONINTERP_FOUND ${PYTHON3INTERP_FOUND}) + set(PYTHON_EXECUTABLE ${PYTHON3_EXECUTABLE}) +else() + find_package(PythonLibs 2.6) + find_package(PythonInterpWithDebug) +endif() + if(MSVC) set(CMAKE_CXX_FLAGS "/Zc:wchar_t- /GR /EHsc /DWIN32 /D_WINDOWS /D_SCL_SECURE_NO_WARNINGS") else() - if(CMAKE_HOST_UNIX) + if(CMAKE_HOST_UNIX AND NOT CYGWIN) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fvisibility=hidden -Wno-strict-aliasing") endif() set(CMAKE_CXX_FLAGS_DEBUG "-g") @@ -35,58 +53,15 @@ else() endif() endif() -if (WIN32) - set(PATH_SEP "\;") -else() - set(PATH_SEP ":") -endif() - -if(WIN32 OR AVOID_PROTECTED_HACK) - message(STATUS "Avoiding protected hack!") - add_definitions("-DAVOID_PROTECTED_HACK") -else() - message(STATUS "Using protected hack!") -endif() - set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE) -set(shiboken_MAJOR_VERSION "0") -set(shiboken_MINOR_VERSION "5") -set(shiboken_MICRO_VERSION "0") -set(shiboken_VERSION "${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VERSION}.${shiboken_MICRO_VERSION}") -if(ENABLE_VERSION_SUFFIX) - set(shiboken_SUFFIX "-${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VERSION}") +if (WIN32) + set(PATH_SEP "\;") else() - set(shiboken_SUFFIX "") + set(PATH_SEP ":") endif() -set(shiboken_SRC -cppgenerator.cpp -headergenerator.cpp -overloaddata.cpp -shiboken.cpp -shibokengenerator.cpp -) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${APIEXTRACTOR_INCLUDE_DIR} - ${GENERATORRUNNER_INCLUDE_DIR} - ${QT_INCLUDE_DIR} - ${QT_QTCORE_INCLUDE_DIR}) - -add_library(shiboken_generator SHARED ${shiboken_SRC}) -set_property(TARGET shiboken_generator PROPERTY PREFIX "") - -target_link_libraries(shiboken_generator - ${APIEXTRACTOR_LIBRARY} - ${GENERATORRUNNER_LIBRARY} - ${QT_QTCORE_LIBRARY}) - -add_executable(shiboken main.cpp) -set_target_properties(shiboken PROPERTIES OUTPUT_NAME shiboken${shiboken_SUFFIX}) -target_link_libraries(shiboken ${QT_QTCORE_LIBRARY}) - # uninstall target configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" @@ -94,39 +69,53 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake" add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") -# Detect if the python libs were compiled in debug mode -execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "from distutils import sysconfig; \\ - print sysconfig.get_config_var('Py_DEBUG')" - OUTPUT_VARIABLE PY_DEBUG - OUTPUT_STRIP_TRAILING_WHITESPACE) - +set(SHIBOKEN_BUILD_TYPE "Release") if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(NOT PYTHON_DEBUG_LIBRARIES) message(FATAL_ERROR "Python debug library not found. Try compile shiboken with -DCMAKE_BUILD_TYPE=Release") endif() - if(NOT PY_DEBUG) + if(NOT PYTHON_WITH_DEBUG) message(WARNING "Compiling shiboken with debug enabled, but the python executable was not compiled with debug support.") else() add_definitions("-DPy_DEBUG") + set(SBK_ADD_PY_DEBUG_DEFINITION "add_definitions(\"-DPy_DEBUG\")") + set(SBK_PKG_CONFIG_PY_DEBUG_DEFINITION " -DPy_DEBUG") endif() set(SBK_PYTHON_LIBRARIES ${PYTHON_DEBUG_LIBRARIES}) + set(SHIBOKEN_BUILD_TYPE "Debug") else() set(SBK_PYTHON_LIBRARIES ${PYTHON_LIBRARIES}) add_definitions("-DNDEBUG") endif() +if(APPLE) + set(SBK_PYTHON_LIBRARIES "-undefined dynamic_lookup") +endif() -if (BUILD_TESTS) - enable_testing() +if(CMAKE_VERSION VERSION_LESS 2.8) + set(SBK_PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_PATH}) +else() + set(SBK_PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_DIRS}) endif() add_subdirectory(libshiboken) +add_subdirectory(doc) -if (BUILD_TESTS) - add_subdirectory(tests) +# deps found, compile the generator. +if (QT4_FOUND AND ApiExtractor_FOUND AND GeneratorRunner_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND) + add_subdirectory(generator) + add_subdirectory(shibokenmodule) + + if (BUILD_TESTS) + enable_testing() + add_subdirectory(tests) + endif() +else() + message(WARNING "Some dependencies were not found, shiboken generator compilation disabled!") endif() + add_subdirectory(data) +# dist target set(ARCHIVE_NAME ${CMAKE_PROJECT_NAME}-${shiboken_VERSION}) add_custom_target(dist COMMAND mkdir -p "${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}" && @@ -137,8 +126,4 @@ add_custom_target(dist echo "Source package created at ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar.bz2.\n" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) -add_dependencies(shiboken shiboken_generator) - -install(TARGETS shiboken_generator DESTINATION "${GENERATORRUNNER_PLUGIN_DIR}") -install(TARGETS shiboken DESTINATION bin) diff --git a/Doxyfile b/Doxyfile deleted file mode 100644 index 24289839..00000000 --- a/Doxyfile +++ /dev/null @@ -1,311 +0,0 @@ -# Doxyfile 1.5.7.1 - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = "CPython 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/cpythonbackend/ -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/cpythonbackend -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 = cpythonbackend.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/cmake/Modules/FindPython3Interp.cmake b/cmake/Modules/FindPython3Interp.cmake new file mode 100644 index 00000000..373982e2 --- /dev/null +++ b/cmake/Modules/FindPython3Interp.cmake @@ -0,0 +1,48 @@ +# - Find python interpreter +# This module finds if Python interpreter is installed and determines where the +# executables are. This code sets the following variables: +# +# PYTHONINTERP3_FOUND - Was the Python executable found +# PYTHON3_EXECUTABLE - path to the Python interpreter +# + +#============================================================================= +# Copyright 2005-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distributed this file outside of CMake, substitute the full +# License text for the above reference.) + +FIND_PROGRAM(PYTHON3_EXECUTABLE + NAMES python3.2mu python3.2m python3.2u python3.2 python3.1 python3.0 python3 + PATHS + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.2\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.1\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.0\\InstallPath] + ) + +FIND_PROGRAM(PYTHON3_DBG_EXECUTABLE + NAMES python3.2dmu python3.2dm python3.2du python3.2d python3.1-dbg python3.0-dbg python3-dbg + PATHS + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.2\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.1\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.0\\InstallPath] + ) + + +# handle the QUIETLY and REQUIRED arguments and set PYTHONINTERP_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Python3Interp DEFAULT_MSG PYTHON3_EXECUTABLE) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Python3InterpDbg DEFAULT_MSG PYTHON3_DBG_EXECUTABLE) + +MARK_AS_ADVANCED(PYTHON3_EXECUTABLE) +MARK_AS_ADVANCED(PYTHON3_DBG_EXECUTABLE) + + diff --git a/cmake/Modules/FindPython3InterpWithDebug.cmake b/cmake/Modules/FindPython3InterpWithDebug.cmake new file mode 100644 index 00000000..23087e65 --- /dev/null +++ b/cmake/Modules/FindPython3InterpWithDebug.cmake @@ -0,0 +1,50 @@ +INCLUDE(FindPython3Interp) +INCLUDE(FindPython3Libs) + +find_package(Python3Interp REQUIRED) + +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + # This is for Debian + set(PYTHON3_EXECUTABLE_TMP "${PYTHON3_DBG_EXECUTABLE}") + + # Fall back to the standard interpreter. + if(NOT EXISTS "${PYTHON3_EXECUTABLE_TMP}") + set(PYTHON3_EXECUTABLE_TMP "${PYTHON3_EXECUTABLE}") + endif() + + set(PYTHON3_EXECUTABLE "${PYTHON3_EXECUTABLE_TMP}") +endif() + +# Detect if the python libs were compiled in debug mode +execute_process( + COMMAND ${PYTHON3_EXECUTABLE} -c "from distutils import sysconfig; \\ + print(bool(sysconfig.get_config_var('Py_DEBUG')))" + OUTPUT_VARIABLE PYTHON_WITH_DEBUG + OUTPUT_STRIP_TRAILING_WHITESPACE) + +message("PYTHON WITH DEBUG: ${PYTHON3_EXECUTABLE}") + +execute_process( + COMMAND ${PYTHON3_EXECUTABLE} -c "import sys; \\ + from distutils import sysconfig; \\ + vr = sys.version_info; \\ + prefix = '-python%d.%d' % (vr[0], vr[1]); \\ + suffix = prefix + '-dbg' if bool(sysconfig.get_config_var('Py_DEBUG')) else prefix; \\ + suffix = '.' + sysconfig.get_config_var('SOABI') if (vr.major == 3 and vr.minor >= 2) else suffix; \\ + print(suffix)" + OUTPUT_VARIABLE PYTHON_SUFFIX + OUTPUT_STRIP_TRAILING_WHITESPACE) + +#Fix missing variable on UNIX env +if(NOT PYTHON3_DEBUG_LIBRARIES AND UNIX) + string(REPLACE "-dbg" "" PYTHON_NAME_AUX ${PYTHON_SUFFIX}) + string(REPLACE "-python" "python" PYTHON_NAME ${PYTHON_NAME_AUX}) + find_library(LIBRARY_FOUND ${PYTHON_NAME}_d) + if (LIBRARY_FOUND) + set(PYTHON3_DEBUG_LIBRARIES "${LIBRARY_FOUND}") + else() + set(PYTHON3_DEBUG_LIBRARIES "${PYTHON3_LIBRARIES}") + endif() +endif() + + diff --git a/cmake/Modules/FindPython3Libs.cmake b/cmake/Modules/FindPython3Libs.cmake new file mode 100644 index 00000000..03fe8b80 --- /dev/null +++ b/cmake/Modules/FindPython3Libs.cmake @@ -0,0 +1,210 @@ +# - Find python libraries +# This module finds if Python is installed and determines where the +# include files and libraries are. It also determines what the name of +# the library is. This code sets the following variables: +# +# PYTHONLIBS3_FOUND - have the Python libs been found +# PYTHON3_LIBRARIES - path to the python library +# PYTHON3_INCLUDE_DIRS - path to where Python.h is found +# PYTHON3_DEBUG_LIBRARIES - path to the debug library +# + +#============================================================================= +# Copyright 2001-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distributed this file outside of CMake, substitute the full +# License text for the above reference.) + +INCLUDE(CMakeFindFrameworks) +# Is there a python3 framework? How do we search for it? +# Search for the python framework on Apple. +# CMAKE_FIND_FRAMEWORKS(Python) + +FOREACH(_CURRENT_VERSION 3.2 3.1 3.0) + IF(_CURRENT_VERSION GREATER 3.1) + SET(_32FLAGS "m" "u" "mu" "") + ELSE() + SET(_32FLAGS "") + ENDIF() + FOREACH(_COMPILATION_FLAGS ${_32FLAGS}) + STRING(REPLACE "." "" _CURRENT_VERSION_NO_DOTS ${_CURRENT_VERSION}) + IF(WIN32) + IF(_CURRENT_VERSION GREATER 3.1) + FIND_LIBRARY(PYTHON3_DEBUG_LIBRARY + NAMES python${_CURRENT_VERSION_NO_DOTS}d${_COMPILATION_FLAGS} python + PATHS + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs/Debug + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs ) + ELSE() + FIND_LIBRARY(PYTHON3_DEBUG_LIBRARY + NAMES python${_CURRENT_VERSION_NO_DOTS}${_COMPILATION_FLAGS}_d python + PATHS + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs/Debug + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs ) + ENDIF() + ENDIF(WIN32) + + FIND_LIBRARY(PYTHON3_LIBRARY + NAMES python${_CURRENT_VERSION_NO_DOTS}${_COMPILATION_FLAGS} python${_CURRENT_VERSION}${_COMPILATION_FLAGS} + PATHS + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs + # Avoid finding the .dll in the PATH. We want the .lib. + NO_SYSTEM_ENVIRONMENT_PATH + ) + # Look for the static library in the Python config directory + FIND_LIBRARY(PYTHON3_LIBRARY + NAMES python${_CURRENT_VERSION_NO_DOTS}${_COMPILATION_FLAGS} python${_CURRENT_VERSION}${_COMPILATION_FLAGS} + # Avoid finding the .dll in the PATH. We want the .lib. + NO_SYSTEM_ENVIRONMENT_PATH + # This is where the static library is usually located + PATH_SUFFIXES python${_CURRENT_VERSION}/config + ) + + IF(_CURRENT_VERSION GREATER 3.1) + FIND_LIBRARY(PYTHON3_DEBUG_LIBRARY + NAMES python${_CURRENT_VERSION_NO_DOTS}d${_COMPILATION_FLAGS} python${_CURRENT_VERSION}d${_COMPILATION_FLAGS} + PATHS + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs + # Avoid finding the .dll in the PATH. We want the .lib. + NO_SYSTEM_ENVIRONMENT_PATH + ) + # Look for the static library in the Python config directory + FIND_LIBRARY(PYTHON3_DEBUG_LIBRARY + NAMES python${_CURRENT_VERSION_NO_DOTS}d${_COMPILATION_FLAGS} python${_CURRENT_VERSION}d${_COMPILATION_FLAGS} + # Avoid finding the .dll in the PATH. We want the .lib. + NO_SYSTEM_ENVIRONMENT_PATH + # This is where the static library is usually located + PATH_SUFFIXES python${_CURRENT_VERSION}/config + ) + ENDIF() + +# SET(PYTHON_FRAMEWORK_INCLUDES) +# IF(Python_FRAMEWORKS AND NOT PYTHON_INCLUDE_DIR) +# FOREACH(dir ${Python_FRAMEWORKS}) +# SET(PYTHON_FRAMEWORK_INCLUDES ${PYTHON_FRAMEWORK_INCLUDES} +# ${dir}/Versions/${_CURRENT_VERSION}/include/python${_CURRENT_VERSION}) +# ENDFOREACH(dir) +# ENDIF(Python_FRAMEWORKS AND NOT PYTHON_INCLUDE_DIR) + + FIND_PATH(PYTHON3_INCLUDE_DIR + NAMES Python.h + PATHS + ${PYTHON_FRAMEWORK_INCLUDES} + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/include + PATH_SUFFIXES + python${_CURRENT_VERSION}${_COMPILATION_FLAGS} + ) + + # For backward compatibility, set PYTHON_INCLUDE_PATH, but make it internal. + SET(PYTHON_INCLUDE_PATH "${PYTHON_INCLUDE_DIR}" CACHE INTERNAL + "Path to where Python.h is found (deprecated)") + ENDFOREACH(_COMPILATION_FLAGS) +ENDFOREACH(_CURRENT_VERSION) + +MARK_AS_ADVANCED( + PYTHON3_DEBUG_LIBRARY + PYTHON3_LIBRARY + PYTHON3_INCLUDE_DIR +) + +# We use PYTHON3_INCLUDE_DIR, PYTHON3_LIBRARY and PYTHON3_DEBUG_LIBRARY for the +# cache entries because they are meant to specify the location of a single +# library. We now set the variables listed by the documentation for this +# module. +SET(PYTHON3_INCLUDE_DIRS "${PYTHON3_INCLUDE_DIR}") +SET(PYTHON3_LIBRARIES "${PYTHON3_LIBRARY}") +SET(PYTHON3_DEBUG_LIBRARIES "${PYTHON3_DEBUG_LIBRARY}") + + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Python3Libs DEFAULT_MSG PYTHON3_LIBRARIES PYTHON3_INCLUDE_DIRS) + + +# PYTHON_ADD_MODULE( src1 src2 ... srcN) is used to build modules for python. +# PYTHON_WRITE_MODULES_HEADER() writes a header file you can include +# in your sources to initialize the static python modules + +GET_PROPERTY(_TARGET_SUPPORTS_SHARED_LIBS + GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS) + +FUNCTION(PYTHON3_ADD_MODULE _NAME ) + OPTION(PYTHON3_ENABLE_MODULE_${_NAME} "Add module ${_NAME}" TRUE) + OPTION(PYTHON3_MODULE_${_NAME}_BUILD_SHARED + "Add module ${_NAME} shared" ${_TARGET_SUPPORTS_SHARED_LIBS}) + + # Mark these options as advanced + MARK_AS_ADVANCED(PYTHON3_ENABLE_MODULE_${_NAME} + PYTHON3_MODULE_${_NAME}_BUILD_SHARED) + + IF(PYTHON3_ENABLE_MODULE_${_NAME}) + IF(PYTHON3_MODULE_${_NAME}_BUILD_SHARED) + SET(PY_MODULE_TYPE MODULE) + ELSE(PYTHON3_MODULE_${_NAME}_BUILD_SHARED) + SET(PY_MODULE_TYPE STATIC) + SET_PROPERTY(GLOBAL APPEND PROPERTY PY_STATIC_MODULES_LIST ${_NAME}) + ENDIF(PYTHON3_MODULE_${_NAME}_BUILD_SHARED) + + SET_PROPERTY(GLOBAL APPEND PROPERTY PY_MODULES_LIST ${_NAME}) + ADD_LIBRARY(${_NAME} ${PY_MODULE_TYPE} ${ARGN}) +# TARGET_LINK_LIBRARIES(${_NAME} ${PYTHON_LIBRARIES}) + + ENDIF(PYTHON3_ENABLE_MODULE_${_NAME}) +ENDFUNCTION(PYTHON3_ADD_MODULE) + +FUNCTION(PYTHON3_WRITE_MODULES_HEADER _filename) + + GET_PROPERTY(PY_STATIC_MODULES_LIST GLOBAL PROPERTY PY_STATIC_MODULES_LIST) + + GET_FILENAME_COMPONENT(_name "${_filename}" NAME) + STRING(REPLACE "." "_" _name "${_name}") + STRING(TOUPPER ${_name} _nameUpper) + + SET(_filenameTmp "${_filename}.in") + FILE(WRITE ${_filenameTmp} "/*Created by cmake, do not edit, changes will be lost*/\n") + FILE(APPEND ${_filenameTmp} +"#ifndef ${_nameUpper} +#define ${_nameUpper} + +#include + +#ifdef __cplusplus +extern \"C\" { +#endif /* __cplusplus */ + +") + + FOREACH(_currentModule ${PY_STATIC_MODULES_LIST}) + FILE(APPEND ${_filenameTmp} "extern void init${PYTHON_MODULE_PREFIX}${_currentModule}(void);\n\n") + ENDFOREACH(_currentModule ${PY_STATIC_MODULES_LIST}) + + FILE(APPEND ${_filenameTmp} +"#ifdef __cplusplus +} +#endif /* __cplusplus */ + +") + + + FOREACH(_currentModule ${PY_STATIC_MODULES_LIST}) + FILE(APPEND ${_filenameTmp} "int ${_name}_${_currentModule}(void) \n{\n static char name[]=\"${PYTHON_MODULE_PREFIX}${_currentModule}\"; return PyImport_AppendInittab(name, init${PYTHON_MODULE_PREFIX}${_currentModule});\n}\n\n") + ENDFOREACH(_currentModule ${PY_STATIC_MODULES_LIST}) + + FILE(APPEND ${_filenameTmp} "void ${_name}_LoadAllPythonModules(void)\n{\n") + FOREACH(_currentModule ${PY_STATIC_MODULES_LIST}) + FILE(APPEND ${_filenameTmp} " ${_name}_${_currentModule}();\n") + ENDFOREACH(_currentModule ${PY_STATIC_MODULES_LIST}) + FILE(APPEND ${_filenameTmp} "}\n\n") + FILE(APPEND ${_filenameTmp} "#ifndef EXCLUDE_LOAD_ALL_FUNCTION\nvoid CMakeLoadAllPythonModules(void)\n{\n ${_name}_LoadAllPythonModules();\n}\n#endif\n\n#endif\n") + +# with CONFIGURE_FILE() cmake complains that you may not use a file created using FILE(WRITE) as input file for CONFIGURE_FILE() + EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_filenameTmp}" "${_filename}" OUTPUT_QUIET ERROR_QUIET) + +ENDFUNCTION(PYTHON3_WRITE_MODULES_HEADER) + diff --git a/cmake/Modules/FindPythonInterpWithDebug.cmake b/cmake/Modules/FindPythonInterpWithDebug.cmake index 264dd5d8..7722d956 100644 --- a/cmake/Modules/FindPythonInterpWithDebug.cmake +++ b/cmake/Modules/FindPythonInterpWithDebug.cmake @@ -1,21 +1,53 @@ -INCLUDE(FindPythonInterp) +find_program(PYTHON_EXECUTABLE NAMES python2.7 python2.6 python2.5) -find_package(PythonInterp REQUIRED) - -#Fix missing variable on UNIX env -if(NOT PYTHON_DEBUG_LIBRARIES AND UNIX) - set(PYTHON_DEBUG_LIBRARIES "${PYTHON_LIBRARIES}") +if (NOT PYTHON_EXECUTABLE) + find_package(PythonInterp REQUIRED) +else() + set(PYTHONINTERP_FOUND 1) endif() -if(PYTHONINTERP_FOUND AND UNIX AND CMAKE_BUILD_TYPE STREQUAL "Debug") +if (PYTHONINTERP_FOUND AND UNIX AND CMAKE_BUILD_TYPE STREQUAL "Debug") # This is for Debian set(PYTHON_EXECUTABLE_TMP "${PYTHON_EXECUTABLE}-dbg") - # Fall back to the standard interpreter. - if(NOT EXISTS "${PYTHON_EXECUTABLE_TMP}") + if (NOT EXISTS "${PYTHON_EXECUTABLE_TMP}") + # On Fedora we usually have the suffix as debug. As we didn't + # find python interpreter with the suffix dbg we'll fall back + # to the suffix as debug. + set(PYTHON_EXECUTABLE_TMP "${PYTHON_EXECUTABLE}-debug") + endif() + # Falling back to the standard interpreter. + if (NOT EXISTS "${PYTHON_EXECUTABLE_TMP}") set(PYTHON_EXECUTABLE_TMP "${PYTHON_EXECUTABLE}") endif() set(PYTHON_EXECUTABLE "${PYTHON_EXECUTABLE_TMP}") endif() +# Detect if the python libs were compiled in debug mode +execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c "from distutils import sysconfig; \\ + print bool(sysconfig.get_config_var('Py_DEBUG'))" + OUTPUT_VARIABLE PYTHON_WITH_DEBUG + OUTPUT_STRIP_TRAILING_WHITESPACE) + +execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c "import sys; \\ + from distutils import sysconfig; \\ + vr = sys.version_info; \\ + suffix = '-dbg' if bool(sysconfig.get_config_var('Py_DEBUG')) else ''; \\ + print '-python%d.%d%s' % (vr[0], vr[1], suffix)" + OUTPUT_VARIABLE PYTHON_SUFFIX + OUTPUT_STRIP_TRAILING_WHITESPACE) + +# Fix missing variable on UNIX env +if (NOT PYTHON_DEBUG_LIBRARIES AND UNIX) + string(REPLACE "-dbg" "" PYTHON_NAME_TMP ${PYTHON_SUFFIX}) + string(REPLACE "-python" "python" PYTHON_NAME ${PYTHON_NAME_TMP}) + find_library(LIBRARY_FOUND ${PYTHON_NAME}_d) + if (LIBRARY_FOUND) + set(PYTHON_DEBUG_LIBRARIES "${LIBRARY_FOUND}") + else() + set(PYTHON_DEBUG_LIBRARIES "${PYTHON_LIBRARIES}") + endif() +endif() diff --git a/cppgenerator.cpp b/cppgenerator.cpp deleted file mode 100644 index 507ef7f2..00000000 --- a/cppgenerator.cpp +++ /dev/null @@ -1,3875 +0,0 @@ -/* - * This file is part of the Shiboken Python Bindings Generator project. - * - * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: PySide team - * - * 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 -#include - -#include -#include -#include - -inline CodeSnipList getConversionRule(TypeSystem::Language lang, const AbstractMetaFunction *function) -{ - CodeSnipList list; - - foreach(AbstractMetaArgument *arg, function->arguments()) { - QString convRule = function->conversionRule(lang, arg->argumentIndex() + 1); - if (!convRule.isEmpty()) { - CodeSnip snip(0, TypeSystem::TargetLangCode); - snip.position = CodeSnip::Beginning; - - convRule.replace("%in", arg->name()); - convRule.replace("%out", arg->name() + "_out"); - - snip.addCode(convRule); - list << snip; - } - - } - return list; -} - -// utiliy functions -inline CodeSnipList getReturnConversionRule(TypeSystem::Language lang, - const AbstractMetaFunction *function, - const QString& inputName, - const QString& outputName) -{ - CodeSnipList list; - - QString convRule = function->conversionRule(lang, 0); - if (!convRule.isEmpty()) { - CodeSnip snip(0, lang); - snip.position = CodeSnip::Beginning; - - convRule.replace("%in", inputName); - convRule.replace("%out", outputName); - - snip.addCode(convRule); - list << snip; - } - - return list; -} - - -CppGenerator::CppGenerator() : m_currentErrorCode(0) -{ - // sequence protocol functions - typedef QPair StrPair; - m_sequenceProtocol.insert("__len__", StrPair("PyObject* self", "Py_ssize_t")); - m_sequenceProtocol.insert("__getitem__", StrPair("PyObject* self, Py_ssize_t _i", "PyObject*")); - m_sequenceProtocol.insert("__setitem__", StrPair("PyObject* self, Py_ssize_t _i, PyObject* _value", "int")); - m_sequenceProtocol.insert("__getslice__", StrPair("PyObject* self, Py_ssize_t _i1, Py_ssize_t _i2", "PyObject*")); - m_sequenceProtocol.insert("__setslice__", StrPair("PyObject* self, Py_ssize_t _i1, Py_ssize_t _i2, PyObject* _value", "int")); - m_sequenceProtocol.insert("__contains__", StrPair("PyObject* self, PyObject* _value", "int")); - m_sequenceProtocol.insert("__concat__", StrPair("PyObject* self, PyObject* _other", "PyObject*")); -} - -QString CppGenerator::fileNameForClass(const AbstractMetaClass *metaClass) const -{ - return metaClass->qualifiedCppName().toLower().replace("::", "_") + QLatin1String("_wrapper.cpp"); -} - -QList CppGenerator::filterGroupedOperatorFunctions(const AbstractMetaClass* metaClass, - uint query) -{ - // ( func_name, num_args ) => func_list - QMap, AbstractMetaFunctionList> results; - foreach (AbstractMetaFunction* func, metaClass->operatorOverloads(query)) { - if (func->isModifiedRemoved() || func->name() == "operator[]" || func->name() == "operator->") - continue; - int args; - if (func->isComparisonOperator()) { - args = -1; - } else { - args = func->arguments().size(); - } - QPair op(func->name(), args); - results[op].append(func); - } - return results.values(); -} - -/*! - Function used to write the class generated binding code on the buffer - \param s the output buffer - \param metaClass the pointer to metaclass information -*/ -void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaClass) -{ - ReportHandler::debugSparse("Generating wrapper implementation for " + metaClass->fullName()); - - // write license comment - s << licenseComment() << endl; - -#ifndef AVOID_PROTECTED_HACK - if (!metaClass->isNamespace() && !metaClass->hasPrivateDestructor()) { - s << "//workaround to access protected functions" << endl; - s << "#define protected public" << endl << endl; - } -#endif - - // headers - s << "// default includes" << endl; - s << "#include " << endl; - s << "#include " << endl; - s << "#include " << endl; - if (usePySideExtensions()) { - s << "#include " << endl; - s << "#include " << endl; - s << "#include " << endl; - } - - s << "#include \n"; - s << "#include \n"; - if (usePySideExtensions()) { - if (metaClass->isQObject()) { - s << "#include \n"; - s << "#include \n"; - } - } - - // The multiple inheritance initialization function - // needs the 'set' class from C++ STL. - if (hasMultipleInheritanceInAncestry(metaClass)) - s << "#include " << endl; - - s << "#include \"" << getModuleHeaderFileName() << '"' << endl << endl; - - QString headerfile = fileNameForClass(metaClass); - headerfile.replace("cpp", "h"); - s << "#include \"" << headerfile << '"' << endl; - foreach (AbstractMetaClass* innerClass, metaClass->innerClasses()) { - if (shouldGenerate(innerClass)) { - QString headerfile = fileNameForClass(innerClass); - headerfile.replace("cpp", "h"); - s << "#include \"" << headerfile << '"' << endl; - } - } - - //Extra includes - s << endl << "// Extra includes" << endl; - QList includes = metaClass->typeEntry()->extraIncludes(); - qSort(includes.begin(), includes.end()); - foreach (Include inc, includes) - s << inc.toString() << endl; - s << endl; - - if (metaClass->typeEntry()->typeFlags() & ComplexTypeEntry::Deprecated) - s << "#Deprecated" << endl; - - s << "using namespace Shiboken;" << endl; - - //Use class base namespace - const AbstractMetaClass *context = metaClass->enclosingClass(); - while(context) { - if (context->isNamespace() && !context->enclosingClass()) { - s << "using namespace " << context->qualifiedCppName() << ";" << endl; - break; - } - context = context->enclosingClass(); - } - - s << endl; - - // class inject-code native/beginning - if (!metaClass->typeEntry()->codeSnips().isEmpty()) { - writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), CodeSnip::Beginning, TypeSystem::NativeCode, 0, 0, metaClass); - s << endl; - } - - if (shouldGenerateCppWrapper(metaClass)) { - s << "// Native ---------------------------------------------------------" << endl; - s << endl; - - foreach (const AbstractMetaFunction* func, filterFunctions(metaClass)) { - if ((func->isPrivate() && !visibilityModifiedToPrivate(func)) - || (func->isModifiedRemoved() && !func->isAbstract())) - continue; - if (func->isConstructor() && !func->isCopyConstructor() && !func->isUserAdded()) - writeConstructorNative(s, func); -#ifdef AVOID_PROTECTED_HACK - else if (!metaClass->hasPrivateDestructor() && (func->isVirtual() || func->isAbstract())) -#else - else if (func->isVirtual() || func->isAbstract()) -#endif - writeVirtualMethodNative(s, func); - } - -#ifdef AVOID_PROTECTED_HACK - if (!metaClass->hasPrivateDestructor()) { -#endif - - if (usePySideExtensions() && metaClass->isQObject()) - writeMetaObjectMethod(s, metaClass); - - writeDestructorNative(s, metaClass); - -#ifdef AVOID_PROTECTED_HACK - } -#endif - } - - Indentation indentation(INDENT); - - QString methodsDefinitions; - QTextStream md(&methodsDefinitions); - QString singleMethodDefinitions; - QTextStream smd(&singleMethodDefinitions); - - bool hasComparisonOperator = metaClass->hasComparisonOperatorOverload(); - bool typeAsNumber = metaClass->hasArithmeticOperatorOverload() || metaClass->hasLogicalOperatorOverload() || metaClass->hasBitwiseOperatorOverload(); - - s << endl << "// Target ---------------------------------------------------------" << endl << endl; - s << "extern \"C\" {" << endl; - foreach (AbstractMetaFunctionList allOverloads, getFunctionGroups(metaClass).values()) { - AbstractMetaFunctionList overloads; - foreach (AbstractMetaFunction* func, allOverloads) { - if (!func->isAssignmentOperator() - && !func->isCastOperator() - && !func->isModifiedRemoved() - && (!func->isPrivate() || func->functionType() == AbstractMetaFunction::EmptyFunction) - && func->ownerClass() == func->implementingClass()) - overloads.append(func); - } - - if (overloads.isEmpty()) - continue; - - const AbstractMetaFunction* rfunc = overloads.first(); - if (m_sequenceProtocol.contains(rfunc->name())) - continue; - - if (rfunc->isConstructor()) - writeConstructorWrapper(s, overloads); - - if (!rfunc->isConstructor() && !rfunc->isOperatorOverload()) { - writeMethodWrapper(s, overloads); - if (OverloadData::hasStaticAndInstanceFunctions(overloads)) { - QString methDefName = cpythonMethodDefinitionName(rfunc); - smd << "static PyMethodDef " << methDefName << " = {" << endl; - smd << INDENT; - writeMethodDefinitionEntry(smd, overloads); - smd << endl << "};" << endl << endl; - } - writeMethodDefinition(md, overloads); - } - } - - QString className = cpythonTypeName(metaClass).replace(QRegExp("_Type$"), ""); - - // Write single method definitions - s << singleMethodDefinitions; - - // Write methods definition - s << "static PyMethodDef " << className << "_methods[] = {" << endl; - s << methodsDefinitions << INDENT << "{0} // Sentinel" << endl; - s << "};" << endl << endl; - - // Write tp_getattro function - if (usePySideExtensions() && metaClass->qualifiedCppName() == "QObject") { - writeGetattroFunction(s, metaClass); - s << endl; - writeSetattroFunction(s, metaClass); - s << endl; - } else if (classNeedsGetattroFunction(metaClass)) { - writeGetattroFunction(s, metaClass); - s << endl; - } - - if (typeAsNumber) { - QList opOverloads = filterGroupedOperatorFunctions( - metaClass, - AbstractMetaClass::ArithmeticOp - | AbstractMetaClass::LogicalOp - | AbstractMetaClass::BitwiseOp); - - foreach (AbstractMetaFunctionList allOverloads, opOverloads) { - AbstractMetaFunctionList overloads; - foreach (AbstractMetaFunction* func, allOverloads) { - if (!func->isModifiedRemoved() - && !func->isPrivate() - && (func->ownerClass() == func->implementingClass() || func->isAbstract())) - overloads.append(func); - } - - if (overloads.isEmpty()) - continue; - - writeMethodWrapper(s, overloads); - } - - s << "// type has number operators" << endl; - writeTypeAsNumberDefinition(s, metaClass); - } - - if (supportsSequenceProtocol(metaClass)) { - writeSequenceMethods(s, metaClass); - writeTypeAsSequenceDefinition(s, metaClass); - } - - if (hasComparisonOperator) { - s << "// Rich comparison" << endl; - writeRichCompareFunction(s, metaClass); - } - - if (shouldGenerateGetSetList(metaClass)) { - foreach (const AbstractMetaField* metaField, metaClass->fields()) { - if (metaField->isStatic()) - continue; - writeGetterFunction(s, metaField); - if (!metaField->type()->isConstant()) - writeSetterFunction(s, metaField); - s << endl; - } - - s << "// Getters and Setters for " << metaClass->name() << endl; - s << "static PyGetSetDef " << cpythonGettersSettersDefinitionName(metaClass) << "[] = {" << endl; - foreach (const AbstractMetaField* metaField, metaClass->fields()) { - if (metaField->isStatic()) - continue; - - bool hasSetter = !metaField->type()->isConstant(); - s << INDENT << "{const_cast(\"" << metaField->name() << "\"), "; - s << cpythonGetterFunctionName(metaField); - s << ", " << (hasSetter ? cpythonSetterFunctionName(metaField) : "0"); - s << "}," << endl; - } - s << INDENT << "{0} // Sentinel" << endl; - s << "};" << endl << endl; - } - - s << "} // extern \"C\"" << endl << endl; - - if (!metaClass->typeEntry()->hashFunction().isEmpty()) - writeHashFunction(s, metaClass); - writeObjCopierFunction(s, metaClass); - writeClassDefinition(s, metaClass); - s << endl; - - if (metaClass->isPolymorphic() && metaClass->baseClass()) - writeTypeDiscoveryFunction(s, metaClass); - - - foreach (AbstractMetaEnum* cppEnum, metaClass->enums()) { - bool hasFlags = cppEnum->typeEntry()->flags(); - if (hasFlags) { - writeFlagsMethods(s, cppEnum); - writeFlagsNumberMethodsDefinition(s, cppEnum); - s << endl; - } - - writeEnumDefinition(s, cppEnum); - - if (hasFlags) { - // Write Enum as Flags definition (at the moment used only by QFlags) - writeFlagsDefinition(s, cppEnum); - s << endl; - } - } - s << endl; - - writeClassRegister(s, metaClass); - - // class inject-code native/end - if (!metaClass->typeEntry()->codeSnips().isEmpty()) { - writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), CodeSnip::End, TypeSystem::NativeCode, 0, 0, metaClass); - s << endl; - } -} - -void CppGenerator::writeConstructorNative(QTextStream& s, const AbstractMetaFunction* func) -{ - Indentation indentation(INDENT); - s << functionSignature(func, wrapperName(func->ownerClass()) + "::", "", - OriginalTypeDescription | SkipDefaultValues); - s << " : "; - writeFunctionCall(s, func); - if (usePySideExtensions() && func->ownerClass()->isQObject()) - s << ", m_metaObject(0)"; - - s << " {" << endl; - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); - writeCodeSnips(s, func->injectedCodeSnips(), CodeSnip::Beginning, TypeSystem::NativeCode, func, lastArg); - s << INDENT << "// ... middle" << endl; - writeCodeSnips(s, func->injectedCodeSnips(), CodeSnip::End, TypeSystem::NativeCode, func, lastArg); - s << '}' << endl << endl; -} - -void CppGenerator::writeDestructorNative(QTextStream &s, const AbstractMetaClass *metaClass) -{ - Indentation indentation(INDENT); - s << wrapperName(metaClass) << "::~" << wrapperName(metaClass) << "()" << endl << '{' << endl; - s << INDENT << "BindingManager::instance().invalidateWrapper(this);" << endl; - s << '}' << endl; -} - -void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFunction* func) -{ - //skip metaObject function, this will be written manually ahead - if (usePySideExtensions() && func->ownerClass() && func->ownerClass()->isQObject() && - ((func->name() == "metaObject") || (func->name() == "qt_metacall"))) - return; - - const TypeEntry* type = func->type() ? func->type()->typeEntry() : 0; - - QString prefix = wrapperName(func->ownerClass()) + "::"; - s << functionSignature(func, prefix, "", Generator::SkipDefaultValues|Generator::OriginalTypeDescription) << endl; - s << "{" << endl; - - Indentation indentation(INDENT); - - if (func->isAbstract() && func->isModifiedRemoved()) { - ReportHandler::warning("Pure virtual method \"" + func->ownerClass()->name() + "::" + func->minimalSignature() + "\" must be implement but was completely removed on typesystem."); - s << INDENT << "return"; - if (func->type()) { - s << ' '; - writeMinimalConstructorCallArguments(s, func->type()); - } - s << ';' << endl; - s << '}' << endl << endl; - return; - } - - s << INDENT << "Shiboken::GilState gil;" << endl; - - s << INDENT << "Shiboken::AutoDecRef py_override(BindingManager::instance().getOverride(this, \""; - s << func->name() << "\"));" << endl; - - s << INDENT << "if (py_override.isNull()) {" << endl; - { - Indentation indentation(INDENT); - - CodeSnipList snips; - if (func->hasInjectedCode()) { - snips = func->injectedCodeSnips(); - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); - writeCodeSnips(s, snips, CodeSnip::Beginning, TypeSystem::ShellCode, func, lastArg); - s << endl; - } - - if (func->isAbstract()) { - s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '"; - s << func->ownerClass()->name() << '.' << func->name(); - s << "()' not implemented.\");" << endl; - s << INDENT << "return "; - if (func->type()) { - writeMinimalConstructorCallArguments(s, func->type()); - } - } else { - if (func->allowThread()) { - s << INDENT << "Shiboken::ThreadStateSaver " THREAD_STATE_SAVER_VAR ";" << endl; - s << INDENT << THREAD_STATE_SAVER_VAR ".save();" << endl; - } - - s << INDENT << "return this->" << func->implementingClass()->qualifiedCppName() << "::"; - writeFunctionCall(s, func, Generator::VirtualCall); - } - } - s << ';' << endl; - s << INDENT << '}' << endl << endl; - - CodeSnipList convRules = getConversionRule(TypeSystem::TargetLangCode, func); - if (convRules.size()) - writeCodeSnips(s, convRules, CodeSnip::Beginning, TypeSystem::TargetLangCode, func); - - s << INDENT << "Shiboken::AutoDecRef pyargs("; - - if (func->arguments().isEmpty()) { - s << "PyTuple_New(0));" << endl; - } else { - QStringList argConversions; - foreach (const AbstractMetaArgument* arg, func->arguments()) { - if (func->argumentRemoved(arg->argumentIndex() + 1)) - continue; - - - QString argConv; - QTextStream ac(&argConv); - bool convert = arg->type()->isObject() - || arg->type()->isQObject() - || arg->type()->isValue() - || arg->type()->isValuePointer() - || arg->type()->isNativePointer() - || arg->type()->isFlags() - || arg->type()->isEnum() - || arg->type()->isContainer() - || arg->type()->isReference() - || (arg->type()->isPrimitive() - && !m_formatUnits.contains(arg->type()->typeEntry()->name())); - - bool hasConversionRule = !func->conversionRule(TypeSystem::TargetLangCode, arg->argumentIndex() + 1).isEmpty(); - - Indentation indentation(INDENT); - ac << INDENT; - if (convert && !hasConversionRule) - writeToPythonConversion(ac, arg->type(), func->ownerClass()); - - if (hasConversionRule) { - ac << arg->name() << "_out"; - } else { - QString argName = arg->name(); -#ifdef AVOID_PROTECTED_HACK - const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(arg->type()); - if (metaEnum && metaEnum->isProtected()) { - argName.prepend(protectedEnumSurrogateName(metaEnum) + '('); - argName.append(')'); - } -#endif - ac << (convert ? "(" : "") << argName << (convert ? ")" : ""); - } - - argConversions << argConv; - } - - s << "Py_BuildValue(\"(" << getFormatUnitString(func, false) << ")\"," << endl; - s << argConversions.join(",\n") << endl; - s << INDENT << "));" << endl; - } - s << endl; - - CodeSnipList snips; - if (func->hasInjectedCode()) { - snips = func->injectedCodeSnips(); - - if (injectedCodeUsesPySelf(func)) - s << INDENT << "PyObject* pySelf = BindingManager::instance().retrieveWrapper(this);" << endl; - - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); - writeCodeSnips(s, snips, CodeSnip::Beginning, TypeSystem::NativeCode, func, lastArg); - s << endl; - } - - if (!injectedCodeCallsPythonOverride(func)) { - s << INDENT; - s << "Shiboken::AutoDecRef " PYTHON_RETURN_VAR "(PyObject_Call(py_override, pyargs, NULL));" << endl; - if (type) { - s << INDENT << "// An error happened in python code!" << endl; - s << INDENT << "if (" PYTHON_RETURN_VAR ".isNull()) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_Print();" << endl; - s << INDENT << "return "; - writeMinimalConstructorCallArguments(s, func->type()); - s << ';' << endl; - } - s << INDENT << '}' << endl; - - if (func->type()) { - s << INDENT << "// Check return type" << endl; - s << INDENT << "bool typeIsValid = "; - QString desiredType; - if (func->typeReplaced(0).isEmpty()) { - s << cpythonIsConvertibleFunction(func->type()); - // SbkType would return null when the type is a container. - if (func->type()->typeEntry()->isContainer()) { - desiredType = '"' + reinterpret_cast(func->type()->typeEntry())->typeName() + '"'; - } else { - QString typeName = func->type()->cppSignature(); -#ifdef AVOID_PROTECTED_HACK - const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(func->type()); - if (metaEnum && metaEnum->isProtected()) - typeName = protectedEnumSurrogateName(metaEnum); -#endif - if (func->type()->isPrimitive()) - desiredType = "\"" + func->type()->name() + "\""; - else - desiredType = "SbkType<" + typeName + " >()->tp_name"; - } - } else { - s << guessCPythonCheckFunction(func->typeReplaced(0)); - desiredType = '"' + func->typeReplaced(0) + '"'; - } - s << "(" PYTHON_RETURN_VAR ");" << endl; - if (func->type()->isQObject() || func->type()->isObject() || func->type()->isValuePointer()) - s << INDENT << "typeIsValid = typeIsValid || (" PYTHON_RETURN_VAR " == Py_None);" << endl; - - s << INDENT << "if (!typeIsValid) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_Format(PyExc_TypeError, \"Invalid return value in function %s, expected %s, got %s.\", \"" - << func->ownerClass()->name() << '.' << func->name() << "\", " << desiredType - << ", " PYTHON_RETURN_VAR "->ob_type->tp_name);" << endl; - s << INDENT << "return "; - writeMinimalConstructorCallArguments(s, func->type()); - s << ';' << endl; - } - s << INDENT << "}" << endl; - } - - bool hasConversionRule = !func->conversionRule(TypeSystem::NativeCode, 0).isEmpty(); - if (hasConversionRule) { - CodeSnipList convRule = getReturnConversionRule(TypeSystem::NativeCode, func, "", CPP_RETURN_VAR); - writeCodeSnips(s, convRule, CodeSnip::Any, TypeSystem::NativeCode, func); - } else if (!injectedCodeHasReturnValueAttribution(func, TypeSystem::NativeCode)) { - s << INDENT; -#ifdef AVOID_PROTECTED_HACK - QString enumName; - const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(func->type()); - bool isProtectedEnum = metaEnum && metaEnum->isProtected(); - if (isProtectedEnum) { - enumName = metaEnum->name(); - if (metaEnum->enclosingClass()) - enumName = metaEnum->enclosingClass()->qualifiedCppName() + "::" + enumName; - s << enumName; - } else -#endif - s << translateTypeForWrapperMethod(func->type(), func->implementingClass()); - s << " " CPP_RETURN_VAR "("; -#ifdef AVOID_PROTECTED_HACK - if (isProtectedEnum) - s << enumName << '('; -#endif - writeToCppConversion(s, func->type(), func->implementingClass(), PYTHON_RETURN_VAR); -#ifdef AVOID_PROTECTED_HACK - if (isProtectedEnum) - s << ')'; -#endif - s << ')'; - s << ';' << endl; - } - } - } - - bool transferReturnToCpp = false; - foreach (FunctionModification func_mod, func->modifications()) { - foreach (ArgumentModification arg_mod, func_mod.argument_mods) { - if (arg_mod.resetAfterUse) { - s << INDENT << "BindingManager::instance().invalidateWrapper(PyTuple_GET_ITEM(pyargs, "; - s << (arg_mod.index - 1) << "));" << endl; - } else if ((arg_mod.index == 0) && (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::CppOwnership)) { - s << INDENT << "BindingManager::instance().invalidateWrapper(" << PYTHON_RETURN_VAR ".object());" << endl; - transferReturnToCpp = true; - } - } - } - - if (func->hasInjectedCode()) { - s << endl; - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); - writeCodeSnips(s, snips, CodeSnip::End, TypeSystem::NativeCode, func, lastArg); - } - - if (type) { - if (!transferReturnToCpp && (func->type()->isObject() || func->type()->isValuePointer()) ) { - s << INDENT << "if (" << PYTHON_RETURN_VAR << "->ob_refcnt < 2) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_ReferenceError, \"Returning last python reference on virutal function: " - << func->ownerClass()->name() << "." << func->name() << "\");" << endl; - s << INDENT << "PyErr_Print();" << endl; - s << INDENT << "assert(false);" << endl; - } - s << INDENT << "}" << endl; - } - s << INDENT << "return " CPP_RETURN_VAR ";" << endl; - } - - s << '}' << endl << endl; -} - -void CppGenerator::writeMetaObjectMethod(QTextStream& s, const AbstractMetaClass* metaClass) -{ - Indentation indentation(INDENT); - QString wrapperClassName = wrapperName(metaClass); - QString prefix = wrapperClassName + "::"; - s << "const QMetaObject* " << wrapperClassName << "::metaObject() const\n{\n"; - s << INDENT << "if (!m_metaObject) {\n"; - { - Indentation indentation(INDENT); - s << INDENT << "PyObject *pySelf = BindingManager::instance().retrieveWrapper(this);\n" - << INDENT << "void *typeData = Shiboken::getTypeUserData(reinterpret_cast(pySelf));" << endl - << INDENT << "if (!typeData) {" << endl; - { - Indentation indentation2(INDENT); - s << INDENT << "m_metaObject = PySide::DynamicQMetaObject::createBasedOn(pySelf, pySelf->ob_type, &" - << metaClass->qualifiedCppName() << "::staticMetaObject);" << endl - << INDENT << "Shiboken::setTypeUserData(reinterpret_cast(pySelf), m_metaObject, PySide::deleteDynamicQMetaObject);" << endl; - } - s << INDENT << "} else {" << endl; - { - Indentation indentation2(INDENT); - s << INDENT << "m_metaObject = reinterpret_cast(typeData);" << endl; - } - s << INDENT << "}" << endl; - } - s << INDENT << "}" << endl; - s << INDENT << "return m_metaObject;\n"; - s << "}\n\n"; - - s << "int " << wrapperClassName << "::qt_metacall(QMetaObject::Call call, int id, void** args)\n"; - s << "{\n"; - s << INDENT << "int result = " << metaClass->qualifiedCppName() << "::qt_metacall(call, id, args);\n"; - s << INDENT << "return result < 0 ? result : PySide::SignalManager::qt_metacall(this, call, id, args);\n"; - s << "}\n\n"; -} - -void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFunctionList overloads) -{ - OverloadData overloadData(overloads, this); - - const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); - const AbstractMetaClass* metaClass = rfunc->ownerClass(); - QString className = cpythonTypeName(metaClass); - - m_currentErrorCode = -1; - - s << "static int" << endl; - s << cpythonFunctionName(rfunc) << "(PyObject* self, PyObject* args, PyObject* kwds)" << endl; - s << '{' << endl; - - // Check if the right constructor was called. - if (!metaClass->hasPrivateDestructor()) { - s << INDENT << "if (Shiboken::isUserType(self) && !Shiboken::canCallConstructor(self->ob_type, Shiboken::SbkType<" << metaClass->qualifiedCppName() << " >()))" << endl; - Indentation indent(INDENT); - s << INDENT << "return " << m_currentErrorCode << ';' << endl << endl; - } - - s << INDENT; - bool hasCppWrapper = shouldGenerateCppWrapper(metaClass); - s << (hasCppWrapper ? wrapperName(metaClass) : metaClass->qualifiedCppName()); - s << "* cptr = 0;" << endl; - - bool needsOverloadId = overloadData.maxArgs() > 0; - if (needsOverloadId) - s << INDENT << "int overloadId = -1;" << endl; - - s << INDENT << "SbkBaseWrapper* sbkSelf = reinterpret_cast(self);" << endl; - - if (metaClass->isAbstract() || metaClass->baseClassNames().size() > 1) { - s << INDENT << "SbkBaseWrapperType* type = reinterpret_cast(self->ob_type);" << endl; - s << INDENT << "SbkBaseWrapperType* myType = reinterpret_cast(" << cpythonTypeNameExt(metaClass->typeEntry()) << ");" << endl; - } - - if (metaClass->isAbstract()) { - s << INDENT << "if (type == myType) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_NotImplementedError," << endl; - { - Indentation indentation(INDENT); - s << INDENT << "\"'" << metaClass->qualifiedCppName(); - } - s << "' represents a C++ abstract class and cannot be instantiated\");" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << INDENT << '}' << endl << endl; - } - - if (metaClass->baseClassNames().size() > 1) { - if (!metaClass->isAbstract()) { - s << INDENT << "if (type != myType) {" << endl; - } - { - Indentation indentation(INDENT); - s << INDENT << "type->mi_init = myType->mi_init;" << endl; - s << INDENT << "type->mi_offsets = myType->mi_offsets;" << endl; - s << INDENT << "type->mi_specialcast = myType->mi_specialcast;" << endl; - } - if (!metaClass->isAbstract()) - s << INDENT << '}' << endl << endl; - } - - s << endl; - - if (metaClass->isQObject() || overloadData.hasArgumentWithDefaultValue()) { - // Check usage of unknown named arguments - writeNamedArgumentsCheck(s, overloadData); - if (!metaClass->isQObject()) - s << INDENT << "int numNamedArgs = (kwds ? PyDict_Size(kwds) : 0);" << endl; - } - if (overloadData.maxArgs() > 0) { - s << endl << INDENT << "int numArgs = "; - writeArgumentsInitializer(s, overloadData); - } - - if (needsOverloadId) - writeOverloadedFunctionDecisor(s, overloadData); - - writeFunctionCalls(s, overloadData); - s << endl; - - s << INDENT << "if (PyErr_Occurred() || !Shiboken::setCppPointer(sbkSelf, Shiboken::SbkType<" << metaClass->qualifiedCppName() << " >(), cptr)) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "delete cptr;" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << INDENT << '}' << endl; - if (overloadData.maxArgs() > 0) { - s << INDENT << "if (!cptr) goto " << cpythonFunctionName(rfunc) << "_TypeError;" << endl; - s << endl; - } - - s << INDENT << "sbkSelf->validCppObject = 1;" << endl; - // If the created C++ object has a C++ wrapper the ownership is assigned to Python - // (first "1") and the flag indicating that the Python wrapper holds an C++ wrapper - // is marked as true (the second "1"). Otherwise the default values apply: - // Python owns it and C++ wrapper is false. - if (shouldGenerateCppWrapper(overloads.first()->ownerClass())) - s << INDENT << "sbkSelf->containsCppWrapper = 1;" << endl; - s << INDENT << "BindingManager::instance().registerWrapper(sbkSelf, cptr);" << endl; - - // Create metaObject and register signal/slot - if (metaClass->isQObject()) { - if (usePySideExtensions()) - s << INDENT << "PySide::signalUpdateSource(self);" << endl; - - s << INDENT << "cptr->metaObject();" << endl; - - if (metaClass->isQObject()) { - s << INDENT << "for (std::vector::size_type i = 0; i < propertyKeys.size(); i++) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "const char* propName = PyString_AS_STRING(propertyKeys[i]);" << endl; - s << INDENT << "const QMetaObject* mo = cptr->metaObject();" << endl; - s << INDENT << "if (mo->indexOfProperty(propName) != -1) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "cptr->setProperty(propName, "; - s << "Shiboken::Converter::toCpp(PyDict_GetItem(kwds, propertyKeys[i])));" << endl; - } - s << INDENT << "} else {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "QString signalSignature = QString(\"%1()\").arg(propName);" << endl; - s << INDENT << "if (mo->indexOfSignal(qPrintable(signalSignature)) != -1) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "signalSignature = '2' + signalSignature;" << endl; - s << INDENT << "PySide::signal_connect(self, qPrintable(signalSignature), PyDict_GetItem(kwds, propertyKeys[i]));" << endl; - } - s << INDENT << "} else {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "delete cptr;" << endl; - s << INDENT << "PyErr_Format(PyExc_AttributeError, \"'%s' is not a Qt property or a signal\", propName);" << endl; - s << INDENT << "return -1;" << endl; - } - s << INDENT << "};" << endl; - } - s << INDENT << "}" << endl; - } - s << INDENT << '}' << endl; - } - } - - // Constructor code injections, position=end - bool hasCodeInjectionsAtEnd = false; - foreach(AbstractMetaFunction* func, overloads) { - foreach (CodeSnip cs, func->injectedCodeSnips()) { - if (cs.position == CodeSnip::End) { - hasCodeInjectionsAtEnd = true; - break; - } - } - } - if (hasCodeInjectionsAtEnd) { - // FIXME: C++ arguments are not available in code injection on constructor when position = end. - s << INDENT << "switch(overloadId) {" << endl; - foreach(AbstractMetaFunction* func, overloads) { - Indentation indent(INDENT); - foreach (CodeSnip cs, func->injectedCodeSnips()) { - if (cs.position == CodeSnip::End) { - s << INDENT << "case " << metaClass->functions().indexOf(func) << ':' << endl; - s << INDENT << '{' << endl; - { - Indentation indent(INDENT); - writeCodeSnips(s, func->injectedCodeSnips(), CodeSnip::End, TypeSystem::TargetLangCode, func); - } - s << INDENT << '}' << endl; - break; - } - } - } - s << '}' << endl; - } - - s << endl; - s << endl << INDENT << "return 1;" << endl; - if (overloadData.maxArgs() > 0) - writeErrorSection(s, overloadData); - s << '}' << endl << endl; - m_currentErrorCode = 0; -} - -void CppGenerator::writeMinimalConstructorCallArguments(QTextStream& s, const AbstractMetaClass* metaClass) -{ - if (!metaClass) - return; - - AbstractMetaFunctionList ctors = metaClass->queryFunctions(AbstractMetaClass::Constructors); - const AbstractMetaFunction* ctor = 0; - - foreach (const AbstractMetaFunction* candidate, ctors) { - if (candidate->arguments().size() == 0) { - ctor = candidate; - break; - } - - bool allPrimitives = true; - foreach (const AbstractMetaArgument* arg, candidate->arguments()) { - if (!arg->type()->isPrimitive() && arg->defaultValueExpression().isEmpty()) { - allPrimitives = false; - break; - } - } - if (allPrimitives) { - if (!ctor || candidate->arguments().size() < ctor->arguments().size()) - ctor = candidate; - } - } - - if (!ctor) { - ReportHandler::warning("Class "+metaClass->name()+" does not have a default constructor."); - return; - } - - QStringList argValues; - AbstractMetaArgumentList args = ctor->arguments(); - for (int i = 0; i < args.size(); i++) { - if (args[i]->defaultValueExpression().isEmpty()) - argValues << args[i]->type()->name()+"(0)"; - } - s << metaClass->qualifiedCppName() << '(' << argValues.join(QLatin1String(", ")) << ')'; -} - -void CppGenerator::writeMinimalConstructorCallArguments(QTextStream& s, const AbstractMetaType* metaType) -{ - Q_ASSERT(metaType); - const TypeEntry* type = metaType->typeEntry(); - - if (type->isObject() || metaType->isValuePointer()) { - s << "0"; - } else if (type->isPrimitive()) { - const PrimitiveTypeEntry* primitiveTypeEntry = reinterpret_cast(type); - if (primitiveTypeEntry->hasDefaultConstructor()) - s << primitiveTypeEntry->defaultConstructor(); - else - s << type->name() << "(0)"; - } else if (type->isContainer() || type->isFlags() || type->isEnum()){ - s << metaType->cppSignature() << "()"; - } else if (metaType->isNativePointer() && type->isVoid()) { - s << "0"; - } else { - // this is slowwwww, FIXME: Fix the API od APIExtractor, these things should be easy! - foreach (AbstractMetaClass* metaClass, classes()) { - if (metaClass->typeEntry() == type) { - writeMinimalConstructorCallArguments(s, metaClass); - return; - } - } - ReportHandler::warning("Could not find a AbstractMetaClass for type "+metaType->name()); - } -} - -void CppGenerator::writeMethodWrapper(QTextStream& s, const AbstractMetaFunctionList overloads) -{ - OverloadData overloadData(overloads, this); - const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); - - //DEBUG -// if (rfunc->name() == "operator+" && rfunc->ownerClass()->name() == "Str") { -// QString dumpFile = QString("/tmp/%1_%2.dot").arg(moduleName()).arg(pythonOperatorFunctionName(rfunc)).toLower(); -// overloadData.dumpGraph(dumpFile); -// } - //DEBUG - - int minArgs = overloadData.minArgs(); - int maxArgs = overloadData.maxArgs(); - bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(overloadData); - bool usesNamedArguments = overloadData.hasArgumentWithDefaultValue(); - - s << "static PyObject* "; - s << cpythonFunctionName(rfunc) << "(PyObject* self"; - if (maxArgs > 0) { - s << ", PyObject* arg"; - if (usePyArgs) - s << 's'; - if (usesNamedArguments) - s << ", PyObject* kwds"; - } - s << ')' << endl << '{' << endl; - - if (rfunc->implementingClass() && - (!rfunc->implementingClass()->isNamespace() && overloadData.hasInstanceFunction())) { - - s << INDENT; -#ifdef AVOID_PROTECTED_HACK - QString _wrapperName = wrapperName(rfunc->ownerClass()); - bool hasProtectedMembers = rfunc->ownerClass()->hasProtectedMembers(); - s << (hasProtectedMembers ? _wrapperName : rfunc->ownerClass()->qualifiedCppName()); -#else - s << rfunc->ownerClass()->qualifiedCppName(); -#endif - s << "* " CPP_SELF_VAR " = 0;" << endl; - - if (rfunc->isOperatorOverload() && rfunc->isBinaryOperator()) { - QString checkFunc = cpythonCheckFunction(rfunc->ownerClass()->typeEntry()); - s << INDENT << "bool isReverse = " << checkFunc << "(arg) && !" << checkFunc << "(self);\n" - << INDENT << "if (isReverse)\n"; - Indentation indent(INDENT); - s << INDENT << "std::swap(self, arg);\n\n"; - } - - // Sets the C++ "self" (the "this" for the object) if it has one. - QString cppSelfAttribution = CPP_SELF_VAR " = "; -#ifdef AVOID_PROTECTED_HACK - cppSelfAttribution += (hasProtectedMembers ? QString("(%1*)").arg(_wrapperName) : ""); -#endif - cppSelfAttribution += cpythonWrapperCPtr(rfunc->ownerClass(), "self"); - - // Checks if the underlying C++ object is valid. - if (overloadData.hasStaticFunction()) { - s << INDENT << "if (self) {" << endl; - { - Indentation indent(INDENT); - writeInvalidCppObjectCheck(s); - s << INDENT << cppSelfAttribution << ';' << endl; - } - s << INDENT << '}' << endl; - } else { - writeInvalidCppObjectCheck(s); - s << INDENT << cppSelfAttribution << ';' << endl; - } - s << endl; - } - - bool hasReturnValue = overloadData.hasNonVoidReturnType(); - - if (hasReturnValue && !rfunc->isInplaceOperator()) - s << INDENT << "PyObject* " PYTHON_RETURN_VAR " = 0;" << endl; - - bool needsOverloadId = overloadData.maxArgs() > 0; - if (needsOverloadId) - s << INDENT << "int overloadId = -1;" << endl; - - if (usesNamedArguments) { - // Check usage of unknown named arguments - writeNamedArgumentsCheck(s, overloadData); - s << INDENT << "int numNamedArgs = (kwds ? PyDict_Size(kwds) : 0);" << endl; - } - - if (minArgs != maxArgs || maxArgs > 1) { - s << INDENT << "int numArgs = "; - if (minArgs == 0 && maxArgs == 1 && !usePyArgs) - s << "(arg == 0 ? 0 : 1);" << endl; - else - writeArgumentsInitializer(s, overloadData); - } - s << endl; - - /* - * Make sure reverse <> operators defined in other classes (specially from other modules) - * are called. A proper and generic solution would require an reengineering in the operator - * system like the extended converters. - * - * Solves #119 - QDataStream <> operators not working for QPixmap - * http://bugs.openbossa.org/show_bug.cgi?id=119 - */ - bool callExtendedReverseOperator = hasReturnValue && !rfunc->isInplaceOperator() && rfunc->isOperatorOverload(); - if (callExtendedReverseOperator) { - QString revOpName = ShibokenGenerator::pythonOperatorFunctionName(rfunc).insert(2, 'r'); - if (rfunc->isBinaryOperator()) { - s << INDENT << "if (!isReverse" << endl; - { - Indentation indent(INDENT); - s << INDENT << "&& SbkBaseWrapper_Check(arg)" << endl; - s << INDENT << "&& !PyObject_TypeCheck(arg, self->ob_type)" << endl; - s << INDENT << "&& PyObject_HasAttrString(arg, const_cast(\"" << revOpName << "\"))) {" << endl; - // This PyObject_CallMethod call will emit lots of warnings like - // "deprecated conversion from string constant to char *" during compilation - // due to the method name argument being declared as "char*" instead of "const char*" - // issue 6952 http://bugs.python.org/issue6952 - s << INDENT << "PyObject* revOpMethod = PyObject_GetAttrString(arg, const_cast(\"" << revOpName << "\"));" << endl; - s << INDENT << "if (revOpMethod && PyCallable_Check(revOpMethod)) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << PYTHON_RETURN_VAR " = PyObject_CallFunction(revOpMethod, const_cast(\"O\"), self);" << endl; - s << INDENT << "if (PyErr_Occurred() && (PyErr_ExceptionMatches(PyExc_NotImplementedError)"; - s << " || PyErr_ExceptionMatches(PyExc_AttributeError))) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_Clear();" << endl; - s << INDENT << "Py_XDECREF(" PYTHON_RETURN_VAR ");" << endl; - s << INDENT << PYTHON_RETURN_VAR " = 0;" << endl; - } - s << INDENT << '}' << endl; - } - s << INDENT << "}" << endl; - s << INDENT << "Py_XDECREF(revOpMethod);" << endl << endl; - } - s << INDENT << "}" << endl; - } - s << INDENT << "// Do not enter here if other object has implemented a reverse operator." << endl; - s << INDENT << "if (!" PYTHON_RETURN_VAR ") {" << endl << endl; - } - - if (needsOverloadId) - writeOverloadedFunctionDecisor(s, overloadData); - - writeFunctionCalls(s, overloadData); - s << endl; - - if (callExtendedReverseOperator) - s << endl << INDENT << "} // End of \"if (!" PYTHON_RETURN_VAR ")\"" << endl << endl; - - s << endl << INDENT << "if (PyErr_Occurred()"; - if (hasReturnValue && !rfunc->isInplaceOperator()) - s << " || !" PYTHON_RETURN_VAR; - s << ") {" << endl; - { - Indentation indent(INDENT); - if (hasReturnValue && !rfunc->isInplaceOperator()) - s << INDENT << "Py_XDECREF(" PYTHON_RETURN_VAR ");" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << INDENT << '}' << endl; - - if (hasReturnValue) { - if (rfunc->isInplaceOperator()) { - s << INDENT << "Py_INCREF(self);\n"; - s << INDENT << "return self;\n"; - } else { - s << INDENT << "return " PYTHON_RETURN_VAR ";\n"; - } - } else { - s << INDENT << "Py_RETURN_NONE;" << endl; - } - - if (maxArgs > 0) - writeErrorSection(s, overloadData); - - s << '}' << endl << endl; -} - -void CppGenerator::writeNamedArgumentsCheck(QTextStream& s, OverloadData& overloadData) -{ - // Check usage of unknown named arguments - QSet argNamesSet; - foreach (const AbstractMetaFunction* func, overloadData.overloads()) { - foreach (const AbstractMetaArgument* arg, func->arguments()) { - if (arg->defaultValueExpression().isEmpty() - || func->argumentRemoved(arg->argumentIndex() + 1)) - continue; - argNamesSet << QString("\"%1\"").arg(arg->name()); - } - } - QStringList argNamesList = argNamesSet.toList(); - qSort(argNamesList.begin(), argNamesList.end()); - - const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); - bool ownerClassIsQObject = rfunc->ownerClass() && rfunc->ownerClass()->isQObject() && rfunc->isConstructor(); - if (overloadData.hasArgumentWithDefaultValue() || (ownerClassIsQObject && rfunc->isConstructor())) { - s << INDENT << "std::vector propertyKeys;" << endl << endl; - s << INDENT << "// Check existence of named argument." << endl; - s << INDENT << "if (kwds) {" << endl; - { - Indentation indent(INDENT); - if (argNamesList.size() > 0) - s << INDENT << "std::string argNames[] = { " << argNamesList.join(", ") << " };" << endl; - s << INDENT << "PyObject* keys = PyDict_Keys(kwds);" << endl; - s << INDENT << "Shiboken::AutoDecRef auto_keys(keys);" << endl; - s << INDENT << "for (int i = 0; i < PyList_GET_SIZE(keys); ++i) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyObject* argName = PyList_GET_ITEM(keys, i);" << endl; - if (argNamesList.size() > 0) { - s << INDENT << "if (!std::binary_search(argNames, argNames + " << argNamesList.count(); - s << ", std::string(PyString_AS_STRING(argName)))) {" << endl; - } - { - Indentation indent(INDENT); - if (ownerClassIsQObject) { - s << INDENT << "propertyKeys.push_back(argName);" << endl; - } else { - s << INDENT << "PyErr_Format(PyExc_TypeError, \"" << fullPythonFunctionName(overloadData.referenceFunction()); - s << "(): got an unexpected keyword argument '%s'\", PyString_AS_STRING(argName));" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - } - if (argNamesList.size() > 0) - s << INDENT << '}' << endl; - } - s << INDENT << '}' << endl; - } - } - s << INDENT << '}' << endl; -} - -void CppGenerator::writeArgumentsInitializer(QTextStream& s, OverloadData& overloadData) -{ - const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); - s << "PyTuple_GET_SIZE(args);" << endl; - - int minArgs = overloadData.minArgs(); - int maxArgs = overloadData.maxArgs(); - - QStringList palist; - - s << INDENT << "PyObject* "; - if (maxArgs == 1) { - s << "arg = 0"; - palist << "&arg"; - } else { - s << "pyargs[] = {" << QString(maxArgs, '0').split("", QString::SkipEmptyParts).join(", ") << '}'; - for (int i = 0; i < maxArgs; i++) - palist << QString("&(pyargs[%1])").arg(i); - } - s << ';' << endl << endl; - - QString pyargs = palist.join(", "); - - if (overloadData.hasVarargs()) { - maxArgs--; - if (minArgs > maxArgs) - minArgs = maxArgs; - - s << INDENT << "PyObject* nonvarargs = PyTuple_GetSlice(args, 0, " << maxArgs << ");" << endl; - s << INDENT << "Shiboken::AutoDecRef auto_nonvarargs(nonvarargs);" << endl; - s << INDENT << "pyargs[" << maxArgs << "] = PyTuple_GetSlice(args, " << maxArgs << ", numArgs);" << endl; - s << INDENT << "Shiboken::AutoDecRef auto_varargs(pyargs[" << maxArgs << "]);" << endl; - s << endl; - } - - bool usesNamedArguments = overloadData.hasArgumentWithDefaultValue(); - - s << INDENT << "// invalid argument lengths" << endl; - bool ownerClassIsQObject = rfunc->ownerClass() && rfunc->ownerClass()->isQObject() && rfunc->isConstructor(); - if (usesNamedArguments) { - if (!ownerClassIsQObject) { - s << INDENT << "if (numArgs" << (overloadData.hasArgumentWithDefaultValue() ? " + numNamedArgs" : "") << " > " << maxArgs << ") {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_TypeError, \"" << fullPythonFunctionName(rfunc) << "(): too many arguments\");" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << INDENT << '}'; - } - if (minArgs > 0) { - if (ownerClassIsQObject) - s << INDENT; - else - s << " else "; - s << "if (numArgs < " << minArgs << ") {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_TypeError, \"" << fullPythonFunctionName(rfunc) << "(): not enough arguments\");" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << INDENT << '}'; - } - } - QList invalidArgsLength = overloadData.invalidArgumentLengths(); - if (!invalidArgsLength.isEmpty()) { - QStringList invArgsLen; - foreach (int i, invalidArgsLength) - invArgsLen << QString("numArgs == %1").arg(i); - if (usesNamedArguments && (!ownerClassIsQObject || minArgs > 0)) - s << " else "; - else - s << INDENT; - s << "if (" << invArgsLen.join(" || ") << ")" << endl; - Indentation indent(INDENT); - s << INDENT << "goto " << cpythonFunctionName(rfunc) << "_TypeError;"; - } - s << endl << endl; - - QString funcName; - if (rfunc->isOperatorOverload()) - funcName = ShibokenGenerator::pythonOperatorFunctionName(rfunc); - else - funcName = rfunc->name(); - - if (usesNamedArguments) { - s << INDENT << "if (!PyArg_ParseTuple(" << (overloadData.hasVarargs() ? "nonvarargs" : "args"); - s << ", \"|" << QByteArray(maxArgs, 'O') << ':' << funcName << "\", " << pyargs << "))" << endl; - } else { - s << INDENT << "if (!PyArg_UnpackTuple(" << (overloadData.hasVarargs() ? "nonvarargs" : "args"); - s << ", \"" << funcName << "\", " << minArgs << ", " << maxArgs << ", " << pyargs << "))" << endl; - } - { - Indentation indent(INDENT); - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << endl; -} - -void CppGenerator::writeCppSelfDefinition(QTextStream& s, const AbstractMetaFunction* func) -{ - if (!func->ownerClass() || func->isStatic() || func->isConstructor()) - return; - - s << INDENT; -#ifdef AVOID_PROTECTED_HACK - QString _wrapperName = wrapperName(func->ownerClass()); - bool hasProtectedMembers = func->ownerClass()->hasProtectedMembers(); - s << (hasProtectedMembers ? _wrapperName : func->ownerClass()->qualifiedCppName()) << "* " CPP_SELF_VAR " = "; - s << (hasProtectedMembers ? QString("(%1*)").arg(_wrapperName) : ""); -#else - s << func->ownerClass()->qualifiedCppName() << "* " CPP_SELF_VAR " = "; -#endif - s << cpythonWrapperCPtr(func->ownerClass(), "self") << ';' << endl; - if (func->isUserAdded()) - s << INDENT << "(void)" CPP_SELF_VAR "; // avoid warnings about unused variables" << endl; -} - -void CppGenerator::writeErrorSection(QTextStream& s, OverloadData& overloadData) -{ - const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); - s << endl << INDENT << cpythonFunctionName(rfunc) << "_TypeError:" << endl; - Indentation indentation(INDENT); - QString funcName = fullPythonFunctionName(rfunc); - - QString argsVar = !rfunc->isConstructor() && overloadData.maxArgs() == 1 ? "arg" : "args"; - if (verboseErrorMessagesDisabled()) { - s << INDENT << "Shiboken::setErrorAboutWrongArguments(" << argsVar << ", \"" << funcName << "\", 0);" << endl; - } else { - QStringList overloadSignatures; - foreach (const AbstractMetaFunction* f, overloadData.overloads()) { - QStringList args; - foreach(AbstractMetaArgument* arg, f->arguments()) { - QString strArg; - AbstractMetaType* argType = arg->type(); - if (isCString(argType)) { - strArg = "str"; - } else if (argType->isPrimitive()) { - const PrimitiveTypeEntry* ptp = reinterpret_cast(argType->typeEntry()); - while (ptp->aliasedTypeEntry()) - ptp = ptp->aliasedTypeEntry(); - - if (strArg == "QString") { - strArg = "unicode"; - } else if (strArg == "QChar") { - strArg = "1-unicode"; - } else { - strArg = ptp->name().replace(QRegExp("^signed\\s+"), ""); - if (strArg == "double") - strArg = "float"; - } - } else if (argType->typeEntry()->isContainer()) { - strArg = argType->fullName(); - if (strArg == "QList" || strArg == "QVector" - || strArg == "QLinkedList" || strArg == "QStack" - || strArg == "QQueue") { - strArg = "list"; - } else if (strArg == "QMap" || strArg == "QHash" - || strArg == "QMultiMap" || strArg == "QMultiHash") { - strArg = "dict"; - } else if (strArg == "QPair") { - strArg == "2-tuple"; - } - } else { - strArg = argType->fullName(); - } - if (!arg->defaultValueExpression().isEmpty()) { - strArg += " = "; - if ((isCString(argType) || argType->isValuePointer() || argType->typeEntry()->isObject()) - && arg->defaultValueExpression() == "0") - strArg += "None"; - else - strArg += arg->defaultValueExpression().replace("::", ".").replace("\"", "\\\""); - } - args << strArg; - } - overloadSignatures << "\""+args.join(", ")+"\""; - } - s << INDENT << "const char* overloads[] = {" << overloadSignatures.join(", ") << ", 0};" << endl; - s << INDENT << "Shiboken::setErrorAboutWrongArguments(" << argsVar << ", \"" << funcName << "\", overloads);" << endl; - } - s << INDENT << "return " << m_currentErrorCode << ';' << endl; -} - -void CppGenerator::writeInvalidCppObjectCheck(QTextStream& s, QString pyArgName, const TypeEntry* type) -{ - s << INDENT << "if (Shiboken::cppObjectIsInvalid(" << pyArgName << "))" << endl; - Indentation indent(INDENT); - s << INDENT << "return " << m_currentErrorCode << ';' << endl; -} - -void CppGenerator::writeTypeCheck(QTextStream& s, const AbstractMetaType* argType, QString argumentName, bool isNumber, QString customType) -{ - if (!customType.isEmpty()) - s << guessCPythonCheckFunction(customType); - else if (argType->isEnum()) - s << cpythonIsConvertibleFunction(argType, false); - else - s << cpythonIsConvertibleFunction(argType, isNumber); - - s << '(' << argumentName << ')'; -} - -void CppGenerator::writeTypeCheck(QTextStream& s, const OverloadData* overloadData, QString argumentName) -{ - QSet numericTypes; - - foreach (OverloadData* od, overloadData->previousOverloadData()->nextOverloadData()) { - foreach (const AbstractMetaFunction* func, od->overloads()) { - const AbstractMetaArgument* arg = od->argument(func); - - if (!arg->type()->isPrimitive()) - continue; - if (ShibokenGenerator::isNumber(arg->type()->typeEntry())) - numericTypes << arg->type()->typeEntry(); - } - } - - // This condition trusts that the OverloadData object will arrange for - // PyInt type to come after the more precise numeric types (e.g. float and bool) - const AbstractMetaType* argType = overloadData->argType(); - bool numberType = numericTypes.count() == 1 || ShibokenGenerator::isPyInt(argType); - QString customType = (overloadData->hasArgumentTypeReplace() ? overloadData->argumentTypeReplaced() : ""); - writeTypeCheck(s, argType, argumentName, numberType, customType); -} - -void CppGenerator::writeArgumentConversion(QTextStream& s, - const AbstractMetaType* argType, - QString argName, QString pyArgName, - const AbstractMetaClass* context, - QString defaultValue) -{ - const TypeEntry* type = argType->typeEntry(); - - if (type->isCustom() || type->isVarargs()) - return; - - QString typeName; - QString baseTypeName = type->name(); - bool isWrappedCppClass = type->isValue() || type->isObject(); - if (isWrappedCppClass) - typeName = baseTypeName + '*'; - else - typeName = translateTypeForWrapperMethod(argType, context); - - if (type->isContainer() || type->isPrimitive()) { - // If the type is a const char*, we don't remove the "const". - if (typeName.startsWith("const ") && !(isCString(argType))) - typeName.remove(0, sizeof("const ") / sizeof(char) - 1); - if (typeName.endsWith("&")) - typeName.chop(1); - } - typeName = typeName.trimmed(); - - bool hasImplicitConversions = !implicitConversions(argType).isEmpty(); - - if (isWrappedCppClass) { - const TypeEntry* typeEntry = (hasImplicitConversions ? type : 0); - writeInvalidCppObjectCheck(s, pyArgName, typeEntry); - } - - // Auto pointer to dealloc new objects created because to satisfy implicit conversion. - if (hasImplicitConversions) - s << INDENT << "std::auto_ptr<" << baseTypeName << " > " << argName << "_auto_ptr;" << endl; - - // Value type that has default value. - if (argType->isValue() && !defaultValue.isEmpty()) - s << INDENT << baseTypeName << ' ' << argName << "_tmp = " << defaultValue << ';' << endl; - - if (usePySideExtensions() && typeName == "QStringRef") { - s << INDENT << "QString " << argName << "_qstring = "; - if (!defaultValue.isEmpty()) - s << pyArgName << " ? "; - s << "Shiboken::Converter::toCpp(" << pyArgName << ')' << endl; - if (!defaultValue.isEmpty()) - s << " : " << defaultValue; - s << ';' << endl; - s << INDENT << "QStringRef " << argName << "(&" << argName << "_qstring);" << endl; - } else { - s << INDENT << typeName << ' ' << argName << " = "; - if (!defaultValue.isEmpty()) - s << pyArgName << " ? "; - s << "Shiboken::Converter<" << typeName << " >::toCpp(" << pyArgName << ')'; - if (!defaultValue.isEmpty()) { - s << " : "; - if (argType->isValue()) - s << '&' << argName << "_tmp"; - else - s << defaultValue; - } - s << ';' << endl; - } - - if (hasImplicitConversions) { - s << INDENT << "if ("; - if (!defaultValue.isEmpty()) - s << pyArgName << " && "; - s << '!' << cpythonCheckFunction(type) << '(' << pyArgName << "))"; - s << endl; - Indentation indent(INDENT); - s << INDENT << argName << "_auto_ptr = std::auto_ptr<" << baseTypeName; - s << " >(" << argName << ");" << endl; - } -} - -void CppGenerator::writeNoneReturn(QTextStream& s, const AbstractMetaFunction* func, bool thereIsReturnValue) -{ - if (thereIsReturnValue && (!func->type() || func->argumentRemoved(0)) && !injectedCodeHasReturnValueAttribution(func)) { - s << INDENT << PYTHON_RETURN_VAR " = Py_None;" << endl; - s << INDENT << "Py_INCREF(Py_None);" << endl; - } -} - -void CppGenerator::writeOverloadedFunctionDecisor(QTextStream& s, const OverloadData& overloadData) -{ - s << INDENT << "// Overloaded function decisor" << endl; - QList functionOverloads = overloadData.overloadsWithoutRepetition(); - for (int i = 0; i < functionOverloads.count(); i++) - s << INDENT << "// " << i << ": " << functionOverloads.at(i)->minimalSignature() << endl; - writeOverloadedFunctionDecisorEngine(s, &overloadData); - s << endl; - - s << INDENT << "// Function signature not found." << endl; - s << INDENT << "if (overloadId == -1) goto " << cpythonFunctionName(overloadData.referenceFunction()) << "_TypeError;" << endl; - s << endl; -} - -void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream& s, const OverloadData* parentOverloadData) -{ - bool hasDefaultCall = parentOverloadData->nextArgumentHasDefaultValue(); - const AbstractMetaFunction* referenceFunction = parentOverloadData->referenceFunction(); - - // If the next argument has not an argument with a default value, it is still possible - // that one of the overloads for the current overload data has its final occurrence here. - // If found, the final occurrence of a method is attributed to the referenceFunction - // variable to be used further on this method on the conditional that identifies default - // method calls. - if (!hasDefaultCall) { - foreach (const AbstractMetaFunction* func, parentOverloadData->overloads()) { - if (parentOverloadData->isFinalOccurrence(func)) { - referenceFunction = func; - hasDefaultCall = true; - break; - } - } - } - - int maxArgs = parentOverloadData->maxArgs(); - // Python constructors always receive multiple arguments. - bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(*parentOverloadData); - - // Functions without arguments are identified right away. - if (maxArgs == 0) { - s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(referenceFunction); - s << "; // " << referenceFunction->minimalSignature() << endl; - return; - - // To decide if a method call is possible at this point the current overload - // data object cannot be the head, since it is just an entry point, or a root, - // for the tree of arguments and it does not represent a valid method call. - } else if (!parentOverloadData->isHeadOverloadData()) { - bool isLastArgument = parentOverloadData->nextOverloadData().isEmpty(); - bool signatureFound = parentOverloadData->overloads().size() == 1; - - // The current overload data describes the last argument of a signature, - // so the method can be identified right now. - if (isLastArgument || (signatureFound && !hasDefaultCall)) { - const AbstractMetaFunction* func = parentOverloadData->referenceFunction(); - s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(func); - s << "; // " << func->minimalSignature() << endl; - return; - } - } - - bool isFirst = true; - - // If the next argument has a default value the decisor can perform a method call; - // it just need to check if the number of arguments received from Python are equal - // to the number of parameters preceding the argument with the default value. - if (hasDefaultCall) { - isFirst = false; - int numArgs = parentOverloadData->argPos() + 1; - s << INDENT << "if (numArgs == " << numArgs << ") {" << endl; - { - Indentation indent(INDENT); - const AbstractMetaFunction* func = referenceFunction; - foreach (OverloadData* overloadData, parentOverloadData->nextOverloadData()) { - const AbstractMetaFunction* defValFunc = overloadData->getFunctionWithDefaultValue(); - if (defValFunc) { - func = defValFunc; - break; - } - } - s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(func); - s << "; // " << func->minimalSignature() << endl; - } - s << INDENT << '}'; - } - - foreach (OverloadData* overloadData, parentOverloadData->nextOverloadData()) { - bool signatureFound = overloadData->overloads().size() == 1 - && !overloadData->getFunctionWithDefaultValue() - && !overloadData->findNextArgWithDefault(); - - const AbstractMetaFunction* refFunc = overloadData->referenceFunction(); - - if (isFirst) { - isFirst = false; - s << INDENT; - } else { - s << " else "; - } - - QString typeChecks; - QTextStream tck(&typeChecks); - - QString pyArgName = (usePyArgs && maxArgs > 1) ? QString("pyargs[%1]").arg(overloadData->argPos()) : "arg"; - - OverloadData* od = overloadData; - int startArg = od->argPos(); - int sequenceArgCount = 0; - while (od && !od->argType()->isVarargs()) { - if (usePyArgs && maxArgs > 1) - pyArgName = QString("pyargs[%1]").arg(od->argPos()); - - writeTypeCheck(tck, od, pyArgName); - sequenceArgCount++; - - if (od->nextOverloadData().isEmpty() - || od->nextArgumentHasDefaultValue() - || od->nextOverloadData().size() != 1 - || od->overloads().size() != od->nextOverloadData().first()->overloads().size()) { - overloadData = od; - od = 0; - } else { - od = od->nextOverloadData().first(); - if (!od->argType()->isVarargs()) - tck << " && "; - } - } - - s << "if ("; - if (usePyArgs && signatureFound) { - AbstractMetaArgumentList args = refFunc->arguments(); - int lastArgIsVarargs = (int) (args.size() > 1 && args.last()->type()->isVarargs()); - int numArgs = args.size() - OverloadData::numberOfRemovedArguments(refFunc) - lastArgIsVarargs; - s << "numArgs " << (lastArgIsVarargs ? ">=" : "==") << " " << numArgs << " && "; - } else if (sequenceArgCount > 1) { - s << "numArgs >= " << (startArg + sequenceArgCount) << " && "; - } - - if (refFunc->isOperatorOverload()) - s << (refFunc->isReverseOperator() ? "" : "!") << "isReverse && "; - - s << typeChecks << ") {" << endl; - - { - Indentation indent(INDENT); - writeOverloadedFunctionDecisorEngine(s, overloadData); - } - - s << INDENT << "}"; - } - s << endl; -} - -void CppGenerator::writeFunctionCalls(QTextStream& s, const OverloadData& overloadData) -{ - QList overloads = overloadData.overloadsWithoutRepetition(); - s << INDENT << "// Call function/method" << endl; - s << INDENT << "{" << endl; - { - Indentation indent(INDENT); - if (overloadData.hasAllowThread()) - s << INDENT << "Shiboken::ThreadStateSaver " THREAD_STATE_SAVER_VAR ";" << endl; - - s << INDENT << (overloads.count() > 1 ? "switch (overloadId) " : "") << '{' << endl; - { - Indentation indent(INDENT); - if (overloads.count() == 1) { - writeSingleFunctionCall(s, overloadData, overloads.first()); - } else { - for (int i = 0; i < overloads.count(); i++) { - const AbstractMetaFunction* func = overloads.at(i); - s << INDENT << "case " << i << ": // " << func->minimalSignature() << endl; - s << INDENT << '{' << endl; - { - Indentation indent(INDENT); - writeSingleFunctionCall(s, overloadData, func); - s << INDENT << "break;" << endl; - } - s << INDENT << '}' << endl; - } - } - } - s << INDENT << '}' << endl << INDENT << "}"; - } -} - -void CppGenerator::writeSingleFunctionCall(QTextStream& s, const OverloadData& overloadData, const AbstractMetaFunction* func) -{ - if (func->functionType() == AbstractMetaFunction::EmptyFunction) { - s << INDENT << "PyErr_Format(PyExc_TypeError, \"%s is a private method.\", \"" << func->signature().replace("::", ".") << "\");" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - return; - } - - - - const AbstractMetaClass* implementingClass = overloadData.referenceFunction()->implementingClass(); - bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(overloadData) && overloadData.maxArgs() > 1; - - // Handle named arguments. - writeNamedArgumentResolution(s, func, usePyArgs); - - int removedArgs = 0; - for (int i = 0; i < func->arguments().count(); i++) { - if (func->argumentRemoved(i + 1)) { - removedArgs++; - continue; - } - - if (!func->conversionRule(TypeSystem::NativeCode, i + 1).isEmpty()) - continue; - - const AbstractMetaArgument* arg = func->arguments().at(i); - - QString typeReplaced = func->typeReplaced(arg->argumentIndex() + 1); - const AbstractMetaType* argType = 0; - if (typeReplaced.isEmpty()) - argType = arg->type(); - else - argType = buildAbstractMetaTypeFromString(typeReplaced); - - if (argType) { - QString argName = QString("cpp_arg%1").arg(i - removedArgs); - QString pyArgName = usePyArgs ? QString("pyargs[%1]").arg(i - removedArgs) : "arg"; - QString defaultValue = guessScopeForDefaultValue(func, arg); - - writeArgumentConversion(s, argType, argName, pyArgName, implementingClass, defaultValue); - - // Free a custom type created by buildAbstractMetaTypeFromString. - if (argType != arg->type()) - delete argType; - } - } - - s << endl; - - int numRemovedArgs = OverloadData::numberOfRemovedArguments(func); - - s << INDENT << "if(!PyErr_Occurred()) {" << endl; - writeMethodCall(s, func, func->arguments().size() - numRemovedArgs); - if (!func->isConstructor()) - writeNoneReturn(s, func, overloadData.hasNonVoidReturnType()); - s << INDENT << "}" << endl; -} - -void CppGenerator::writeNamedArgumentResolution(QTextStream& s, const AbstractMetaFunction* func, bool usePyArgs) -{ - AbstractMetaArgumentList args = OverloadData::getArgumentsWithDefaultValues(func); - if (!args.isEmpty()) { - s << INDENT << "if (kwds) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "const char* errorArgName = 0;" << endl; - s << INDENT << "PyObject* "; - foreach (const AbstractMetaArgument* arg, args) { - int pyArgIndex = arg->argumentIndex() - OverloadData::numberOfRemovedArguments(func, arg->argumentIndex()); - QString pyArgName = usePyArgs ? QString("pyargs[%1]").arg(pyArgIndex) : "arg"; - s << "value = PyDict_GetItemString(kwds, \"" << arg->name() << "\");" << endl; - s << INDENT << "if (value) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "if (" << pyArgName << ")" << endl; - { - Indentation indent(INDENT); - s << INDENT << "errorArgName = \"" << arg->name() << "\";" << endl; - } - s << INDENT << "else" << endl; - { - Indentation indent(INDENT); - s << INDENT << pyArgName << " = value;" << endl; - } - } - s << INDENT << '}' << endl; - s << INDENT; - } - s << "if (errorArgName) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_Format(PyExc_TypeError, \"" << fullPythonFunctionName(func); - s << "(): got multiple values for keyword argument '%s'\", errorArgName);" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << INDENT << '}' << endl; - - } - s << INDENT << '}' << endl; - } -} - -QString CppGenerator::argumentNameFromIndex(const AbstractMetaFunction* func, int argIndex, const AbstractMetaClass** wrappedClass) -{ - *wrappedClass = 0; - QString pyArgName; - if (argIndex == -1) { - pyArgName = QString("self"); - *wrappedClass = func->implementingClass(); - } else if (argIndex == 0) { - if (func->type()) { - pyArgName = PYTHON_RETURN_VAR; - *wrappedClass = classes().findClass(func->type()->typeEntry()->name()); - } else { - ReportHandler::warning("Invalid Argument index on function modification: " + func->name()); - } - } else { - int realIndex = argIndex - 1 - OverloadData::numberOfRemovedArguments(func, argIndex - 1); - *wrappedClass = classes().findClass(func->arguments().at(realIndex)->type()->typeEntry()->name()); - if (argIndex == 1 - && OverloadData::isSingleArgument(getFunctionGroups(func->implementingClass())[func->name()])) - pyArgName = QString("arg"); - else - pyArgName = QString("pyargs[%1]").arg(argIndex - 1); - } - return pyArgName; -} - -void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* func, int maxArgs) -{ - s << INDENT << "// " << func->minimalSignature() << (func->isReverseOperator() ? " [reverse operator]": "") << endl; - if (func->isConstructor()) { - foreach (CodeSnip cs, func->injectedCodeSnips()) { - if (cs.position == CodeSnip::End) { - s << INDENT << "overloadId = " << func->ownerClass()->functions().indexOf(const_cast(func)) << ';' << endl; - break; - } - } - } - - if (func->isAbstract()) { - s << INDENT << "if (SbkBaseWrapper_containsCppWrapper(self)) {\n"; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '"; - s << func->ownerClass()->name() << '.' << func->name() << "()' not implemented.\");" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << INDENT << "}\n"; - } - - // Used to provide contextual information to custom code writer function. - const AbstractMetaArgument* lastArg = 0; - - if (func->allowThread()) - s << INDENT << THREAD_STATE_SAVER_VAR ".save();" << endl; - - CodeSnipList snips; - if (func->hasInjectedCode()) { - snips = func->injectedCodeSnips(); - - // Find the last argument available in the method call to provide - // the injected code writer with information to avoid invalid replacements - // on the %# variable. - if (maxArgs > 0 && maxArgs < func->arguments().size() - OverloadData::numberOfRemovedArguments(func)) { - int removedArgs = 0; - for (int i = 0; i < maxArgs + removedArgs; i++) { - lastArg = func->arguments().at(i); - if (func->argumentRemoved(i + 1)) - removedArgs++; - } - } else if (maxArgs != 0 && !func->arguments().isEmpty()) { - lastArg = func->arguments().last(); - } - - writeCodeSnips(s, snips, CodeSnip::Beginning, TypeSystem::TargetLangCode, func, lastArg); - s << endl; - } - - CodeSnipList convRules = getConversionRule(TypeSystem::NativeCode, func); - if (convRules.size()) - writeCodeSnips(s, convRules, CodeSnip::Beginning, TypeSystem::TargetLangCode, func); - - // Code to restore the threadSaver has been written? - bool threadRestored = false; - - if (!func->isUserAdded()) { - bool badModifications = false; - QStringList userArgs; - - if (!func->isCopyConstructor()) { - int removedArgs = 0; - for (int i = 0; i < maxArgs + removedArgs; i++) { - const AbstractMetaArgument* arg = func->arguments().at(i); - if (func->argumentRemoved(i + 1)) { - - // If some argument with default value is removed from a - // method signature, the said value must be explicitly - // added to the method call. - removedArgs++; - - // If have conversion rules I will use this for removed args - bool hasConversionRule = !func->conversionRule(TypeSystem::NativeCode, arg->argumentIndex() + 1).isEmpty(); - if (hasConversionRule) { - userArgs << arg->name() + "_out"; - } else { - if (arg->defaultValueExpression().isEmpty()) - badModifications = true; - else - userArgs << guessScopeForDefaultValue(func, arg); - } - } else { - int idx = arg->argumentIndex() - removedArgs; - QString argName; - - bool hasConversionRule = !func->conversionRule(TypeSystem::NativeCode, arg->argumentIndex() + 1).isEmpty(); - if (hasConversionRule) { - argName = arg->name() + "_out"; - } else { - argName = QString("cpp_arg%1").arg(idx); - if (shouldDereferenceArgumentPointer(arg)) - argName.prepend('*'); - } - userArgs << argName; - } - } - - // If any argument's default value was modified the method must be called - // with this new value whenever the user doesn't pass an explicit value to it. - // Also, any unmodified default value coming after the last user specified - // argument and before the modified argument must be explicitly stated. - QStringList otherArgs; - bool otherArgsModified = false; - bool argsClear = true; - for (int i = func->arguments().size() - 1; i >= maxArgs + removedArgs; i--) { - const AbstractMetaArgument* arg = func->arguments().at(i); - bool defValModified = arg->defaultValueExpression() != arg->originalDefaultValueExpression(); - bool hasConversionRule = !func->conversionRule(TypeSystem::NativeCode, arg->argumentIndex() + 1).isEmpty(); - if (argsClear && !defValModified && !hasConversionRule) - continue; - else - argsClear = false; - - otherArgsModified |= defValModified || hasConversionRule || func->argumentRemoved(i + 1); - - if (!arg->defaultValueExpression().isEmpty()) - otherArgs.prepend(guessScopeForDefaultValue(func, arg)); - else if (hasConversionRule) - otherArgs.prepend(arg->name() + "_out"); - else - badModifications = true; - } - if (otherArgsModified) - userArgs << otherArgs; - } - - bool isCtor = false; - QString methodCall; - QTextStream mc(&methodCall); - - if (badModifications) { - // When an argument is removed from a method signature and no other - // means of calling the method is provided (as with code injection) - // the generator must write a compiler error line stating the situation. - if (func->injectedCodeSnips(CodeSnip::Any, TypeSystem::TargetLangCode).isEmpty()) { - qFatal(qPrintable("No way to call \"" + func->ownerClass()->name() - + "::" + func->minimalSignature() - +"\" with the modifications described in the type system file")); - } - } else if (func->isOperatorOverload()) { - QString firstArg("(*" CPP_SELF_VAR ")"); - QString secondArg("cpp_arg0"); - if (!func->isUnaryOperator() && shouldDereferenceArgumentPointer(func->arguments().first())) { - secondArg.prepend("(*"); - secondArg.append(')'); - } - - if (func->isUnaryOperator()) - std::swap(firstArg, secondArg); - - QString op = func->originalName(); - op = op.right(op.size() - (sizeof("operator")/sizeof(char)-1)); - - if (func->isBinaryOperator()) { - if (func->isReverseOperator()) - std::swap(firstArg, secondArg); - mc << firstArg << ' ' << op << ' ' << secondArg; - } else { - mc << op << ' ' << secondArg; - } - } else if (!injectedCodeCallsCppFunction(func)) { - if (func->isConstructor() || func->isCopyConstructor()) { - isCtor = true; - QString className = wrapperName(func->ownerClass()); - mc << "new " << className << '('; - if (func->isCopyConstructor() && maxArgs == 1) { - mc << '*'; - QString arg("cpp_arg0"); - if (shouldGenerateCppWrapper(func->ownerClass())) - arg = QString("reinterpret_cast<%1*>(%2)").arg(className).arg(arg); - mc << arg; - } else { - mc << userArgs.join(", "); - } - mc << ')'; - } else { - if (func->ownerClass()) { -#ifndef AVOID_PROTECTED_HACK - if (!func->isStatic()) - mc << CPP_SELF_VAR "->"; - if (!func->isAbstract()) - mc << func->ownerClass()->qualifiedCppName() << "::"; - mc << func->originalName(); -#else - if (!func->isStatic()) { - if (func->isProtected()) - mc << "((" << wrapperName(func->ownerClass()) << "*) "; - mc << CPP_SELF_VAR << (func->isProtected() ? ")" : "") << "->"; - } - if (!func->isAbstract()) - mc << (func->isProtected() ? wrapperName(func->ownerClass()) : func->ownerClass()->qualifiedCppName()) << "::"; - mc << func->originalName() << (func->isProtected() ? "_protected" : ""); -#endif - } else { - mc << func->originalName(); - } - mc << '(' << userArgs.join(", ") << ')'; - } - } - - if (!injectedCodeCallsCppFunction(func)) { - s << INDENT; - if (isCtor) { - s << "cptr = "; - } else if (func->type() && !func->isInplaceOperator()) { -#ifdef AVOID_PROTECTED_HACK - QString enumName; - const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(func->type()); - if (metaEnum) { - if (metaEnum->isProtected()) - enumName = protectedEnumSurrogateName(metaEnum); - else - enumName = func->type()->cppSignature(); - methodCall.prepend(enumName + '('); - methodCall.append(')'); - s << enumName; - } else -#endif - s << func->type()->cppSignature(); - s << " " CPP_RETURN_VAR " = "; - } - s << methodCall << ';' << endl; - - if (func->allowThread()) { - s << INDENT << THREAD_STATE_SAVER_VAR ".restore();" << endl; - threadRestored = true; - } - - if (!isCtor && !func->isInplaceOperator() && func->type()) { - s << INDENT << PYTHON_RETURN_VAR " = "; - writeToPythonConversion(s, func->type(), func->ownerClass(), CPP_RETURN_VAR); - s << ';' << endl; - } - } - } - - if (!threadRestored && func->allowThread()) - s << INDENT << THREAD_STATE_SAVER_VAR ".restore();" << endl; - - if (func->hasInjectedCode() && !func->isConstructor()) { - s << endl; - writeCodeSnips(s, snips, CodeSnip::End, TypeSystem::TargetLangCode, func, lastArg); - } - - bool hasReturnPolicy = false; - - // Ownership transference between C++ and Python. - QList ownership_mods; - // Python object reference management. - QList refcount_mods; - foreach (FunctionModification func_mod, func->modifications()) { - foreach (ArgumentModification arg_mod, func_mod.argument_mods) { - if (!arg_mod.ownerships.isEmpty() && arg_mod.ownerships.contains(TypeSystem::TargetLangCode)) - ownership_mods.append(arg_mod); - else if (!arg_mod.referenceCounts.isEmpty()) - refcount_mods.append(arg_mod); - } - } - - if (!ownership_mods.isEmpty()) { - s << endl << INDENT << "// Ownership transferences." << endl; - foreach (ArgumentModification arg_mod, ownership_mods) { - const AbstractMetaClass* wrappedClass = 0; - QString pyArgName = argumentNameFromIndex(func, arg_mod.index, &wrappedClass); - if (!wrappedClass) { - s << "#error Invalid ownership modification for argument " << arg_mod.index << '(' << pyArgName << ')' << endl << endl; - break; - } - - if (arg_mod.index == 0) - hasReturnPolicy = true; - - // The default ownership does nothing. This is useful to avoid automatic heuristically - // based generation of code defining parenting. - if (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::DefaultOwnership) - continue; - - s << INDENT; - if (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::TargetLangOwnership) { - s << "SbkBaseWrapper_setOwnership(" << pyArgName << ", true);"; - } else if (wrappedClass->hasVirtualDestructor()) { - if (arg_mod.index == 0) { - s << "SbkBaseWrapper_setOwnership(" PYTHON_RETURN_VAR ", 0);"; - } else { - s << "BindingManager::instance().transferOwnershipToCpp(" << pyArgName << ");"; - } - } else { - s << "BindingManager::instance().invalidateWrapper(" << pyArgName << ");"; - } - s << endl; - } - - } else if (!refcount_mods.isEmpty()) { - foreach (ArgumentModification arg_mod, refcount_mods) { - if (arg_mod.referenceCounts.first().action != ReferenceCount::Add) - continue; - const AbstractMetaClass* wrappedClass = 0; - QString pyArgName = argumentNameFromIndex(func, arg_mod.index, &wrappedClass); - if (pyArgName.isEmpty()) { - s << "#error Invalid reference count modification for argument " << arg_mod.index << endl << endl; - break; - } - - s << INDENT << "Shiboken::keepReference(reinterpret_cast(self), \""; - QString varName = arg_mod.referenceCounts.first().varName; - if (varName.isEmpty()) - varName = func->minimalSignature() + QString().number(arg_mod.index); - - s << varName << "\", " << pyArgName << ");" << endl; - - if (arg_mod.index == 0) - hasReturnPolicy = true; - } - } - writeParentChildManagement(s, func, !hasReturnPolicy); -} - -QStringList CppGenerator::getAncestorMultipleInheritance(const AbstractMetaClass* metaClass) -{ - QStringList result; - AbstractMetaClassList baseClases = getBaseClasses(metaClass); - if (!baseClases.isEmpty()) { - foreach (const AbstractMetaClass* baseClass, baseClases) { - result.append(QString("((size_t) static_cast(class_ptr)) - base").arg(baseClass->qualifiedCppName())); - result.append(QString("((size_t) static_cast((%2*)((void*)class_ptr))) - base").arg(baseClass->qualifiedCppName()).arg(metaClass->qualifiedCppName())); - } - foreach (const AbstractMetaClass* baseClass, baseClases) - result.append(getAncestorMultipleInheritance(baseClass)); - } - return result; -} - -void CppGenerator::writeMultipleInheritanceInitializerFunction(QTextStream& s, const AbstractMetaClass* metaClass) -{ - QString className = metaClass->qualifiedCppName(); - QStringList ancestors = getAncestorMultipleInheritance(metaClass); - s << "static int mi_offsets[] = { "; - for (int i = 0; i < ancestors.size(); i++) - s << "-1, "; - s << "-1 };" << endl; - s << "int*" << endl; - s << multipleInheritanceInitializerFunctionName(metaClass) << "(const void* cptr)" << endl; - s << '{' << endl; - s << INDENT << "if (mi_offsets[0] == -1) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "std::set offsets;" << endl; - s << INDENT << "std::set::iterator it;" << endl; - s << INDENT << "const " << className << "* class_ptr = reinterpret_cast(cptr);" << endl; - s << INDENT << "size_t base = (size_t) class_ptr;" << endl; - - foreach (QString ancestor, ancestors) - s << INDENT << "offsets.insert(" << ancestor << ");" << endl; - - s << endl; - s << INDENT << "offsets.erase(0);" << endl; - s << endl; - - s << INDENT << "int i = 0;" << endl; - s << INDENT << "for (it = offsets.begin(); it != offsets.end(); it++) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "mi_offsets[i] = *it;" << endl; - s << INDENT << "i++;" << endl; - } - s << INDENT << '}' << endl; - } - s << INDENT << '}' << endl; - s << INDENT << "return mi_offsets;" << endl; - s << '}' << endl; -} - -void CppGenerator::writeSpecialCastFunction(QTextStream& s, const AbstractMetaClass* metaClass) -{ - QString className = metaClass->qualifiedCppName(); - s << "static void* " << cpythonSpecialCastFunctionName(metaClass) << "(void* obj, SbkBaseWrapperType* desiredType)\n"; - s << "{\n"; - s << INDENT << className << "* me = reinterpret_cast<" << className << "*>(obj);\n"; - bool firstClass = true; - foreach (const AbstractMetaClass* baseClass, getAllAncestors(metaClass)) { - s << INDENT << (!firstClass ? "else " : "") << "if (desiredType == reinterpret_cast(" << cpythonTypeNameExt(baseClass->typeEntry()) << "))\n"; - Indentation indent(INDENT); - s << INDENT << "return static_cast<" << baseClass->qualifiedCppName() << "*>(me);\n"; - firstClass = false; - } - s << INDENT << "return me;\n"; - s << "}\n\n"; -} - -void CppGenerator::writeExtendedIsConvertibleFunction(QTextStream& s, const TypeEntry* externalType, const QList& conversions) -{ - s << "static bool " << extendedIsConvertibleFunctionName(externalType) << "(PyObject* pyobj)" << endl; - s << '{' << endl; - s << INDENT << "return "; - bool isFirst = true; - foreach (const AbstractMetaClass* metaClass, conversions) { - Indentation indent(INDENT); - if (isFirst) - isFirst = false; - else - s << endl << INDENT << " || "; - s << cpythonIsConvertibleFunction(metaClass->typeEntry()) << "(pyobj)"; - } - s << ';' << endl; - s << '}' << endl; -} - -void CppGenerator::writeExtendedToCppFunction(QTextStream& s, const TypeEntry* externalType, const QList& conversions) -{ - s << "static void* " << extendedToCppFunctionName(externalType) << "(PyObject* pyobj)" << endl; - s << '{' << endl; - s << INDENT << "void* cptr = 0;" << endl; - bool isFirst = true; - foreach (const AbstractMetaClass* metaClass, conversions) { - s << INDENT; - if (isFirst) - isFirst = false; - else - s << "else "; - s << "if (" << cpythonIsConvertibleFunction(metaClass->typeEntry()) << "(pyobj))" << endl; - Indentation indent(INDENT); - s << INDENT << "cptr = new " << externalType->name() << '('; - writeToCppConversion(s, metaClass, "pyobj"); - s << ");" << endl; - } - s << INDENT << "return cptr;" << endl; - s << '}' << endl; -} - -void CppGenerator::writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, const QList& conversions) -{ - s << INDENT << "// Extended implicit conversions for " << externalType->targetLangPackage() << '.' << externalType->name() << endl; - s << INDENT << "shiboType = reinterpret_cast("; - s << cppApiVariableName(externalType->targetLangPackage()) << '['; - s << getTypeIndexVariableName(externalType) << "]);" << endl; - s << INDENT << "shiboType->ext_isconvertible = " << extendedIsConvertibleFunctionName(externalType) << ';' << endl; - s << INDENT << "shiboType->ext_tocpp = " << extendedToCppFunctionName(externalType) << ';' << endl; -} - -QString CppGenerator::multipleInheritanceInitializerFunctionName(const AbstractMetaClass* metaClass) -{ - if (!hasMultipleInheritanceInAncestry(metaClass)) - return QString(); - return QString("%1_mi_init").arg(cpythonBaseName(metaClass->typeEntry())); -} - -bool CppGenerator::supportsSequenceProtocol(const AbstractMetaClass* metaClass) -{ - foreach(QString funcName, m_sequenceProtocol.keys()) { - if (metaClass->hasFunction(funcName)) - return true; - } - - const ComplexTypeEntry* baseType = metaClass->typeEntry()->baseContainerType(); - if (baseType && (reinterpret_cast(baseType)->type() == ContainerTypeEntry::ListContainer)) - return true; - - return false; -} - -bool CppGenerator::shouldGenerateGetSetList(const AbstractMetaClass* metaClass) -{ - foreach (AbstractMetaField* f, metaClass->fields()) { - if (!f->isStatic()) - return true; - } - return false; -} - -bool CppGenerator::pythonFunctionWrapperUsesListOfArguments(const OverloadData& overloadData) -{ - bool usePyArgs = overloadData.maxArgs() > 1 - || overloadData.referenceFunction()->isConstructor() - || overloadData.hasArgumentWithDefaultValue(); - return usePyArgs; -} - -void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* metaClass) -{ - QString tp_flags; - QString tp_init; - QString tp_new; - QString tp_dealloc; - QString cpp_dtor('0'); - QString tp_as_number('0'); - QString tp_as_sequence('0'); - QString tp_hash('0'); - QString mi_init('0'); - QString obj_copier('0'); - QString mi_specialcast('0'); - QString cppClassName = metaClass->qualifiedCppName(); - QString className = cpythonTypeName(metaClass).replace(QRegExp("_Type$"), ""); - QString baseClassName('0'); - AbstractMetaFunctionList ctors = metaClass->queryFunctions(AbstractMetaClass::Constructors); - bool onlyPrivCtor = !metaClass->hasNonPrivateConstructor(); - - if (metaClass->hasArithmeticOperatorOverload() - || metaClass->hasLogicalOperatorOverload() - || metaClass->hasBitwiseOperatorOverload()) { - tp_as_number = QString("&%1_as_number").arg(cpythonBaseName(metaClass)); - } - - // sequence protocol check - if (supportsSequenceProtocol(metaClass)) - tp_as_sequence = QString("&Py%1_as_sequence").arg(cppClassName); - - if (!metaClass->baseClass()) - baseClassName = "reinterpret_cast(&Shiboken::SbkBaseWrapper_Type)"; - - if (metaClass->isNamespace() || metaClass->hasPrivateDestructor()) { - tp_flags = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES"; - tp_dealloc = metaClass->hasPrivateDestructor() ? - "Shiboken::deallocWrapperWithPrivateDtor" : "0"; - tp_init = "0"; - } else { - if (onlyPrivCtor) - tp_flags = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES"; - else - tp_flags = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES"; - - QString deallocClassName; - if (shouldGenerateCppWrapper(metaClass)) - deallocClassName = wrapperName(metaClass); - else - deallocClassName = cppClassName; - tp_dealloc = "&Shiboken::deallocWrapper"; - - QString dtorClassName = metaClass->qualifiedCppName(); -#ifdef AVOID_PROTECTED_HACK - if (metaClass->hasProtectedDestructor()) - dtorClassName = wrapperName(metaClass); -#endif - cpp_dtor = "&Shiboken::callCppDestructor<" + dtorClassName + " >"; - - tp_init = onlyPrivCtor ? "0" : cpythonFunctionName(ctors.first()); - } - - QString tp_getattro('0'); - QString tp_setattro('0'); - if (usePySideExtensions() && (metaClass->qualifiedCppName() == "QObject")) { - tp_getattro = cpythonGetattroFunctionName(metaClass); - tp_setattro = cpythonSetattroFunctionName(metaClass); - } else if (classNeedsGetattroFunction(metaClass)) { - tp_getattro = cpythonGetattroFunctionName(metaClass); - } - - if (metaClass->hasPrivateDestructor() || onlyPrivCtor) - tp_new = "0"; - else - tp_new = "Shiboken::SbkBaseWrapper_TpNew"; - - QString tp_richcompare = QString('0'); - if (metaClass->hasComparisonOperatorOverload()) - tp_richcompare = cpythonBaseName(metaClass) + "_richcompare"; - - QString tp_getset = QString('0'); - if (shouldGenerateGetSetList(metaClass)) - tp_getset = cpythonGettersSettersDefinitionName(metaClass); - - // search for special functions - ShibokenGenerator::clearTpFuncs(); - foreach (AbstractMetaFunction* func, metaClass->functions()) { - if (m_tpFuncs.contains(func->name())) - m_tpFuncs[func->name()] = cpythonFunctionName(func); - } - - // class or some ancestor has multiple inheritance - const AbstractMetaClass* miClass = getMultipleInheritingClass(metaClass); - if (miClass) { - if (metaClass == miClass) { - mi_init = multipleInheritanceInitializerFunctionName(miClass); - writeMultipleInheritanceInitializerFunction(s, metaClass); - } - mi_specialcast = '&'+cpythonSpecialCastFunctionName(metaClass); - writeSpecialCastFunction(s, metaClass); - s << endl; - } - - if (metaClass->typeEntry()->isValue() && shouldGenerateCppWrapper(metaClass)) - obj_copier = '&' + cpythonBaseName(metaClass) + "_ObjCopierFunc"; - - if (!metaClass->typeEntry()->hashFunction().isEmpty()) - tp_hash = '&' + cpythonBaseName(metaClass) + "_HashFunc"; - - s << "// Class Definition -----------------------------------------------" << endl; - s << "extern \"C\" {" << endl; - s << "static SbkBaseWrapperType " << className + "_Type" << " = { { {" << endl; - s << INDENT << "PyObject_HEAD_INIT(&Shiboken::SbkBaseWrapperType_Type)" << endl; - s << INDENT << "/*ob_size*/ 0," << endl; - s << INDENT << "/*tp_name*/ \"" << metaClass->fullName() << "\"," << endl; - s << INDENT << "/*tp_basicsize*/ sizeof(Shiboken::SbkBaseWrapper)," << endl; - s << INDENT << "/*tp_itemsize*/ 0," << endl; - s << INDENT << "/*tp_dealloc*/ " << tp_dealloc << ',' << endl; - s << INDENT << "/*tp_print*/ 0," << endl; - s << INDENT << "/*tp_getattr*/ 0," << endl; - s << INDENT << "/*tp_setattr*/ 0," << endl; - s << INDENT << "/*tp_compare*/ 0," << endl; - s << INDENT << "/*tp_repr*/ " << m_tpFuncs["__repr__"] << "," << endl; - s << INDENT << "/*tp_as_number*/ " << tp_as_number << ',' << endl; - s << INDENT << "/*tp_as_sequence*/ " << tp_as_sequence << ',' << endl; - s << INDENT << "/*tp_as_mapping*/ 0," << endl; - s << INDENT << "/*tp_hash*/ " << tp_hash << ',' << endl; - s << INDENT << "/*tp_call*/ 0," << endl; - s << INDENT << "/*tp_str*/ " << m_tpFuncs["__str__"] << ',' << endl; - s << INDENT << "/*tp_getattro*/ " << tp_getattro << ',' << endl; - s << INDENT << "/*tp_setattro*/ " << tp_setattro << ',' << endl; - s << INDENT << "/*tp_as_buffer*/ 0," << endl; - s << INDENT << "/*tp_flags*/ " << tp_flags << ',' << endl; - s << INDENT << "/*tp_doc*/ 0," << endl; - s << INDENT << "/*tp_traverse*/ 0," << endl; - s << INDENT << "/*tp_clear*/ 0," << endl; - s << INDENT << "/*tp_richcompare*/ " << tp_richcompare << ',' << endl; - s << INDENT << "/*tp_weaklistoffset*/ 0," << endl; - s << INDENT << "/*tp_iter*/ 0," << endl; - s << INDENT << "/*tp_iternext*/ 0," << endl; - s << INDENT << "/*tp_methods*/ " << className << "_methods," << endl; - s << INDENT << "/*tp_members*/ 0," << endl; - s << INDENT << "/*tp_getset*/ " << tp_getset << ',' << endl; - s << INDENT << "/*tp_base*/ " << baseClassName << ',' << endl; - s << INDENT << "/*tp_dict*/ 0," << endl; - s << INDENT << "/*tp_descr_get*/ 0," << endl; - s << INDENT << "/*tp_descr_set*/ 0," << endl; - s << INDENT << "/*tp_dictoffset*/ 0," << endl; - s << INDENT << "/*tp_init*/ " << tp_init << ',' << endl; - s << INDENT << "/*tp_alloc*/ 0," << endl; - s << INDENT << "/*tp_new*/ " << tp_new << ',' << endl; - s << INDENT << "/*tp_free*/ 0," << endl; - s << INDENT << "/*tp_is_gc*/ 0," << endl; - s << INDENT << "/*tp_bases*/ 0," << endl; - s << INDENT << "/*tp_mro*/ 0," << endl; - s << INDENT << "/*tp_cache*/ 0," << endl; - s << INDENT << "/*tp_subclasses*/ 0," << endl; - s << INDENT << "/*tp_weaklist*/ 0" << endl; - s << "}, }," << endl; - s << INDENT << "/*mi_offsets*/ 0," << endl; - s << INDENT << "/*mi_init*/ " << mi_init << ',' << endl; - s << INDENT << "/*mi_specialcast*/ " << mi_specialcast << ',' << endl; - s << INDENT << "/*type_discovery*/ 0," << endl; - s << INDENT << "/*obj_copier*/ " << obj_copier << ',' << endl; - s << INDENT << "/*ext_isconvertible*/ 0," << endl; - s << INDENT << "/*ext_tocpp*/ 0," << endl; - s << INDENT << "/*cpp_dtor*/ " << cpp_dtor << ',' << endl; - s << INDENT << "/*is_multicpp*/ 0," << endl; - s << INDENT << "/*is_user_type*/ 0," << endl; - QString suffix; - if (metaClass->typeEntry()->isObject() || metaClass->typeEntry()->isQObject()) - suffix = "*"; - s << INDENT << "/*original_name*/ \"" << metaClass->qualifiedCppName() << suffix << "\"," << endl; - s << INDENT << "/*user_data*/ 0" << endl; - s << "};" << endl; - s << "} //extern" << endl; -} - - -void CppGenerator::writeSequenceMethods(QTextStream& s, const AbstractMetaClass* metaClass) -{ - - QMap funcs; - bool injectedCode = false; - - QHash< QString, QPair< QString, QString > >::const_iterator it = m_sequenceProtocol.begin(); - for (; it != m_sequenceProtocol.end(); ++it) { - const AbstractMetaFunction* func = metaClass->findFunction(it.key()); - if (!func) - continue; - injectedCode = true; - QString funcName = cpythonFunctionName(func); - QString funcArgs = it.value().first; - QString funcRetVal = it.value().second; - - CodeSnipList snips = func->injectedCodeSnips(CodeSnip::Any, TypeSystem::TargetLangCode); - s << funcRetVal << ' ' << funcName << '(' << funcArgs << ')' << endl << '{' << endl; - writeInvalidCppObjectCheck(s); - - writeCppSelfDefinition(s, func); - - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); - writeCodeSnips(s, snips,CodeSnip::Any, TypeSystem::TargetLangCode, func, lastArg); - s << '}' << endl << endl; - } - - if (!injectedCode) - writeStdListWrapperMethods(s, metaClass); -} - -void CppGenerator::writeTypeAsSequenceDefinition(QTextStream& s, const AbstractMetaClass* metaClass) -{ - QString className = metaClass->qualifiedCppName(); - QMap funcs; - - bool hasFunctions = false; - foreach(QString funcName, m_sequenceProtocol.keys()) { - const AbstractMetaFunction* func = metaClass->findFunction(funcName); - funcs[funcName] = func ? cpythonFunctionName(func).prepend("&") : "0"; - if (!hasFunctions && func) - hasFunctions = true; - } - - //use default implementation - if (!hasFunctions) { - QString baseName = cpythonBaseName(metaClass->typeEntry()); - funcs["__len__"] = baseName + "__len__"; - funcs["__getitem__"] = baseName + "__getitem__"; - funcs["__setitem__"] = baseName + "__setitem__"; - } - - s << "static PySequenceMethods Py" << className << "_as_sequence = {\n" - << INDENT << "/*sq_length*/ " << funcs["__len__"] << ",\n" - << INDENT << "/*sq_concat*/ " << funcs["__concat__"] << ",\n" - << INDENT << "/*sq_repeat*/ 0,\n" - << INDENT << "/*sq_item*/ " << funcs["__getitem__"] << ",\n" - << INDENT << "/*sq_slice*/ " << funcs["__getslice__"] << ",\n" - << INDENT << "/*sq_ass_item*/ " << funcs["__setitem__"] << ",\n" - << INDENT << "/*sq_ass_slice*/ " << funcs["__setslice__"] << ",\n" - << INDENT << "/*sq_contains*/ " << funcs["__contains__"] << ",\n" - << INDENT << "/*sq_inplace_concat*/ 0,\n" - << INDENT << "/*sq_inplace_repeat*/ 0\n" - << "};\n\n"; -} - -void CppGenerator::writeTypeAsNumberDefinition(QTextStream& s, const AbstractMetaClass* metaClass) -{ - QMap nb; - - nb["__add__"] = QString('0'); - nb["__sub__"] = QString('0'); - nb["__mul__"] = QString('0'); - nb["__div__"] = QString('0'); - nb["__mod__"] = QString('0'); - nb["__neg__"] = QString('0'); - nb["__pos__"] = QString('0'); - nb["__invert__"] = QString('0'); - nb["__lshift__"] = QString('0'); - nb["__rshift__"] = QString('0'); - nb["__and__"] = QString('0'); - nb["__xor__"] = QString('0'); - nb["__or__"] = QString('0'); - nb["__iadd__"] = QString('0'); - nb["__isub__"] = QString('0'); - nb["__imul__"] = QString('0'); - nb["__idiv__"] = QString('0'); - nb["__imod__"] = QString('0'); - nb["__ilshift__"] = QString('0'); - nb["__irshift__"] = QString('0'); - nb["__iand__"] = QString('0'); - nb["__ixor__"] = QString('0'); - nb["__ior__"] = QString('0'); - - QList opOverloads = - filterGroupedOperatorFunctions(metaClass, - AbstractMetaClass::ArithmeticOp - | AbstractMetaClass::LogicalOp - | AbstractMetaClass::BitwiseOp); - - foreach (AbstractMetaFunctionList opOverload, opOverloads) { - const AbstractMetaFunction* rfunc = opOverload[0]; - QString opName = ShibokenGenerator::pythonOperatorFunctionName(rfunc); - nb[opName] = cpythonFunctionName(rfunc); - } - - s << "static PyNumberMethods " << cpythonBaseName(metaClass); - s << "_as_number = {" << endl; - s << INDENT << "/*nb_add*/ (binaryfunc)" << nb["__add__"] << ',' << endl; - s << INDENT << "/*nb_subtract*/ (binaryfunc)" << nb["__sub__"] << ',' << endl; - s << INDENT << "/*nb_multiply*/ (binaryfunc)" << nb["__mul__"] << ',' << endl; - s << INDENT << "/*nb_divide*/ (binaryfunc)" << nb["__div__"] << ',' << endl; - s << INDENT << "/*nb_remainder*/ (binaryfunc)" << nb["__mod__"] << ',' << endl; - s << INDENT << "/*nb_divmod*/ 0," << endl; - s << INDENT << "/*nb_power*/ 0," << endl; - s << INDENT << "/*nb_negative*/ (unaryfunc)" << nb["__neg__"] << ',' << endl; - s << INDENT << "/*nb_positive*/ (unaryfunc)" << nb["__pos__"] << ',' << endl; - s << INDENT << "/*nb_absolute*/ 0," << endl; - s << INDENT << "/*nb_nonzero*/ 0," << endl; - s << INDENT << "/*nb_invert*/ (unaryfunc)" << nb["__invert__"] << ',' << endl; - s << INDENT << "/*nb_lshift*/ (binaryfunc)" << nb["__lshift__"] << ',' << endl; - s << INDENT << "/*nb_rshift*/ (binaryfunc)" << nb["__rshift__"] << ',' << endl; - s << INDENT << "/*nb_and*/ (binaryfunc)" << nb["__and__"] << ',' << endl; - s << INDENT << "/*nb_xor*/ (binaryfunc)" << nb["__xor__"] << ',' << endl; - s << INDENT << "/*nb_or*/ (binaryfunc)" << nb["__or__"] << ',' << endl; - s << INDENT << "/*nb_coerce*/ 0," << endl; - s << INDENT << "/*nb_int*/ 0," << endl; - s << INDENT << "/*nb_long*/ 0," << endl; - s << INDENT << "/*nb_float*/ 0," << endl; - s << INDENT << "/*nb_oct*/ 0," << endl; - s << INDENT << "/*nb_hex*/ 0," << endl; - s << INDENT << "/*nb_inplace_add*/ (binaryfunc)" << nb["__iadd__"] << ',' << endl; - s << INDENT << "/*nb_inplace_subtract*/ (binaryfunc)" << nb["__isub__"] << ',' << endl; - s << INDENT << "/*nb_inplace_multiply*/ (binaryfunc)" << nb["__imul__"] << ',' << endl; - s << INDENT << "/*nb_inplace_divide*/ (binaryfunc)" << nb["__idiv__"] << ',' << endl; - s << INDENT << "/*nb_inplace_remainder*/ (binaryfunc)" << nb["__imod__"] << ',' << endl; - s << INDENT << "/*nb_inplace_power*/ 0," << endl; - s << INDENT << "/*nb_inplace_lshift*/ (binaryfunc)" << nb["__ilshift__"] << ',' << endl; - s << INDENT << "/*nb_inplace_rshift*/ (binaryfunc)" << nb["__irshift__"] << ',' << endl; - s << INDENT << "/*nb_inplace_and*/ (binaryfunc)" << nb["__iand__"] << ',' << endl; - s << INDENT << "/*nb_inplace_xor*/ (binaryfunc)" << nb["__ixor__"] << ',' << endl; - s << INDENT << "/*nb_inplace_or*/ (binaryfunc)" << nb["__ior__"] << ',' << endl; - s << INDENT << "/*nb_floor_divide*/ 0," << endl; - s << INDENT << "/*nb_true_divide*/ 0," << endl; - s << INDENT << "/*nb_inplace_floor_divide*/ 0," << endl; - s << INDENT << "/*nb_inplace_true_divide*/ 0," << endl; - s << INDENT << "/*nb_index*/ 0" << endl; - s << "};" << endl << endl; -} - -void CppGenerator::writeGetterFunction(QTextStream& s, const AbstractMetaField* metaField) -{ - s << "static PyObject* " << cpythonGetterFunctionName(metaField) << "(PyObject* self, void*)" << endl; - s << '{' << endl; - s << INDENT << "return "; - - QString cppField; -#ifdef AVOID_PROTECTED_HACK - if (metaField->isProtected()) - cppField = QString("((%1*)%2)->%3()").arg(wrapperName(metaField->enclosingClass())).arg(cpythonWrapperCPtr(metaField->enclosingClass(), "self")).arg(protectedFieldGetterName(metaField)); - else -#endif - cppField= QString("%1->%2").arg(cpythonWrapperCPtr(metaField->enclosingClass(), "self")).arg(metaField->name()); - writeToPythonConversion(s, metaField->type(), metaField->enclosingClass(), cppField); - s << ';' << endl; - s << '}' << endl; -} - -void CppGenerator::writeSetterFunction(QTextStream& s, const AbstractMetaField* metaField) -{ - s << "static int " << cpythonSetterFunctionName(metaField) << "(PyObject* self, PyObject* value, void*)" << endl; - s << '{' << endl; - - s << INDENT << "if (value == 0) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_TypeError, \"'"; - s << metaField->name() << "' may not be deleted\");" << endl; - s << INDENT << "return -1;" << endl; - } - s << INDENT << '}' << endl; - - s << INDENT << "if (!"; - writeTypeCheck(s, metaField->type(), "value", isNumber(metaField->type()->typeEntry())); - s << ") {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_TypeError, \"wrong type attributed to '"; - s << metaField->name() << "', '" << metaField->type()->name() << "' or convertible type expected\");" << endl; - s << INDENT << "return -1;" << endl; - } - s << INDENT << '}' << endl << endl; - - s << INDENT; -#ifdef AVOID_PROTECTED_HACK - if (metaField->isProtected()) { - QString fieldStr = QString("((%1*)%2)->%3").arg(wrapperName(metaField->enclosingClass())).arg(cpythonWrapperCPtr(metaField->enclosingClass(), "self")).arg(protectedFieldSetterName(metaField)); - s << fieldStr << '('; - writeToCppConversion(s, metaField->type(), metaField->enclosingClass(), "value"); - s << ')'; - } else { -#endif - QString fieldStr = QString("%1->%2").arg(cpythonWrapperCPtr(metaField->enclosingClass(), "self")).arg(metaField->name()); - s << fieldStr << " = "; - writeToCppConversion(s, metaField->type(), metaField->enclosingClass(), "value"); -#ifdef AVOID_PROTECTED_HACK - } -#endif - s << ';' << endl << endl; - - - bool pythonWrapperRefCounting = metaField->type()->typeEntry()->isObject() - || metaField->type()->isValuePointer(); - if (pythonWrapperRefCounting) { - s << INDENT << "Shiboken::keepReference(reinterpret_cast(self), \""; - s << metaField->name() << "\", value);" << endl; - //s << INDENT << "Py_XDECREF(oldvalue);" << endl; - s << endl; - } - - s << INDENT << "return 0;" << endl; - s << '}' << endl; -} - -void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaClass* metaClass) -{ - QString baseName = cpythonBaseName(metaClass); - s << "static PyObject* "; - s << baseName << "_richcompare(PyObject* self, PyObject* other, int op)" << endl; - s << '{' << endl; - QList cmpOverloads = filterGroupedOperatorFunctions(metaClass, AbstractMetaClass::ComparisonOp); - s << INDENT << "bool result = false;" << endl; - s << INDENT << metaClass->qualifiedCppName() << "& cpp_self = *" << cpythonWrapperCPtr(metaClass) << ';' << endl; - s << endl; - - s << INDENT << "switch (op) {" << endl; - { - Indentation indent(INDENT); - foreach (AbstractMetaFunctionList overloads, cmpOverloads) { - OverloadData overloadData(overloads, this); - const AbstractMetaFunction* rfunc = overloads[0]; - - s << INDENT << "case " << ShibokenGenerator::pythonRichCompareOperatorId(rfunc) << ':' << endl; - - Indentation indent(INDENT); - - QString op = rfunc->originalName(); - op = op.right(op.size() - QString("operator").size()); - - int alternativeNumericTypes = 0; - foreach (const AbstractMetaFunction* func, overloads) { - if (!func->isStatic() && - ShibokenGenerator::isNumber(func->arguments()[0]->type()->typeEntry())) - alternativeNumericTypes++; - } - - bool first = true; - bool comparesWithSameType = false; - foreach (const AbstractMetaFunction* func, overloads) { - if (func->isStatic()) - continue; - - const AbstractMetaType* type = func->arguments()[0]->type(); - bool numberType = alternativeNumericTypes == 1 || ShibokenGenerator::isPyInt(type); - - if (!comparesWithSameType) - comparesWithSameType = type->typeEntry() == metaClass->typeEntry(); - - if (!first) { - s << " else "; - } else { - first = false; - s << INDENT; - } - - s << "if (" << cpythonIsConvertibleFunction(type, numberType) << "(other)) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "// " << func->signature() << endl; - s << INDENT; - AbstractMetaClass* clz = classes().findClass(type->typeEntry()); - if (type->typeEntry()->isValue()) { - Q_ASSERT(clz); - s << clz->qualifiedCppName() << '*'; - } else - s << translateTypeForWrapperMethod(type, metaClass); - s << " cpp_other = "; - if (type->typeEntry()->isValue()) - s << cpythonWrapperCPtr(type, "other"); - else - writeToCppConversion(s, type, metaClass, "other"); - s << ';' << endl; - - s << INDENT << "result = "; - // It's a value type and the conversion for a pointer returned null. - if (type->typeEntry()->isValue()) { - s << "!cpp_other ? cpp_self == "; - writeToCppConversion(s, type, metaClass, "other", ExcludeReference | ExcludeConst); - s << " : "; - } - s << "(cpp_self " << op << ' ' << (type->typeEntry()->isValue() ? "(*" : ""); - s << "cpp_other" << (type->typeEntry()->isValue() ? ")" : "") << ");" << endl; - } - s << INDENT << '}'; - } - - // Compares with implicit conversions - if (comparesWithSameType && !metaClass->implicitConversions().isEmpty()) { - AbstractMetaType temporaryType; - temporaryType.setTypeEntry(metaClass->typeEntry()); - temporaryType.setConstant(true); - temporaryType.setReference(false); - temporaryType.setTypeUsagePattern(AbstractMetaType::ValuePattern); - s << " else if (" << cpythonIsConvertibleFunction(metaClass->typeEntry()); - s << "(other)) {" << endl; - { - Indentation indent(INDENT); - writeArgumentConversion(s, &temporaryType, "cpp_other", "other", metaClass); - s << INDENT << "result = (cpp_self " << op << " (*cpp_other));" << endl; - } - s << INDENT << '}'; - } - - s << " else goto " << baseName << "_RichComparison_TypeError;" << endl; - s << endl; - - s << INDENT << "break;" << endl; - } - s << INDENT << "default:" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"operator not implemented.\");" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - } - s << INDENT << '}' << endl << endl; - - s << INDENT << "if (result)" << endl; - { - Indentation indent(INDENT); - s << INDENT << "Py_RETURN_TRUE;" << endl; - } - s << INDENT << baseName << "_RichComparison_TypeError:" << endl; - s << INDENT << "Py_RETURN_FALSE;" << endl << endl; - s << '}' << endl << endl; -} - -void CppGenerator::writeMethodDefinitionEntry(QTextStream& s, const AbstractMetaFunctionList overloads) -{ - Q_ASSERT(!overloads.isEmpty()); - OverloadData overloadData(overloads, this); - bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(overloadData); - const AbstractMetaFunction* func = overloadData.referenceFunction(); - - s << '"' << func->name() << "\", (PyCFunction)" << cpythonFunctionName(func) << ", "; - if (overloadData.maxArgs() < 2 && !usePyArgs) { - bool minZero = overloadData.minArgs() == 0; - bool maxOne = overloadData.maxArgs() == 1; - if (minZero) - s << "METH_NOARGS" << (maxOne ? "|" : ""); - if (maxOne) - s << "METH_O"; - } else { - s << "METH_VARARGS"; - if (overloadData.hasArgumentWithDefaultValue()) - s << "|METH_KEYWORDS"; - } - if (func->ownerClass() && overloadData.hasStaticFunction()) - s << "|METH_STATIC"; -} - -void CppGenerator::writeMethodDefinition(QTextStream& s, const AbstractMetaFunctionList overloads) -{ - Q_ASSERT(!overloads.isEmpty()); - const AbstractMetaFunction* func = overloads.first(); - if (m_tpFuncs.contains(func->name())) - return; - - s << INDENT; - if (OverloadData::hasStaticAndInstanceFunctions(overloads)) { - s << cpythonMethodDefinitionName(func); - } else { - s << '{'; - writeMethodDefinitionEntry(s, overloads); - s << '}'; - } - s << ',' << endl; -} - -void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnum* cppEnum) -{ - QString cpythonName = cpythonEnumName(cppEnum); - QString addFunction; - if (cppEnum->enclosingClass()) - addFunction = "PyDict_SetItemString(" + cpythonTypeName(cppEnum->enclosingClass()) + ".super.ht_type.tp_dict,"; - else - addFunction = "PyModule_AddObject(module,"; - - s << INDENT << "// init enum class: " << cppEnum->name() << endl; - s << INDENT << cpythonTypeNameExt(cppEnum->typeEntry()) << " = &" << cpythonTypeName(cppEnum->typeEntry()) << ';' << endl; - s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << cpythonName << "_Type) < 0)" << endl; - s << INDENT << INDENT << "return;" << endl; - - s << INDENT << "Py_INCREF(&" << cpythonName << "_Type);" << endl; - - s << INDENT << addFunction << endl; - s << INDENT << INDENT << INDENT << '\"' << cppEnum->name() << "\","; - s << "((PyObject*)&" << cpythonName << "_Type));" << endl << endl; - - FlagsTypeEntry* flags = cppEnum->typeEntry()->flags(); - if (flags) { - QString flagsName = cpythonFlagsName(flags); - s << INDENT << "// init flags class: " << flags->name() << endl; - s << INDENT << cpythonTypeNameExt(flags) << " = &" << cpythonTypeName(flags) << ';' << endl; - - s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << flagsName << "_Type) < 0)" << endl; - s << INDENT << INDENT << "return;" << endl; - - s << INDENT << "Py_INCREF(&" << flagsName << "_Type);" << endl; - - s << INDENT << addFunction << endl; - s << INDENT << INDENT << INDENT << '\"' << flags->flagsName() << "\","; - s << "((PyObject*)&" << flagsName << "_Type));" << endl << endl; - } - - - foreach (const AbstractMetaEnumValue* enumValue, cppEnum->values()) { - if (cppEnum->typeEntry()->isEnumValueRejected(enumValue->name())) - continue; - - s << INDENT << "enum_item = Shiboken::SbkEnumObject_New(&"; - s << cpythonName << "_Type," << endl; - { - Indentation indent(INDENT); - s << INDENT; -#ifdef AVOID_PROTECTED_HACK - if (!cppEnum->isProtected()) { -#endif - s << "(long) "; - if (cppEnum->enclosingClass()) - s << cppEnum->enclosingClass()->qualifiedCppName() << "::"; - s << enumValue->name(); -#ifdef AVOID_PROTECTED_HACK - } else { - s << enumValue->value(); - } -#endif - s << ", \"" << enumValue->name() << "\");" << endl; - } - - s << INDENT << addFunction << endl; - { - Indentation indent(INDENT); - s << INDENT << '"' << enumValue->name() << "\", enum_item);" << endl; - } - s << INDENT << "PyDict_SetItemString(" << cpythonName << "_Type.tp_dict," << endl; - { - Indentation indent(INDENT); - s << INDENT << '"' << enumValue->name() << "\", enum_item);" << endl; - } - - } - - // TypeResolver stuff - s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver(\""; - if (cppEnum->enclosingClass()) - s << cppEnum->enclosingClass()->qualifiedCppName() << "::"; - s << cppEnum->name() << "\");\n"; - - - s << endl; -} - -void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaClass* metaClass) -{ - QHash signatures; - - foreach (const AbstractMetaFunction* cppSignal, metaClass->cppSignalFunctions()) { - QString signature; - if (cppSignal->declaringClass() == metaClass) { - if (cppSignal->arguments().count()) { - for (int i = 0; i < cppSignal->arguments().count(); ++i) { - if (i > 0) - signature += ", "; - AbstractMetaArgument *a = cppSignal->arguments().at(i); - signature += a->type()->cppSignature(); - } - } else { - signature = "void"; - } - signatures[cppSignal->name()].append(QMetaObject::normalizedSignature(signature.toAscii())); - } - } - - if (signatures.size() == 0) - return; - - s << INDENT << "// Initialize signals" << endl; - s << INDENT << "PyObject* signal_item;" << endl << endl; - - foreach(QString funcName, signatures.keys()) { - s << INDENT << "signal_item = PySide::signalNew(\"" << funcName <<"\""; - foreach(QString signature, signatures[funcName]) - s << ", \"" + signature << "\""; - s << ", NULL);" << endl; - s << INDENT << "PyDict_SetItemString(" + cpythonTypeName(metaClass) + ".super.ht_type.tp_dict"; - s << ", \"" << funcName << "\", signal_item);" << endl; - s << INDENT << "Py_DECREF(signal_item);" << endl; - } - s << endl; -} - -void CppGenerator::writeEnumNewMethod(QTextStream& s, const AbstractMetaEnum* cppEnum) -{ - QString cpythonName = cpythonEnumName(cppEnum); - s << "static PyObject* "; - s << cpythonName << "_New(PyTypeObject* type, PyObject* args, PyObject* kwds)" << endl; - s << '{' << endl; - s << INDENT << "int item_value = 0;" << endl; - s << INDENT << "if (!PyArg_ParseTuple(args, \"|i:__new__\", &item_value))" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return 0;" << endl; - } - s << INDENT << "PyObject* self = Shiboken::SbkEnumObject_New(type, item_value);" << endl << endl; - s << INDENT << "if (!self)" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return 0;" << endl; - } - s << INDENT << "return self;" << endl << '}' << endl; -} - -void CppGenerator::writeEnumDefinition(QTextStream& s, const AbstractMetaEnum* cppEnum) -{ - QString cpythonName = cpythonEnumName(cppEnum); - QString tp_as_number("0"); - if (cppEnum->typeEntry()->flags()) - tp_as_number = QString("&%1_as_number").arg(cpythonName); - - - s << "static PyGetSetDef " << cpythonName << "_getsetlist[] = {" << endl; - s << INDENT << "{const_cast(\"name\"), (getter)Shiboken::SbkEnumObject_name}," << endl; - s << INDENT << "{0} // Sentinel" << endl; - s << "};" << endl << endl; - - QString newFunc = cpythonName + "_New"; - - s << "// forward declaration of new function" << endl; - s << "static PyObject* " << newFunc << "(PyTypeObject*, PyObject*, PyObject*);" << endl << endl; - - s << "static PyTypeObject " << cpythonName << "_Type = {" << endl; - s << INDENT << "PyObject_HEAD_INIT(&Shiboken::SbkEnumType_Type)" << endl; - s << INDENT << "/*ob_size*/ 0," << endl; - s << INDENT << "/*tp_name*/ \"" << cppEnum->name() << "\"," << endl; - s << INDENT << "/*tp_basicsize*/ sizeof(Shiboken::SbkEnumObject)," << endl; - s << INDENT << "/*tp_itemsize*/ 0," << endl; - s << INDENT << "/*tp_dealloc*/ 0," << endl; - s << INDENT << "/*tp_print*/ 0," << endl; - s << INDENT << "/*tp_getattr*/ 0," << endl; - s << INDENT << "/*tp_setattr*/ 0," << endl; - s << INDENT << "/*tp_compare*/ 0," << endl; - s << INDENT << "/*tp_repr*/ Shiboken::SbkEnumObject_repr," << endl; - s << INDENT << "/*tp_as_number*/ " << tp_as_number << ',' << endl; - s << INDENT << "/*tp_as_sequence*/ 0," << endl; - s << INDENT << "/*tp_as_mapping*/ 0," << endl; - s << INDENT << "/*tp_hash*/ 0," << endl; - s << INDENT << "/*tp_call*/ 0," << endl; - s << INDENT << "/*tp_str*/ Shiboken::SbkEnumObject_repr," << endl; - s << INDENT << "/*tp_getattro*/ 0," << endl; - s << INDENT << "/*tp_setattro*/ 0," << endl; - s << INDENT << "/*tp_as_buffer*/ 0," << endl; - s << INDENT << "/*tp_flags*/ Py_TPFLAGS_DEFAULT," << endl; - s << INDENT << "/*tp_doc*/ 0," << endl; - s << INDENT << "/*tp_traverse*/ 0," << endl; - s << INDENT << "/*tp_clear*/ 0," << endl; - s << INDENT << "/*tp_richcompare*/ 0," << endl; - s << INDENT << "/*tp_weaklistoffset*/ 0," << endl; - s << INDENT << "/*tp_iter*/ 0," << endl; - s << INDENT << "/*tp_iternext*/ 0," << endl; - s << INDENT << "/*tp_methods*/ 0," << endl; - s << INDENT << "/*tp_members*/ 0," << endl; - s << INDENT << "/*tp_getset*/ " << cpythonName << "_getsetlist," << endl; - s << INDENT << "/*tp_base*/ &PyInt_Type," << endl; - s << INDENT << "/*tp_dict*/ 0," << endl; - s << INDENT << "/*tp_descr_get*/ 0," << endl; - s << INDENT << "/*tp_descr_set*/ 0," << endl; - s << INDENT << "/*tp_dictoffset*/ 0," << endl; - s << INDENT << "/*tp_init*/ 0," << endl; - s << INDENT << "/*tp_alloc*/ 0," << endl; - s << INDENT << "/*tp_new*/ " << newFunc << ',' << endl; - s << INDENT << "/*tp_free*/ 0," << endl; - s << INDENT << "/*tp_is_gc*/ 0," << endl; - s << INDENT << "/*tp_bases*/ 0," << endl; - s << INDENT << "/*tp_mro*/ 0," << endl; - s << INDENT << "/*tp_cache*/ 0," << endl; - s << INDENT << "/*tp_subclasses*/ 0," << endl; - s << INDENT << "/*tp_weaklist*/ 0" << endl; - s << "};" << endl << endl; - - writeEnumNewMethod(s, cppEnum); - s << endl; -} - -void CppGenerator::writeFlagsMethods(QTextStream& s, const AbstractMetaEnum* cppEnum) -{ - writeFlagsBinaryOperator(s, cppEnum, "and", "&"); - writeFlagsBinaryOperator(s, cppEnum, "or", "|"); - writeFlagsBinaryOperator(s, cppEnum, "xor", "^"); - - writeFlagsUnaryOperator(s, cppEnum, "invert", "~"); - s << endl; -} - -void CppGenerator::writeFlagsNumberMethodsDefinition(QTextStream& s, const AbstractMetaEnum* cppEnum) -{ - QString cpythonName = cpythonEnumName(cppEnum); - - s << "static PyNumberMethods " << cpythonName << "_as_number = {" << endl; - s << INDENT << "/*nb_add*/ 0," << endl; - s << INDENT << "/*nb_subtract*/ 0," << endl; - s << INDENT << "/*nb_multiply*/ 0," << endl; - s << INDENT << "/*nb_divide*/ 0," << endl; - s << INDENT << "/*nb_remainder*/ 0," << endl; - s << INDENT << "/*nb_divmod*/ 0," << endl; - s << INDENT << "/*nb_power*/ 0," << endl; - s << INDENT << "/*nb_negative*/ 0," << endl; - s << INDENT << "/*nb_positive*/ 0," << endl; - s << INDENT << "/*nb_absolute*/ 0," << endl; - s << INDENT << "/*nb_nonzero*/ 0," << endl; - s << INDENT << "/*nb_invert*/ (unaryfunc)" << cpythonName << "___invert__" << "," << endl; - s << INDENT << "/*nb_lshift*/ 0," << endl; - s << INDENT << "/*nb_rshift*/ 0," << endl; - s << INDENT << "/*nb_and*/ (binaryfunc)" << cpythonName << "___and__" << ',' << endl; - s << INDENT << "/*nb_xor*/ (binaryfunc)" << cpythonName << "___xor__" << ',' << endl; - s << INDENT << "/*nb_or*/ (binaryfunc)" << cpythonName << "___or__" << ',' << endl; - s << INDENT << "/*nb_coerce*/ 0," << endl; - s << INDENT << "/*nb_int*/ 0," << endl; - s << INDENT << "/*nb_long*/ 0," << endl; - s << INDENT << "/*nb_float*/ 0," << endl; - s << INDENT << "/*nb_oct*/ 0," << endl; - s << INDENT << "/*nb_hex*/ 0," << endl; - s << INDENT << "/*nb_inplace_add*/ 0," << endl; - s << INDENT << "/*nb_inplace_subtract*/ 0," << endl; - s << INDENT << "/*nb_inplace_multiply*/ 0," << endl; - s << INDENT << "/*nb_inplace_divide*/ 0," << endl; - s << INDENT << "/*nb_inplace_remainder*/ 0," << endl; - s << INDENT << "/*nb_inplace_power*/ 0," << endl; - s << INDENT << "/*nb_inplace_lshift*/ 0," << endl; - s << INDENT << "/*nb_inplace_rshift*/ 0," << endl; - s << INDENT << "/*nb_inplace_and*/ 0," << endl; - s << INDENT << "/*nb_inplace_xor*/ 0," << endl; - s << INDENT << "/*nb_inplace_or*/ 0," << endl; - s << INDENT << "/*nb_floor_divide*/ 0," << endl; - s << INDENT << "/*nb_true_divide*/ 0," << endl; - s << INDENT << "/*nb_inplace_floor_divide*/ 0," << endl; - s << INDENT << "/*nb_inplace_true_divide*/ 0," << endl; - s << INDENT << "/*nb_index*/ 0" << endl; - s << "};" << endl << endl; -} - -void CppGenerator::writeFlagsDefinition(QTextStream& s, const AbstractMetaEnum* cppEnum) -{ - FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags(); - if (!flagsEntry) - return; - QString cpythonName = cpythonFlagsName(flagsEntry); - QString enumName = cpythonEnumName(cppEnum); - - s << "// forward declaration of new function" << endl; - s << "static PyTypeObject " << cpythonName << "_Type = {" << endl; - s << INDENT << "PyObject_HEAD_INIT(&PyType_Type)" << endl; - s << INDENT << "/*ob_size*/ 0," << endl; - s << INDENT << "/*tp_name*/ \"" << flagsEntry->flagsName() << "\"," << endl; - s << INDENT << "/*tp_basicsize*/ 0," << endl; - s << INDENT << "/*tp_itemsize*/ 0," << endl; - s << INDENT << "/*tp_dealloc*/ 0," << endl; - s << INDENT << "/*tp_print*/ 0," << endl; - s << INDENT << "/*tp_getattr*/ 0," << endl; - s << INDENT << "/*tp_setattr*/ 0," << endl; - s << INDENT << "/*tp_compare*/ 0," << endl; - s << INDENT << "/*tp_repr*/ 0," << endl; - s << INDENT << "/*tp_as_number*/ " << enumName << "_Type.tp_as_number," << endl; - s << INDENT << "/*tp_as_sequence*/ 0," << endl; - s << INDENT << "/*tp_as_mapping*/ 0," << endl; - s << INDENT << "/*tp_hash*/ 0," << endl; - s << INDENT << "/*tp_call*/ 0," << endl; - s << INDENT << "/*tp_str*/ 0," << endl; - s << INDENT << "/*tp_getattro*/ 0," << endl; - s << INDENT << "/*tp_setattro*/ 0," << endl; - s << INDENT << "/*tp_as_buffer*/ 0," << endl; - s << INDENT << "/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES," << endl; - s << INDENT << "/*tp_doc*/ 0," << endl; - s << INDENT << "/*tp_traverse*/ 0," << endl; - s << INDENT << "/*tp_clear*/ 0," << endl; - s << INDENT << "/*tp_richcompare*/ 0," << endl; - s << INDENT << "/*tp_weaklistoffset*/ 0," << endl; - s << INDENT << "/*tp_iter*/ 0," << endl; - s << INDENT << "/*tp_iternext*/ 0," << endl; - s << INDENT << "/*tp_methods*/ 0," << endl; - s << INDENT << "/*tp_members*/ 0," << endl; - s << INDENT << "/*tp_getset*/ 0," << endl; - s << INDENT << "/*tp_base*/ &PyInt_Type," << endl; - s << INDENT << "/*tp_dict*/ 0," << endl; - s << INDENT << "/*tp_descr_get*/ 0," << endl; - s << INDENT << "/*tp_descr_set*/ 0," << endl; - s << INDENT << "/*tp_dictoffset*/ 0," << endl; - s << INDENT << "/*tp_init*/ 0," << endl; - s << INDENT << "/*tp_alloc*/ 0," << endl; - s << INDENT << "/*tp_new*/ PyInt_Type.tp_new," << endl; - s << INDENT << "/*tp_free*/ 0," << endl; - s << INDENT << "/*tp_is_gc*/ 0," << endl; - s << INDENT << "/*tp_bases*/ 0," << endl; - s << INDENT << "/*tp_mro*/ 0," << endl; - s << INDENT << "/*tp_cache*/ 0," << endl; - s << INDENT << "/*tp_subclasses*/ 0," << endl; - s << INDENT << "/*tp_weaklist*/ 0" << endl; - s << "};" << endl << endl; -} - -void CppGenerator::writeFlagsBinaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum, - QString pyOpName, QString cppOpName) -{ - FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags(); - Q_ASSERT(flagsEntry); - - QString converter = "Shiboken::Converter<" + flagsEntry->originalName() + " >::"; - - s << "PyObject* " << cpythonEnumName(cppEnum) << "___" << pyOpName << "__(PyObject* self, PyObject* arg)" << endl; - s << '{' << endl; - - // We need to check the type of self because self and arg can be swapped - s << INDENT << "if (" << converter << "checkType(self) && " << converter << "checkType(arg))" << endl; - s << INDENT << '{' << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_Format(PyExc_TypeError, \"unsupported operand type(s) for %s: '%s' and '%s'\", \"" - << cppOpName << "\", self->ob_type->tp_name, arg->ob_type->tp_name);" << endl; - s << INDENT << "return 0;" << endl; - } - s << INDENT << '}' << endl << endl; - - s << INDENT << "return Shiboken::Converter< " << flagsEntry->originalName() << " >::toPython(" << endl; - { - Indentation indent(INDENT); - s << INDENT << "Shiboken::Converter<" << flagsEntry->originalName() << ">::toCpp(self)" << endl; - s << INDENT << cppOpName << " Shiboken::Converter< "; - s << flagsEntry->originalName() << " >::toCpp(arg)" << endl; - } - s << INDENT << ");" << endl; - s << '}' << endl << endl; -} - -void CppGenerator::writeFlagsUnaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum, - QString pyOpName, QString cppOpName, bool boolResult) -{ - FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags(); - Q_ASSERT(flagsEntry); - - QString converter = "Shiboken::Converter<" + flagsEntry->originalName() + " >::"; - - s << "PyObject* " << cpythonEnumName(cppEnum) << "___" << pyOpName << "__(PyObject* self, PyObject* arg)" << endl; - s << '{' << endl; - s << INDENT << "return Shiboken::Converter< " << (boolResult ? "bool" : flagsEntry->originalName()); - s << " >::toPython(" << endl; - { - Indentation indent(INDENT); - s << INDENT << cppOpName << converter << "toCpp(self)" << endl; - } - s << INDENT << ");" << endl; - s << '}' << endl << endl; -} - -void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* metaClass) -{ - QString pyTypeName = cpythonTypeName(metaClass); - s << "void init_" << metaClass->qualifiedCppName().replace("::", "_") << "(PyObject* module)" << endl; - s << '{' << endl; - s << INDENT << cpythonTypeNameExt(metaClass->typeEntry()) << " = reinterpret_cast(&" << cpythonTypeName(metaClass->typeEntry()) << ");" << endl << endl; - - // class inject-code target/beginning - if (!metaClass->typeEntry()->codeSnips().isEmpty()) { - writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), CodeSnip::Beginning, TypeSystem::TargetLangCode, 0, 0, metaClass); - s << endl; - } - - if (metaClass->baseClass()) - s << INDENT << pyTypeName << ".super.ht_type.tp_base = " << cpythonTypeNameExt(metaClass->baseClass()->typeEntry()) << ';' << endl; - // Multiple inheritance - const AbstractMetaClassList baseClasses = getBaseClasses(metaClass); - if (metaClass->baseClassNames().size() > 1) { - s << INDENT << pyTypeName << ".super.ht_type.tp_bases = PyTuple_Pack("; - s << baseClasses.size(); - s << ',' << endl; - QStringList bases; - foreach (const AbstractMetaClass* base, baseClasses) - bases << "(PyTypeObject*)"+cpythonTypeNameExt(base->typeEntry()); - Indentation indent(INDENT); - s << INDENT << bases.join(", ") << ");" << endl << endl; - } - - // Fill multiple inheritance init function, if needed. - const AbstractMetaClass* miClass = getMultipleInheritingClass(metaClass); - if (miClass && miClass != metaClass) { - s << INDENT << cpythonTypeName(metaClass) << ".mi_init = "; - s << "reinterpret_cast(" + cpythonTypeNameExt(miClass->typeEntry()) + ")->mi_init;" << endl << endl; - } - - // Set typediscovery struct or fill the struct of another one - if (metaClass->isPolymorphic()) { - s << INDENT << "// Fill type discovery information" << endl; - if (metaClass->baseClass()) { - s << INDENT << cpythonTypeName(metaClass) << ".type_discovery = &" << cpythonBaseName(metaClass) << "_typeDiscovery;" << endl; - s << INDENT << "Shiboken::BindingManager& bm = Shiboken::BindingManager::instance();" << endl; - foreach (const AbstractMetaClass* base, baseClasses) { - s << INDENT << "bm.addClassInheritance(reinterpret_cast(" << cpythonTypeNameExt(base->typeEntry()) << "), &" << cpythonTypeName(metaClass) << ");" << endl; - } - } - s << endl; - } - - s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << pyTypeName << ") < 0)" << endl; - s << INDENT << INDENT << "return;" << endl << endl; - - if (metaClass->enclosingClass() && (metaClass->enclosingClass()->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass) ) { - s << INDENT << "PyDict_SetItemString(module," - << "\"" << metaClass->name() << "\", (PyObject*)&" << pyTypeName << ");" << endl; - } else { - s << INDENT << "Py_INCREF(reinterpret_cast(&" << pyTypeName << "));" << endl; - s << INDENT << "PyModule_AddObject(module, \"" << metaClass->name() << "\"," << endl; - Indentation indent(INDENT); - s << INDENT << "((PyObject*)&" << pyTypeName << "));" << endl << endl; - } - - if (!metaClass->enums().isEmpty()) { - s << INDENT << "// Initialize enums" << endl; - s << INDENT << "PyObject* enum_item;" << endl << endl; - } - - foreach (const AbstractMetaEnum* cppEnum, metaClass->enums()) - writeEnumInitialization(s, cppEnum); - - if (metaClass->hasSignals()) - writeSignalInitialization(s, metaClass); - - // Write static fields - foreach (const AbstractMetaField* field, metaClass->fields()) { - if (!field->isStatic()) - continue; - s << INDENT << "PyDict_SetItemString(" + cpythonTypeName(metaClass) + ".super.ht_type.tp_dict, \""; - s << field->name() << "\", "; - writeToPythonConversion(s, field->type(), metaClass, metaClass->qualifiedCppName() + "::" + field->name()); - s << ");" << endl; - } - s << endl; - - // class inject-code target/end - if (!metaClass->typeEntry()->codeSnips().isEmpty()) { - s << endl; - writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), CodeSnip::End, TypeSystem::TargetLangCode, 0, 0, metaClass); - } - - if (!metaClass->isNamespace()) { - bool isObjectType = metaClass->typeEntry()->isObject(); - QString typeName = metaClass->qualifiedCppName(); - if (!isObjectType) - s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver<" << typeName << " >" << "(\"" << typeName << "\");\n"; - - s << INDENT << "Shiboken::TypeResolver::createObjectTypeResolver<" << typeName << " >" << "(\"" << typeName << "*\");\n"; - - QString functionSufix = (isObjectType ? "Object" : "Value"); - s << INDENT << "Shiboken::TypeResolver::create" << functionSufix; - s << "TypeResolver<" << typeName << " >" << "(typeid(" << typeName << ").name());\n"; - if (shouldGenerateCppWrapper(metaClass)) { - s << INDENT << "Shiboken::TypeResolver::create" << functionSufix; - s << "TypeResolver<" << typeName << " >" << "(typeid(" << wrapperName(metaClass) << ").name());\n"; - } - } - - if (usePySideExtensions() && !metaClass->isNamespace()) { - // Qt metatypes are registered only on their first use, so we do this now. - const char* star = metaClass->typeEntry()->isObject() ? "*" : ""; - s << INDENT << "PySide::initQtMetaType<" << metaClass->qualifiedCppName() << star << " >();" << endl; - } - - s << '}' << endl << endl; -} - -void CppGenerator::writeTypeDiscoveryFunction(QTextStream& s, const AbstractMetaClass* metaClass) -{ - QString polymorphicExpr = metaClass->typeEntry()->polymorphicIdValue(); - - s << "static SbkBaseWrapperType* " << cpythonBaseName(metaClass) << "_typeDiscovery(void* cptr, SbkBaseWrapperType* instanceType)\n{" << endl; - - if (!metaClass->baseClass()) { - s << INDENT << "TypeResolver* typeResolver = TypeResolver::get(typeid(*reinterpret_cast<" - << metaClass->qualifiedCppName() << "*>(cptr)).name());" << endl; - s << INDENT << "if (typeResolver)" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return reinterpret_cast(typeResolver->pythonType());" << endl; - } - } else if (!polymorphicExpr.isEmpty()) { - polymorphicExpr = polymorphicExpr.replace("%1", " reinterpret_cast<"+metaClass->qualifiedCppName()+"*>(cptr)"); - s << INDENT << " if (" << polymorphicExpr << ")" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return &" << cpythonTypeName(metaClass) << ';' << endl; - } - } else if (metaClass->isPolymorphic()) { - AbstractMetaClassList ancestors = getAllAncestors(metaClass); - foreach (AbstractMetaClass* ancestor, ancestors) { - if (ancestor->baseClass()) - continue; - if (ancestor->isPolymorphic()) { - s << INDENT << "if (instanceType == reinterpret_cast(Shiboken::SbkType<" - << ancestor->qualifiedCppName() << " >()) && dynamic_cast<" << metaClass->qualifiedCppName() - << "*>(reinterpret_cast<"<< ancestor->qualifiedCppName() << "*>(cptr)))" << endl; - Indentation indent(INDENT); - s << INDENT << "return &" << cpythonTypeName(metaClass) << ';' << endl; - } else { - ReportHandler::warning(metaClass->qualifiedCppName() + " inherits from a non polymorphic type (" - + ancestor->qualifiedCppName() + "), type discovery based on RTTI is " - "impossible, write a polymorphic-id-expresison for this type."); - } - - } - } - s << INDENT << "return 0;" << endl; - s << "}\n\n"; -} - -void CppGenerator::writeSetattroFunction(QTextStream& s, const AbstractMetaClass* metaClass) -{ - s << "static int " << cpythonSetattroFunctionName(metaClass) << "(PyObject* self, PyObject* name, PyObject* value)" << endl; - s << '{' << endl; - if (usePySideExtensions()) { - s << INDENT << "Shiboken::AutoDecRef pp(PySide::qproperty_get_object(self, name));" << endl; - s << INDENT << "if (!pp.isNull())" << endl; - Indentation indent(INDENT); - s << INDENT << INDENT << "return PySide::qproperty_set(pp, self, value);" << endl; - } - s << INDENT << "return PyObject_GenericSetAttr(self, name, value);" << endl; - s << '}' << endl; -} - -void CppGenerator::writeGetattroFunction(QTextStream& s, const AbstractMetaClass* metaClass) -{ - s << "static PyObject* " << cpythonGetattroFunctionName(metaClass) << "(PyObject* self, PyObject* name)" << endl; - s << '{' << endl; - if (classNeedsGetattroFunction(metaClass)) { - s << INDENT << "if (self) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "if (SbkBaseWrapper_instanceDict(self)) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyObject* meth = PyDict_GetItem(SbkBaseWrapper_instanceDict(self), name);" << endl; - s << INDENT << "if (meth) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "Py_INCREF(meth);" << endl; - s << INDENT << "return meth;" << endl; - } - s << INDENT << '}' << endl; - } - s << INDENT << '}' << endl; - s << INDENT << "const char* cname = PyString_AS_STRING(name);" << endl; - foreach (const AbstractMetaFunction* func, getMethodsWithBothStaticAndNonStaticMethods(metaClass)) { - s << INDENT << "if (strcmp(cname, \"" << func->name() << "\") == 0)" << endl; - Indentation indent(INDENT); - s << INDENT << "return PyCFunction_NewEx(&" << cpythonMethodDefinitionName(func) << ", self, 0);" << endl; - } - } - s << INDENT << '}' << endl; - } - s << INDENT << "PyObject* attr = PyObject_GenericGetAttr(self, name);" << endl; - if (usePySideExtensions()) { - s << INDENT << "if (attr && PySide::isQPropertyType(attr)) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyObject *value = PySide::qproperty_get(attr, self);" << endl; - s << INDENT << "Py_DECREF(attr);" << endl; - s << INDENT << "Py_INCREF(value);" << endl; - s << INDENT << "attr = value;" << endl; - } - s << INDENT << "}" << endl; - } - s << INDENT << "return attr;" << endl; - s << '}' << endl; -} - -void CppGenerator::finishGeneration() -{ - //Generate CPython wrapper file - QString classInitDecl; - QTextStream s_classInitDecl(&classInitDecl); - QString classPythonDefines; - QTextStream s_classPythonDefines(&classPythonDefines); - - QSet includes; - QString globalFunctionImpl; - QTextStream s_globalFunctionImpl(&globalFunctionImpl); - QString globalFunctionDecl; - QTextStream s_globalFunctionDef(&globalFunctionDecl); - - Indentation indent(INDENT); - - foreach (AbstractMetaFunctionList globalOverloads, getFunctionGroups().values()) { - AbstractMetaFunctionList overloads; - foreach (AbstractMetaFunction* func, globalOverloads) { - if (!func->isModifiedRemoved()) { - overloads.append(func); - if (func->typeEntry()) - includes << func->typeEntry()->include(); - } - } - - if (overloads.isEmpty()) - continue; - - writeMethodWrapper(s_globalFunctionImpl, overloads); - writeMethodDefinition(s_globalFunctionDef, overloads); - } - - foreach (const AbstractMetaClass* cls, classes()) { - if (!shouldGenerate(cls)) - continue; - - s_classInitDecl << "void init_" << cls->qualifiedCppName().replace("::", "_") << "(PyObject* module);" << endl; - - QString defineStr = "init_" + cls->qualifiedCppName().replace("::", "_"); - - if (cls->enclosingClass() && (cls->enclosingClass()->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass)) - defineStr += "(" + cpythonTypeNameExt(cls->enclosingClass()->typeEntry()) +"->tp_dict);"; - else - defineStr += "(module);"; - s_classPythonDefines << INDENT << defineStr << endl; - } - - QString moduleFileName(outputDirectory() + "/" + subDirectoryForPackage(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 " << endl; - s << "#include " << endl; - s << "#include " << endl; - - s << "#include \"" << getModuleHeaderFileName() << '"' << endl << endl; - foreach (const Include& include, includes) - s << include; - s << endl; - - TypeSystemTypeEntry* moduleEntry = reinterpret_cast(TypeDatabase::instance()->findType(packageName())); - CodeSnipList snips; - if (moduleEntry) - snips = moduleEntry->codeSnips(); - - // module inject-code native/beginning - if (!snips.isEmpty()) { - writeCodeSnips(s, snips, CodeSnip::Beginning, TypeSystem::NativeCode); - s << endl; - } - - s << "// Global functions "; - s << "------------------------------------------------------------" << endl; - s << globalFunctionImpl << endl; - - s << "static PyMethodDef " << moduleName() << "_methods[] = {" << endl; - s << globalFunctionDecl; - s << INDENT << "{0} // Sentinel" << endl << "};" << endl << endl; - - s << "// Classes initialization functions "; - s << "------------------------------------------------------------" << endl; - s << classInitDecl << endl; - - if (!globalEnums().isEmpty()) { - QString converterImpl; - QTextStream convImpl(&converterImpl); - - s << "// Enum definitions "; - s << "------------------------------------------------------------" << endl; - foreach (const AbstractMetaEnum* cppEnum, globalEnums()) { - writeEnumDefinition(s, cppEnum); - s << endl; - } - - if (!converterImpl.isEmpty()) { - s << "// Enum converters "; - s << "------------------------------------------------------------" << endl; - s << "namespace Shiboken" << endl << '{' << endl; - s << converterImpl << endl; - s << "} // namespace Shiboken" << endl << endl; - } - } - - s << "PyTypeObject** " << cppApiVariableName() << ";" << endl << endl;; - foreach (const QString& requiredModule, TypeDatabase::instance()->requiredTargetImports()) - s << "PyTypeObject** " << cppApiVariableName(requiredModule) << ";" << endl << endl;; - - s << "// Module initialization "; - s << "------------------------------------------------------------" << endl; - ExtendedConverterData extendedConverters = getExtendedConverters(); - if (!extendedConverters.isEmpty()) - s << "// Extended Converters" << endl; - foreach (const TypeEntry* externalType, extendedConverters.keys()) { - writeExtendedIsConvertibleFunction(s, externalType, extendedConverters[externalType]); - writeExtendedToCppFunction(s, externalType, extendedConverters[externalType]); - s << endl; - } - s << endl; - - - s << "#if defined _WIN32 || defined __CYGWIN__" << endl; - s << " #define SBK_EXPORT_MODULE __declspec(dllexport)" << endl; - s << "#elif __GNUC__ >= 4" << endl; - s << " #define SBK_EXPORT_MODULE __attribute__ ((visibility(\"default\")))" << endl; - s << "#else" << endl; - s << " #define SBK_EXPORT_MODULE" << endl; - s << "#endif" << endl << endl; - - s << "extern \"C\" SBK_EXPORT_MODULE void init" << moduleName() << "()" << endl; - s << '{' << endl; - - // module inject-code target/beginning - if (!snips.isEmpty()) { - writeCodeSnips(s, snips, CodeSnip::Beginning, TypeSystem::TargetLangCode); - s << endl; - } - - foreach (const QString& requiredModule, TypeDatabase::instance()->requiredTargetImports()) { - s << INDENT << "if (!Shiboken::importModule(\"" << requiredModule << "\", &" << cppApiVariableName(requiredModule) << ")) {" << endl; - s << INDENT << INDENT << "PyErr_SetString(PyExc_ImportError," << "\"could not import "; - s << requiredModule << "\");" << endl << INDENT << INDENT << "return;" << endl; - s << INDENT << "}" << endl << endl; - } - - s << INDENT << "Shiboken::initShiboken();" << endl; - s << INDENT << "PyObject* module = Py_InitModule(\"" << moduleName() << "\", "; - s << moduleName() << "_methods);" << endl << endl; - - s << INDENT << "// Create a CObject containing the API pointer array's address" << endl; - s << INDENT << "static PyTypeObject* cppApi[" << "SBK_" << moduleName() << "_IDX_COUNT" << "];" << endl; - s << INDENT << cppApiVariableName() << " = cppApi;" << endl; - s << INDENT << "PyObject* cppApiObject = PyCObject_FromVoidPtr(reinterpret_cast(cppApi), 0);" << endl; - s << INDENT << "PyModule_AddObject(module, \"_Cpp_Api\", cppApiObject);" << endl << endl; - s << INDENT << "// Initialize classes in the type system" << endl; - s << classPythonDefines; - - if (!extendedConverters.isEmpty()) { - s << INDENT << "// Initialize extended Converters" << endl; - s << INDENT << "Shiboken::SbkBaseWrapperType* shiboType;" << endl << endl; - } - foreach (const TypeEntry* externalType, extendedConverters.keys()) { - writeExtendedConverterInitialization(s, externalType, extendedConverters[externalType]); - s << endl; - } - s << endl; - - if (!globalEnums().isEmpty()) { - s << INDENT << "// Initialize enums" << endl; - s << INDENT << "PyObject* enum_item;" << endl << endl; - } - - foreach (const AbstractMetaEnum* cppEnum, globalEnums()) - writeEnumInitialization(s, cppEnum); - - // Register primitive types on TypeResolver - s << INDENT << "// Register primitive types on TypeResolver" << endl; - foreach(const PrimitiveTypeEntry* pte, primitiveTypes()) { - if (pte->generateCode()) - s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver<" << pte->name() << " >(\"" << pte->name() << "\");" << endl; - } - // Register type resolver for all containers found in signals. - QSet typeResolvers; - foreach (AbstractMetaClass* metaClass, classes()) { - if (!metaClass->isQObject() || !metaClass->typeEntry()->generateCode()) - continue; - foreach (AbstractMetaFunction* func, metaClass->functions()) { - if (func->isSignal()) { - foreach (AbstractMetaArgument* arg, func->arguments()) { - if (arg->type()->isContainer()) { - QString value = translateType(arg->type(), metaClass); - typeResolvers << QMetaObject::normalizedType(value.toAscii().constData()); - } - } - } - } - } - foreach (QString type, typeResolvers) - s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver<" << type << " >(\"" << type << "\");" << endl; - - s << endl << INDENT << "if (PyErr_Occurred()) {" << endl; - { - Indentation indentation(INDENT); - s << INDENT << "PyErr_Print();" << endl; - s << INDENT << "Py_FatalError(\"can't initialize module " << moduleName() << "\");" << endl; - } - s << INDENT << '}' << endl; - - // module inject-code target/end - if (!snips.isEmpty()) { - writeCodeSnips(s, snips, CodeSnip::End, TypeSystem::TargetLangCode); - s << endl; - } - - s << '}' << endl << endl; - - // module inject-code native/end - if (!snips.isEmpty()) { - writeCodeSnips(s, snips, CodeSnip::End, TypeSystem::NativeCode); - s << endl; - } - } -} - -bool CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, int argIndex, bool useHeuristicPolicy) -{ - const int numArgs = func->arguments().count(); - const AbstractMetaClass* cppClass = func->ownerClass(); - const AbstractMetaClass* dClass = func->declaringClass(); - bool ctorHeuristicEnabled = func->isConstructor() && useCtorHeuristic() && useHeuristicPolicy; - - QString parentVariable; - QString childVariable; - ArgumentOwner argOwner = func->argumentOwner(cppClass, argIndex); - - if (argOwner.index == -2) //invalid - argOwner = func->argumentOwner(dClass, argIndex); - - bool usePyArgs = OverloadData(getFunctionGroups(func->implementingClass())[func->name()], this).maxArgs() > 1; - - ArgumentOwner::Action action = argOwner.action; - int parentIndex = argOwner.index; - int childIndex = argIndex; - if (ctorHeuristicEnabled && argIndex > 0 && numArgs) { - AbstractMetaArgument* arg = func->arguments().at(argIndex-1); - if (arg->name() == "parent" && (arg->type()->isObject() || arg->type()->isQObject())) { - action = ArgumentOwner::Add; - parentIndex = argIndex; - childIndex = -1; - } - } - - if (action != ArgumentOwner::Invalid) { - if (!usePyArgs && argIndex > 1) - ReportHandler::warning("Argument index for parent tag out of bounds: "+func->signature()); - - if (action == ArgumentOwner::Remove) { - parentVariable = "Py_None"; - } else { - if (parentIndex == 0) - parentVariable = PYTHON_RETURN_VAR; - else if (parentIndex == -1) - parentVariable = "self"; - else - parentVariable = usePyArgs ? "pyargs["+QString::number(parentIndex-1)+"]" : "arg"; - } - - if (childIndex == 0) - childVariable = PYTHON_RETURN_VAR; - else if (childIndex == -1) - childVariable = "self"; - else - childVariable = usePyArgs ? "pyargs["+QString::number(childIndex-1)+"]" : "arg"; - - s << INDENT << "Shiboken::setParent(" << parentVariable << ", " << childVariable << ");\n"; - - return true; - } - - if (argIndex == 0 && useHeuristicPolicy) - writeReturnValueHeuristics(s, func); - - return false; -} - -void CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, bool useHeuristicForReturn) -{ - const int numArgs = func->arguments().count(); - - // -1 = return value - // 0 = self - // 1..n = func. args. - for (int i = -1; i <= numArgs; ++i) - writeParentChildManagement(s, func, i, i == 0 ? useHeuristicForReturn : true); -} - -void CppGenerator::writeReturnValueHeuristics(QTextStream& s, const AbstractMetaFunction* func, const QString& self) -{ - AbstractMetaType *type = func->type(); - if (!useReturnValueHeuristic() - || !func->ownerClass() - || !type - || func->isStatic() - || !func->typeReplaced(0).isEmpty()) { - return; - } - - if (type->isQObject() || type->isObject() || type->isValuePointer()) - s << INDENT << "Shiboken::setParent(" << self << ", " PYTHON_RETURN_VAR ");" << endl; -} - -void CppGenerator::writeHashFunction(QTextStream& s, const AbstractMetaClass* metaClass) -{ - s << "static long " << cpythonBaseName(metaClass) << "_HashFunc(PyObject* obj)"; - s << '{' << endl; - s << INDENT << "return " << metaClass->typeEntry()->hashFunction() << '('; - writeToCppConversion(s, metaClass, "obj"); - s << ");" << endl; - s << '}' << endl << endl; -} - -void CppGenerator::writeObjCopierFunction(QTextStream& s, const AbstractMetaClass* metaClass) -{ - if (!(metaClass->typeEntry()->isValue() && shouldGenerateCppWrapper(metaClass))) - return; - s << "static void* " << cpythonBaseName(metaClass) << "_ObjCopierFunc(const void* ptr)"; - s << '{' << endl; - s << INDENT << "return new " << wrapperName(metaClass) << "(*reinterpret_castqualifiedCppName() << "*>(ptr));\n"; - s << '}' << endl << endl; - -} - -void CppGenerator::writeStdListWrapperMethods(QTextStream& s, const AbstractMetaClass* metaClass) -{ - //len - s << "Py_ssize_t " << cpythonBaseName(metaClass->typeEntry()) << "__len__" << "(PyObject* self)" << endl << '{' << endl; - s << INDENT << "if (Shiboken::cppObjectIsInvalid(self))" << endl; - s << INDENT << INDENT << "return 0;" << endl << endl; - s << INDENT << metaClass->qualifiedCppName() << " &cppSelf = Shiboken::Converter<" << metaClass->qualifiedCppName() <<"& >::toCpp(self);" << endl; - s << INDENT << "return cppSelf.size();" << endl; - s << "}" << endl; - - //getitem - s << "PyObject* " << cpythonBaseName(metaClass->typeEntry()) << "__getitem__" << "(PyObject* self, Py_ssize_t _i)" << endl << '{' << endl; - s << INDENT << "if (Shiboken::cppObjectIsInvalid(self))" << endl; - s << INDENT << INDENT << "return 0;" << endl << endl; - s << INDENT << metaClass->qualifiedCppName() << " &cppSelf = Shiboken::Converter<" << metaClass->qualifiedCppName() <<"& >::toCpp(self);" << endl; - s << INDENT << "if (_i < 0 || _i >= (Py_ssize_t) cppSelf.size()) {" << endl; - s << INDENT << INDENT << "PyErr_SetString(PyExc_IndexError, \"index out of bounds\");" << endl; - s << INDENT << INDENT << "return 0;" << endl << INDENT << "}" << endl; - s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = cppSelf.begin();" << endl; - s << INDENT << "for(Py_ssize_t pos=0; pos < _i; pos++) _item++;" << endl; - s << INDENT << "return Shiboken::Converter<" << metaClass->qualifiedCppName() << "::value_type>::toPython(*_item);" << endl; - s << "}" << endl; - - //setitem - s << "int " << cpythonBaseName(metaClass->typeEntry()) << "__setitem__" << "(PyObject* self, Py_ssize_t _i, PyObject* _value)" << endl << '{' << endl; - s << INDENT << "if (Shiboken::cppObjectIsInvalid(self))" << endl; - s << INDENT << INDENT << "return -1;" << endl; - s << INDENT << metaClass->qualifiedCppName() << " &cppSelf = Shiboken::Converter<" << metaClass->qualifiedCppName() <<"& >::toCpp(self);" << endl; - s << INDENT << "if (_i < 0 || _i >= (Py_ssize_t) cppSelf.size()) {" << endl; - s << INDENT << INDENT << "PyErr_SetString(PyExc_IndexError, \"list assignment index out of range\");" << endl; - s << INDENT << INDENT << "return -1;" << endl << INDENT << "}" << endl; - s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = cppSelf.begin();" << endl; - s << INDENT << "for(Py_ssize_t pos=0; pos < _i; pos++) _item++;" << endl; - - s << INDENT << metaClass->qualifiedCppName() << "::value_type cppValue = Shiboken::Converter<" << metaClass->qualifiedCppName() << "::value_type>::toCpp(_value);" << endl; - s << INDENT << "*_item = cppValue;" << endl; - s << INDENT << "return 0;"; - s << endl << "}" << endl; -} - - diff --git a/cppgenerator.h b/cppgenerator.h deleted file mode 100644 index 7ce84935..00000000 --- a/cppgenerator.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * This file is part of the Shiboken Python Bindings Generator project. - * - * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: PySide team - * - * 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 "shibokengenerator.h" -#include "overloaddata.h" - -/** - * The CppGenerator generate the implementations of C++ bindings classes. - */ -class CppGenerator : public ShibokenGenerator -{ -public: - CppGenerator(); -protected: - QString fileNameForClass(const AbstractMetaClass* metaClass) const; - QList filterGroupedOperatorFunctions(const AbstractMetaClass* metaClass, - uint query); - void generateClass(QTextStream& s, const AbstractMetaClass* metaClass); - void finishGeneration(); - -private: - void writeConstructorNative(QTextStream& s, const AbstractMetaFunction* func); - void writeDestructorNative(QTextStream& s, const AbstractMetaClass* metaClass); - void writeVirtualMethodNative(QTextStream& s, const AbstractMetaFunction* func); - void writeMetaObjectMethod(QTextStream& s, const AbstractMetaClass* metaClass); - - void writeConstructorWrapper(QTextStream &s, const AbstractMetaFunctionList overloads); - void writeDestructorWrapper(QTextStream& s, const AbstractMetaClass* metaClass); - void writeMinimalConstructorCallArguments(QTextStream& s, const AbstractMetaClass* metaClass); - void writeMinimalConstructorCallArguments(QTextStream& s, const AbstractMetaType* type); - void writeMethodWrapper(QTextStream &s, const AbstractMetaFunctionList overloads); - void writeArgumentsInitializer(QTextStream& s, OverloadData& overloadData); - void writeNamedArgumentsCheck(QTextStream& s, OverloadData& overloadData); - void writeCppSelfDefinition(QTextStream& s, const AbstractMetaFunction* func); - - void writeErrorSection(QTextStream& s, OverloadData& overloadData); - /** - * Writes the check section for the validity of wrapped C++ objects. - * \param s text stream to write - * \param argName Python argument name - * \param type the TypeEntry passed when the validity check must confirm the type of the Python wrapper to be checked - */ - void writeInvalidCppObjectCheck(QTextStream& s, QString pyArgName = "self", const TypeEntry* type = 0); - void writeTypeCheck(QTextStream& s, const AbstractMetaType* argType, QString argumentName, bool isNumber = false, QString customType = ""); - void writeTypeCheck(QTextStream& s, const OverloadData* overloadData, QString argumentName); - - void writeTypeDiscoveryFunction(QTextStream& s, const AbstractMetaClass* metaClass); - - void writeSetattroFunction(QTextStream& s, const AbstractMetaClass* metaClass); - void writeGetattroFunction(QTextStream& s, const AbstractMetaClass* metaClass); - - /** - * Writes Python to C++ conversions for arguments on Python wrappers. - * If implicit conversions, and thus new object allocation, are needed, - * code to deallocate a possible new instance is also generated. - * \param s text stream to write - * \param argType a pointer to the argument type to be converted - * \param argName C++ argument name - * \param pyArgName Python argument name - * \param context the current meta class - * \param defaultValue an optional default value to be used instead of the conversion result - */ - void writeArgumentConversion(QTextStream& s, const AbstractMetaType* argType, - QString argName, QString pyArgName, - const AbstractMetaClass* context = 0, - QString defaultValue = QString()); - /// Convenience method to call writeArgumentConversion with an AbstractMetaArgument instead of an AbstractMetaType. - void writeArgumentConversion(QTextStream& s, const AbstractMetaArgument* arg, - QString argName, QString pyArgName, - const AbstractMetaClass* context = 0, - QString defaultValue = QString()) - { - writeArgumentConversion(s, arg->type(), argName, pyArgName, context, defaultValue); - } - - /** - * Set the Python method wrapper return value variable to Py_None if - * there are return types different from void in any of the other overloads - * for the function passed as parameter. - * \param s text stream to write - * \param func a pointer to the function that will possibly return Py_None - * \param thereIsReturnValue indicates if the return type of any of the other overloads - * for this function is different from 'void' - */ - void writeNoneReturn(QTextStream& s, const AbstractMetaFunction* func, bool thereIsReturnValue); - - /** - * Writes the Python function wrapper overload decisor that selects which C++ - * method/function to call with the received Python arguments. - * \param s text stream to write - * \param overloadData the overload data describing all the possible overloads for the function/method - */ - void writeOverloadedFunctionDecisor(QTextStream& s, const OverloadData& overloadData); - /// Recursive auxiliar method to the other writeOverloadedFunctionDecisor. - void writeOverloadedFunctionDecisorEngine(QTextStream& s, const OverloadData* parentOverloadData); - - /// Writes calls to all the possible method/function overloads. - void writeFunctionCalls(QTextStream& s, const OverloadData& overloadData); - - /// Writes the call to a single function usually from a collection of overloads. - void writeSingleFunctionCall(QTextStream& s, const OverloadData& overloadData, const AbstractMetaFunction* func = 0); - void writeNamedArgumentResolution(QTextStream& s, const AbstractMetaFunction* func, bool usePyArgs); - - /// Returns a string containing the name of an argument for the given function and argument index. - QString argumentNameFromIndex(const AbstractMetaFunction* func, int argIndex, const AbstractMetaClass** wrappedClass); - void writeMethodCall(QTextStream& s, const AbstractMetaFunction* func, int maxArgs = 0); - - void writeClassRegister(QTextStream& s, const AbstractMetaClass* metaClass); - void writeClassDefinition(QTextStream& s, const AbstractMetaClass* metaClass); - void writeMethodDefinitionEntry(QTextStream& s, const AbstractMetaFunctionList overloads); - void writeMethodDefinition(QTextStream& s, const AbstractMetaFunctionList overloads); - /// Writes the implementation of all methods part of python sequence protocol - void writeSequenceMethods(QTextStream& s, const AbstractMetaClass* metaClass); - /// Writes the struct PySequenceMethods for types thats supports the python sequence protocol - void writeTypeAsSequenceDefinition(QTextStream& s, const AbstractMetaClass* metaClass); - void writeTypeAsNumberDefinition(QTextStream& s, const AbstractMetaClass* metaClass); - - void writeGetterFunction(QTextStream& s, const AbstractMetaField* metaField); - void writeSetterFunction(QTextStream& s, const AbstractMetaField* metaField); - - void writeRichCompareFunction(QTextStream& s, const AbstractMetaClass* metaClass); - - void writeEnumNewMethod(QTextStream& s, const AbstractMetaEnum* cppEnum); - void writeEnumDefinition(QTextStream& s, const AbstractMetaEnum* metaEnum); - void writeEnumInitialization(QTextStream& s, const AbstractMetaEnum* metaEnum); - - void writeSignalInitialization(QTextStream& s, const AbstractMetaClass* metaClass); - - void writeFlagsDefinition(QTextStream& s, const AbstractMetaEnum* cppEnum); - void writeFlagsMethods(QTextStream& s, const AbstractMetaEnum* cppEnum); - void writeFlagsNumberMethodsDefinition(QTextStream& s, const AbstractMetaEnum* cppEnum); - void writeFlagsBinaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum, - QString pyOpName, QString cppOpName); - void writeFlagsUnaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum, - QString pyOpName, QString cppOpName, bool boolResult = false); - - /// Writes the function that registers the multiple inheritance information for the classes that need it. - void writeMultipleInheritanceInitializerFunction(QTextStream& s, const AbstractMetaClass* metaClass); - /// Writes the implementation of special cast functions, used when we need to cast a class with mulltiple inheritance. - void writeSpecialCastFunction(QTextStream& s, const AbstractMetaClass* metaClass); - - void writeExtendedIsConvertibleFunction(QTextStream& s, const TypeEntry* externalType, const QList& conversions); - void writeExtendedToCppFunction(QTextStream& s, const TypeEntry* externalType, const QList& conversions); - void writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, const QList& conversions); - - void writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, bool userHeuristicForReturn); - bool writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, int argIndex, bool userHeuristicPolicy); - void writeReturnValueHeuristics(QTextStream& s, const AbstractMetaFunction* func, const QString& self = "self"); - /** - * Returns the multiple inheritance initializer function for the given class. - * \param metaClass the class for whom the function name must be generated. - * \return name of the multiple inheritance information initializer function or - * an empty string if there is no multiple inheritance in its ancestry. - */ - QString multipleInheritanceInitializerFunctionName(const AbstractMetaClass* metaClass); - - /// Returns a list of all classes to which the given class could be casted. - QStringList getAncestorMultipleInheritance(const AbstractMetaClass* metaClass); - - /// Returns true if the given class supports the python sequence protocol - bool supportsSequenceProtocol(const AbstractMetaClass* metaClass); - - /// Returns true if generator should produce getters and setters for the given class. - bool shouldGenerateGetSetList(const AbstractMetaClass* metaClass); - - /// Returns true if the Python wrapper for the received OverloadData must accept a list of arguments. - static bool pythonFunctionWrapperUsesListOfArguments(const OverloadData& overloadData); - - void writeHashFunction(QTextStream& s, const AbstractMetaClass* metaClass); - void writeObjCopierFunction(QTextStream& s, const AbstractMetaClass* metaClass); - - // Write default implementations for sequence protocol - void writeStdListWrapperMethods(QTextStream& s, const AbstractMetaClass* metaClass); - - // Maps special function names to function parameters and return types - // used by CPython API in the sequence protocol. - QHash > m_sequenceProtocol; - int m_currentErrorCode; -}; - -#endif // CPPGENERATOR_H - diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt index 85c9d6a9..c40d5525 100644 --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -1,5 +1,17 @@ +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + set(LIBRARY_OUTPUT_SUFFIX ${CMAKE_DEBUG_POSTFIX}) +else() + set(LIBRARY_OUTPUT_SUFFIX ${CMAKE_RELEASE_POSTFIX}) +endif() + +add_custom_target(data) +add_dependencies(data shiboken) +get_target_property(SHIBOKEN_GENERATOR shiboken OUTPUT_NAME) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ShibokenConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/ShibokenConfig.cmake" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ShibokenConfig-spec.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/ShibokenConfig${PYTHON_SUFFIX}.cmake" @ONLY) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ShibokenConfigVersion.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/ShibokenConfigVersion.cmake" @ONLY) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/shiboken.pc.in" @@ -7,6 +19,8 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/shiboken.pc.in" install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ShibokenConfig.cmake" DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken-${shiboken_VERSION}") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ShibokenConfig${PYTHON_SUFFIX}.cmake" + DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken-${shiboken_VERSION}") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ShibokenConfigVersion.cmake" DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken-${shiboken_VERSION}") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/shiboken${shiboken_SUFFIX}.pc" diff --git a/data/ShibokenConfig-spec.cmake.in b/data/ShibokenConfig-spec.cmake.in new file mode 100644 index 00000000..e1358b64 --- /dev/null +++ b/data/ShibokenConfig-spec.cmake.in @@ -0,0 +1,26 @@ +# SHIBOKEN_INCLUDE_DIR - Directories to include to use SHIBOKEN +# SHIBOKEN_LIBRARY - Files to link against to use SHIBOKEN +# SHIBOKEN_BINARY - Executable name +# SHIBOKEN_BUILD_TYPE - Tells if Shiboken was compiled in Release or Debug mode. +# SHIBOKEN_PYTHON_INTERPRETER - Python interpreter (regular or debug) to be used with the bindings. +# SHIBOKEN_PYTHON_LIBRARIES - Python libraries (regular or debug) Shiboken is linked against. + +SET(SHIBOKEN_INCLUDE_DIR "@CMAKE_INSTALL_PREFIX@/include/shiboken@shiboken_SUFFIX@") +if(MSVC) + SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@@PYTHON_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@.lib") +elseif(CYGWIN) + SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_IMPORT_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@@PYTHON_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_IMPORT_LIBRARY_SUFFIX@") +elseif(WIN32) + SET(SHIBOKEN_LIBRARY "@CMAKE_INSTALL_PREFIX@/bin/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@@PYTHON_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") +else() + SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@@PYTHON_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") +endif() +SET(SHIBOKEN_PYTHON_INCLUDE_DIR "@SBK_PYTHON_INCLUDE_DIR@") +SET(SHIBOKEN_PYTHON_INCLUDE_DIR "@SBK_PYTHON_INCLUDE_DIR@") +SET(SHIBOKEN_PYTHON_INTERPRETER "@PYTHON_EXECUTABLE@") +SET(SHIBOKEN_PYTHON_LIBRARIES "@SBK_PYTHON_LIBRARIES@") +SET(SHIBOKEN_PYTHON_SUFFIX "@PYTHON_SUFFIX@") +message(STATUS "libshiboken built for @SHIBOKEN_BUILD_TYPE@") +@SBK_ADD_PY_DEBUG_DEFINITION@ + +set(SHIBOKEN_BINARY "@CMAKE_INSTALL_PREFIX@/bin/@SHIBOKEN_GENERATOR@") diff --git a/data/ShibokenConfig.cmake.in b/data/ShibokenConfig.cmake.in index 148c35b9..7d8bc863 100644 --- a/data/ShibokenConfig.cmake.in +++ b/data/ShibokenConfig.cmake.in @@ -1,11 +1,5 @@ -# SHIBOKEN_INCLUDE_DIR - Directories to include to use SHIBOKEN -# SHIBOKEN_LIBRARIES - Files to link against to use SHIBOKEN - -SET(SHIBOKEN_INCLUDE_DIR "@CMAKE_INSTALL_PREFIX@/include/shiboken@shiboken_SUFFIX@") -if(MSVC) - SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@.lib") -elseif(WIN32) - SET(SHIBOKEN_LIBRARY "@CMAKE_INSTALL_PREFIX@/bin/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") -else() - SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") +if (NOT PYTHON_SUFFIX) + message(STATUS "Using default python: @PYTHON_SUFFIX@") + SET(PYTHON_SUFFIX @PYTHON_SUFFIX@) endif() +include(@LIB_INSTALL_DIR@/cmake/Shiboken-@shiboken_VERSION@/ShibokenConfig${PYTHON_SUFFIX}.cmake) diff --git a/data/ShibokenConfigVersion.cmake.in b/data/ShibokenConfigVersion.cmake.in index 89d84fc1..b2658a96 100644 --- a/data/ShibokenConfigVersion.cmake.in +++ b/data/ShibokenConfigVersion.cmake.in @@ -1,9 +1,10 @@ set(PACKAGE_VERSION @shiboken_VERSION@) -if("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL @shiboken_MAJOR_VERSION@) - if("${PACKAGE_FIND_VERSION_MINOR}" EQUAL @shiboken_MINOR_VERSION@) - set(PACKAGE_VERSION_COMPATIBLE 1) - if("${PACKAGE_FIND_VERSION_PATCH}" EQUAL @shiboken_MICRO_VERSION@) - set(PACKAGE_VERSION_EXACT 1) - endif() - endif() -endif() + +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") +endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) diff --git a/data/shiboken.pc.in b/data/shiboken.pc.in index ed1cc6c8..155a3d9e 100644 --- a/data/shiboken.pc.in +++ b/data/shiboken.pc.in @@ -2,11 +2,13 @@ prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_PREFIX@ libdir=@LIB_INSTALL_DIR@ includedir=@CMAKE_INSTALL_PREFIX@/include/shiboken -generator_location=@CMAKE_INSTALL_PREFIX@/bin/shiboken +generator_location=@CMAKE_INSTALL_PREFIX@/bin/@SHIBOKEN_GENERATOR@ +python_interpreter=@PYTHON_EXECUTABLE@ +python_include_dir=@SBK_PYTHON_INCLUDE_DIR@ Name: shiboken Description: Support library for Python bindings created with Shiboken generator. Version: @shiboken_VERSION@ -Libs: -L${libdir} -lpython -lshiboken${shiboken_SUFFIX} -Cflags: -I${includedir}/shiboken${shiboken_SUFFIX} +Libs: @SBK_PYTHON_LIBRARIES@ -L${libdir} -lshiboken@shiboken_SUFFIX@@PYTHON_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@ +Cflags: -I@SBK_PYTHON_INCLUDE_DIR@ -I${includedir}/@shiboken_SUFFIX@@SBK_PKG_CONFIG_PY_DEBUG_DEFINITION@ diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 00000000..57c8fa75 --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,15 @@ + +find_program(SPHINX sphinx-build DOC "Path to sphinx-build binary.") + +if (SPHINX) + message("-- sphinx-build - found") + configure_file(conf.py.in conf.py @ONLY) + add_custom_target(doc ${SPHINX} -b html -c . ${CMAKE_CURRENT_SOURCE_DIR} html ) +else() + message("-- sphinx-build - not found! doc target disabled") +endif() + +if (NOT win32) + file(GLOB manpages "${CMAKE_CURRENT_SOURCE_DIR}/*.1") + install(FILES ${manpages} DESTINATION share/man/man1) +endif() diff --git a/doc/Makefile b/doc/Makefile deleted file mode 100644 index 69b857c5..00000000 --- a/doc/Makefile +++ /dev/null @@ -1,88 +0,0 @@ -# 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 ' where 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/PyQtB.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile _build/qthelp/PyQtB.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/_templates/index.html b/doc/_templates/index.html index 47d4914c..00ac6427 100644 --- a/doc/_templates/index.html +++ b/doc/_templates/index.html @@ -13,12 +13,12 @@

Documentation

for a complete overview

- +

Documentation

support for python sequence protocol

- + diff --git a/doc/_templates/layout.html b/doc/_templates/layout.html new file mode 100644 index 00000000..b07c9f7d --- /dev/null +++ b/doc/_templates/layout.html @@ -0,0 +1,31 @@ +{% extends "!layout.html" %} + +# Invert sidebars +{%- block sidebar1 %}{{ sidebar() }}{%- endblock %} +{%- block sidebar2 %}{%- endblock %} + +{%- block header %} +
+
+
+ + {{ relbar() }} +
+
+{%- endblock -%} + +{%- block footer %} + +
+{%- endblock %} + +# No top relbar. +{%- block relbar1 %}{%- endblock %} + +# No bottom relbar. +{%- block relbar2 %}{%- endblock %} diff --git a/doc/_themes/pysidedocs/defindex.html b/doc/_themes/pysidedocs/defindex.html deleted file mode 100644 index 40f4f4c9..00000000 --- a/doc/_themes/pysidedocs/defindex.html +++ /dev/null @@ -1,26 +0,0 @@ -{% extends "layout.html" %} -{% set title = _('Overview') %} -{% block body %} -

{{ docstitle|e }}

-

- Welcome! This is - {% block description %}the documentation for {{ project|e }} - {{ release|e }}{% if last_updated %}, last updated {{ last_updated|e }}{% endif %}{% endblock %}. -

- {% block tables %} -

{{ _('Indices and tables:') }}

- - -
- - - - - -
- {% endblock %} -{% endblock %} diff --git a/doc/_themes/pysidedocs/genindex-single.html b/doc/_themes/pysidedocs/genindex-single.html deleted file mode 100644 index 9aaaeb0c..00000000 --- a/doc/_themes/pysidedocs/genindex-single.html +++ /dev/null @@ -1,46 +0,0 @@ -{% extends "layout.html" %} -{% set title = _('Index') %} -{% block body %} - -

{% trans key=key %}Index – {{ key }}{% endtrans %}

- -
-
-{%- set breakat = count // 2 %} -{%- set numcols = 1 %} -{%- set numitems = 0 %} -{% for entryname, (links, subitems) in entries %} -
{%- if links -%}{{ entryname|e }} - {%- for link in links[1:] %}, [{{ loop.index }}]{% endfor -%} - {%- else -%} -{{ entryname|e }} - {%- endif -%}
- {%- if subitems %} -
- {%- for subentryname, subentrylinks in subitems %} -
{{ subentryname|e }} - {%- for link in subentrylinks[1:] %}, [{{ loop.index }}]{% endfor -%} -
- {%- endfor %} -
- {%- endif -%} -{%- set numitems = numitems + 1 + (subitems|length) -%} -{%- if numcols < 2 and numitems > breakat -%} -{%- set numcols = numcols+1 -%} -
-{%- endif -%} -{%- endfor %} -
- -{% endblock %} - -{% block sidebarrel %} -

Index

-

{% for key, dummy in genindexentries -%} - {{ key }} - {% if not loop.last %}| {% endif %} - {%- endfor %}

- -

{{ _('Full index on one page') }}

- {{ super() }} -{% endblock %} diff --git a/doc/_themes/pysidedocs/genindex-split.html b/doc/_themes/pysidedocs/genindex-split.html deleted file mode 100644 index ab099e5b..00000000 --- a/doc/_themes/pysidedocs/genindex-split.html +++ /dev/null @@ -1,30 +0,0 @@ -{% extends "layout.html" %} -{% set title = _('Index') %} -{% block body %} - -

{{ _('Index') }}

- -

{{ _('Index pages by letter') }}:

- -

{% for key, dummy in genindexentries -%} - {{ key }} - {% if not loop.last %}| {% endif %} - {%- endfor %}

- -

{{ _('Full index on one page') }} - ({{ _('can be huge') }})

- -{% endblock %} - -{% block sidebarrel %} -{% if split_index %} -

Index

-

{% for key, dummy in genindexentries -%} - {{ key }} - {% if not loop.last %}| {% endif %} - {%- endfor %}

- -

{{ _('Full index on one page') }}

-{% endif %} - {{ super() }} -{% endblock %} diff --git a/doc/_themes/pysidedocs/genindex.html b/doc/_themes/pysidedocs/genindex.html deleted file mode 100644 index a19aa80f..00000000 --- a/doc/_themes/pysidedocs/genindex.html +++ /dev/null @@ -1,57 +0,0 @@ -{% extends "layout.html" %} -{% set title = _('Index') %} -{% block body %} - -

{{ _('Index') }}

- - {% for key, dummy in genindexentries -%} - {{ key }} {% if not loop.last %}| {% endif %} - {%- endfor %} - -
- - {% for key, entries in genindexentries %} -

{{ key }}

-
-
-{%- set breakat = genindexcounts[loop.index0] // 2 %} -{%- set numcols = 1 %} -{%- set numitems = 0 %} -{% for entryname, (links, subitems) in entries %} -
{%- if links -%}{{ entryname|e }} - {%- for link in links[1:] %}, [{{ loop.index }}]{% endfor -%} - {%- else -%} -{{ entryname|e }} - {%- endif -%}
- {%- if subitems %} -
- {%- for subentryname, subentrylinks in subitems %} -
{{ subentryname|e }} - {%- for link in subentrylinks[1:] %}, [{{ loop.index }}]{% endfor -%} -
- {%- endfor %} -
- {%- endif -%} -{%- set numitems = numitems + 1 + (subitems|length) -%} -{%- if numcols < 2 and numitems > breakat -%} -{%- set numcols = numcols+1 -%} -
-{%- endif -%} -{%- endfor %} -
-{% endfor %} - -{% endblock %} - -{% block sidebarrel %} -{% if split_index %} -

{{ _('Index') }}

-

{% for key, dummy in genindexentries -%} - {{ key }} - {% if not loop.last %}| {% endif %} - {%- endfor %}

- -

{{ _('Full index on one page') }}

-{% endif %} - {{ super() }} -{% endblock %} diff --git a/doc/_themes/pysidedocs/layout.html b/doc/_themes/pysidedocs/layout.html deleted file mode 100644 index eb574310..00000000 --- a/doc/_themes/pysidedocs/layout.html +++ /dev/null @@ -1,147 +0,0 @@ -{%- block doctype -%} - -{%- endblock %} -{%- set reldelim1 = reldelim1 is not defined and ' »' or reldelim1 %} -{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %} - - - - - {{ metatags }} - {{ project }} — {{ title }} - - - - {%- if not embedded %} - - {%- for scriptfile in script_files %} - - {%- endfor %} - {%- if pagename == "screenshots" %} - {%- endif %} - - - {%- if use_opensearch %} - - {%- endif %} - {%- if favicon %} - - {%- endif %} - {%- endif %} -{%- block linktags %} - {%- if hasdoc('about') %} - - {%- endif %} - {%- if hasdoc('genindex') %} - - {%- endif %} - {%- if hasdoc('search') %} - - {%- endif %} - {%- if hasdoc('copyright') %} - - {%- endif %} - - {%- if parents %} - - {%- endif %} - {%- if next %} - - {%- endif %} - {%- if prev %} - - {%- endif %} -{%- endblock %} -{%- block extrahead %} {% endblock %} - - -{%- block header %}{% endblock %} - -
- - -
- - - {%- block document %} - {% block body %} {% endblock %} - {%- endblock %} -
- -{%- block footer %} - -{%- endblock %} -
- - diff --git a/doc/_themes/pysidedocs/modindex.html b/doc/_themes/pysidedocs/modindex.html deleted file mode 100644 index 0392edc8..00000000 --- a/doc/_themes/pysidedocs/modindex.html +++ /dev/null @@ -1,42 +0,0 @@ -{% extends "layout.html" %} -{% set title = _('Global Module Index') %} -{% block extrahead %} -{{ super() }} -{% if not embedded and collapse_modindex %} - -{% endif %} -{% endblock %} -{% block body %} - -

{{ _('Global Module Index') }}

- - {%- for letter in letters %} - {{ letter }} {% if not loop.last %}| {% endif %} - {%- endfor %} -
- - - {%- for modname, collapse, cgroup, indent, fname, synops, pform, dep, stripped in modindexentries %} - {%- if not modname -%} - - - {%- else -%} - - - - {%- endif -%} - {% endfor %} -
 
{{ fname }}
{% if collapse -%} - - {%- endif %}{% if indent %}   {% endif %} - {% if fname %}{% endif -%} - {{ stripped|e }}{{ modname|e }} - {%- if fname %}{% endif %} - {%- if pform and pform[0] %} ({{ pform|join(', ') }}){% endif -%} - {% if dep %}{{ _('Deprecated')}}:{% endif %} - {{ synops|e }}
- -{% endblock %} diff --git a/doc/_themes/pysidedocs/opensearch.xml b/doc/_themes/pysidedocs/opensearch.xml deleted file mode 100644 index 03875be4..00000000 --- a/doc/_themes/pysidedocs/opensearch.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - {{ project|e }} - {% trans docstitle=docstitle|e %}Search {{ docstitle }}{% endtrans %} - utf-8 - - {{ docstitle|e }} -{% block extra %} {# Put e.g. an element here. #} {% endblock %} - diff --git a/doc/_themes/pysidedocs/page.html b/doc/_themes/pysidedocs/page.html deleted file mode 100644 index 17a93016..00000000 --- a/doc/_themes/pysidedocs/page.html +++ /dev/null @@ -1,4 +0,0 @@ -{% extends "layout.html" %} -{% block body %} - {{ body }} -{% endblock %} diff --git a/doc/_themes/pysidedocs/search.html b/doc/_themes/pysidedocs/search.html deleted file mode 100644 index d7455327..00000000 --- a/doc/_themes/pysidedocs/search.html +++ /dev/null @@ -1,26 +0,0 @@ -{% extends "layout.html" %} -{% set title = _('Search') %} -{% set script_files = script_files + ['_static/searchtools.js'] %} -{% block body %} -
-

Search Results

-
- -

- {% trans %}Please activate JavaScript to enable the search - functionality.{% endtrans %} -

-
- {% if search_performed %} - {% if not search_results %} -

{{ _('Your search did not match any results.') }}

- {% endif %} - {% endif %} -
-
-
-{% endblock %} -{% block footer %} - {{ super() }} - -{% endblock %} diff --git a/doc/_themes/pysidedocs/searchbox.html b/doc/_themes/pysidedocs/searchbox.html new file mode 100644 index 00000000..55a97215 --- /dev/null +++ b/doc/_themes/pysidedocs/searchbox.html @@ -0,0 +1,12 @@ +{%- if pagename != "search" %} + + +{%- endif %} diff --git a/doc/_themes/pysidedocs/static/.directory b/doc/_themes/pysidedocs/static/.directory deleted file mode 100644 index 176338d6..00000000 --- a/doc/_themes/pysidedocs/static/.directory +++ /dev/null @@ -1,3 +0,0 @@ -[Dolphin] -ShowPreview=true -Timestamp=2009,10,13,10,27,39 diff --git a/doc/_themes/pysidedocs/static/doctools.js b/doc/_themes/pysidedocs/static/doctools.js deleted file mode 100644 index 9447678c..00000000 --- a/doc/_themes/pysidedocs/static/doctools.js +++ /dev/null @@ -1,232 +0,0 @@ -/// XXX: make it cross browser - -/** - * make the code below compatible with browsers without - * an installed firebug like debugger - */ -if (!window.console || !console.firebug) { - var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", - "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; - window.console = {}; - for (var i = 0; i < names.length; ++i) - window.console[names[i]] = function() {} -} - -/** - * small helper function to urldecode strings - */ -jQuery.urldecode = function(x) { - return decodeURIComponent(x).replace(/\+/g, ' '); -} - -/** - * small helper function to urlencode strings - */ -jQuery.urlencode = encodeURIComponent; - -/** - * This function returns the parsed url parameters of the - * current request. Multiple values per key are supported, - * it will always return arrays of strings for the value parts. - */ -jQuery.getQueryParameters = function(s) { - if (typeof s == 'undefined') - s = document.location.search; - var parts = s.substr(s.indexOf('?') + 1).split('&'); - var result = {}; - for (var i = 0; i < parts.length; i++) { - var tmp = parts[i].split('=', 2); - var key = jQuery.urldecode(tmp[0]); - var value = jQuery.urldecode(tmp[1]); - if (key in result) - result[key].push(value); - else - result[key] = [value]; - } - return result; -} - -/** - * small function to check if an array contains - * a given item. - */ -jQuery.contains = function(arr, item) { - for (var i = 0; i < arr.length; i++) { - if (arr[i] == item) - return true; - } - return false; -} - -/** - * highlight a given string on a jquery object by wrapping it in - * span elements with the given class name. - */ -jQuery.fn.highlightText = function(text, className) { - function highlight(node) { - if (node.nodeType == 3) { - var val = node.nodeValue; - var pos = val.toLowerCase().indexOf(text); - if (pos >= 0 && !jQuery.className.has(node.parentNode, className)) { - var span = document.createElement("span"); - span.className = className; - span.appendChild(document.createTextNode(val.substr(pos, text.length))); - node.parentNode.insertBefore(span, node.parentNode.insertBefore( - document.createTextNode(val.substr(pos + text.length)), - node.nextSibling)); - node.nodeValue = val.substr(0, pos); - } - } - else if (!jQuery(node).is("button, select, textarea")) { - jQuery.each(node.childNodes, function() { - highlight(this) - }); - } - } - return this.each(function() { - highlight(this); - }); -} - -/** - * Small JavaScript module for the documentation. - */ -var Documentation = { - - init : function() { - this.fixFirefoxAnchorBug(); - this.highlightSearchWords(); - this.initModIndex(); - }, - - /** - * i18n support - */ - TRANSLATIONS : {}, - PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, - LOCALE : 'unknown', - - // gettext and ngettext don't access this so that the functions - // can savely bound to a different name (_ = Documentation.gettext) - gettext : function(string) { - var translated = Documentation.TRANSLATIONS[string]; - if (typeof translated == 'undefined') - return string; - return (typeof translated == 'string') ? translated : translated[0]; - }, - - ngettext : function(singular, plural, n) { - var translated = Documentation.TRANSLATIONS[singular]; - if (typeof translated == 'undefined') - return (n == 1) ? singular : plural; - return translated[Documentation.PLURALEXPR(n)]; - }, - - addTranslations : function(catalog) { - for (var key in catalog.messages) - this.TRANSLATIONS[key] = catalog.messages[key]; - this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); - this.LOCALE = catalog.locale; - }, - - /** - * add context elements like header anchor links - */ - addContextElements : function() { - $('div[id] > :header:first').each(function() { - $('\u00B6'). - attr('href', '#' + this.id). - attr('title', _('Permalink to this headline')). - appendTo(this); - }); - $('dt[id]').each(function() { - $('\u00B6'). - attr('href', '#' + this.id). - attr('title', _('Permalink to this definition')). - appendTo(this); - }); - }, - - /** - * workaround a firefox stupidity - */ - fixFirefoxAnchorBug : function() { - if (document.location.hash && $.browser.mozilla) - window.setTimeout(function() { - document.location.href += ''; - }, 10); - }, - - /** - * highlight the search words provided in the url in the text - */ - highlightSearchWords : function() { - var params = $.getQueryParameters(); - var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; - if (terms.length) { - var body = $('div.body'); - window.setTimeout(function() { - $.each(terms, function() { - body.highlightText(this.toLowerCase(), 'highlight'); - }); - }, 10); - $('') - .appendTo($('.sidebar .this-page-menu')); - } - }, - - /** - * init the modindex toggle buttons - */ - initModIndex : function() { - var togglers = $('img.toggler').click(function() { - var src = $(this).attr('src'); - var idnum = $(this).attr('id').substr(7); - console.log($('tr.cg-' + idnum).toggle()); - if (src.substr(-9) == 'minus.png') - $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); - else - $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); - }).css('display', ''); - if (DOCUMENTATION_OPTIONS.COLLAPSE_MODINDEX) { - togglers.click(); - } - }, - - /** - * helper function to hide the search marks again - */ - hideSearchWords : function() { - $('.sidebar .this-page-menu li.highlight-link').fadeOut(300); - $('span.highlight').removeClass('highlight'); - }, - - /** - * make the url absolute - */ - makeURL : function(relativeURL) { - return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; - }, - - /** - * get the current relative url - */ - getCurrentURL : function() { - var path = document.location.pathname; - var parts = path.split(/\//); - $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { - if (this == '..') - parts.pop(); - }); - var url = parts.join('/'); - return path.substring(url.lastIndexOf('/') + 1, path.length - 1); - } -}; - -// quick alias for translations -_ = Documentation.gettext; - -$(document).ready(function() { - Documentation.init(); -}); diff --git a/doc/_themes/pysidedocs/static/jquery.js b/doc/_themes/pysidedocs/static/jquery.js deleted file mode 100644 index 82b98e1d..00000000 --- a/doc/_themes/pysidedocs/static/jquery.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * jQuery 1.2.6 - New Wave Javascript - * - * Copyright (c) 2008 John Resig (jquery.com) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * $Date: 2008-05-24 14:22:17 -0400 (Sat, 24 May 2008) $ - * $Rev: 5685 $ - */ -(function(){var _jQuery=window.jQuery,_$=window.$;var jQuery=window.jQuery=window.$=function(selector,context){return new jQuery.fn.init(selector,context);};var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,isSimple=/^.[^:#\[\.]*$/,undefined;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem){if(elem.id!=match[3])return jQuery().find(selector);return jQuery(elem);}selector=[];}}else -return jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(jQuery.makeArray(selector));},jquery:"1.2.6",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;return jQuery.inArray(elem&&elem.jquery?elem[0]:elem,this);},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value===undefined)return this[0]&&jQuery[type||"attr"](this[0],name);else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else -return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else -selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return this.pushStack(jQuery.unique(jQuery.merge(this.get(),typeof selector=='string'?jQuery(selector):jQuery.makeArray(selector))));},is:function(selector){return!!selector&&jQuery.multiFilter(selector,this).length>0;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=jQuery.makeArray(value);jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else -this.value=value;});},html:function(value){return value==undefined?(this[0]?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value===undefined){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data===undefined&&this.length)data=jQuery.data(this[0],key);return data===undefined&&parts[1]?this.data(parts[0]):data;}else -return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script"))scripts=scripts.add(elem);else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.fn.init.prototype=jQuery.fn;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else -jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}function now(){return+new Date;}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==i){target=this;--i;}for(;i-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else -jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret,style=elem.style;function color(elem){if(!jQuery.browser.safari)return false;var ret=defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=style.outline;style.outline="0 solid black";style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&style&&style[name])ret=style[name];else if(defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var computedStyle=defaultView.getComputedStyle(elem,null);if(computedStyle&&!color(elem))ret=computedStyle.getPropertyValue(name);else{var swap=[],stack=[],a=elem,i=0;for(;a&&color(a);a=a.parentNode)stack.unshift(a);for(;i]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("",""]||!tags.indexOf("",""]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
"]||!tags.indexOf("",""]||(!tags.indexOf("",""]||!tags.indexOf("",""]||jQuery.browser.msie&&[1,"div
","
"]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf(""&&tags.indexOf("=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else -ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var notxml=!jQuery.isXMLDoc(elem),set=value!==undefined,msie=jQuery.browser.msie;name=notxml&&jQuery.props[name]||name;if(elem.tagName){var special=/href|src|style/.test(name);if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(name in elem&¬xml&&!special){if(set){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem[name]=value;}if(jQuery.nodeName(elem,"form")&&elem.getAttributeNode(name))return elem.getAttributeNode(name).nodeValue;return elem[name];}if(msie&¬xml&&name=="style")return jQuery.attr(elem.style,"cssText",value);if(set)elem.setAttribute(name,""+value);var attr=msie&¬xml&&special?elem.getAttribute(name,2):elem.getAttribute(name);return attr===null?undefined:attr;}if(msie&&name=="opacity"){if(set){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(value)+''=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100)+'':"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(set)elem[name]=value;return elem[name];},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(array!=null){var i=array.length;if(i==null||array.split||array.setInterval||array.call)ret[0]=array;else -while(i)ret[--i]=array[i];}return ret;},inArray:function(elem,array){for(var i=0,length=array.length;i*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});function num(elem,prop){return elem[0]&&parseInt(jQuery.curCSS(elem[0],prop,true),10)||0;}var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return im[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false,re=quickChild,m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[],cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&n!=elem)r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=this.proxy(fn,function(){return fn.apply(this,arguments);});handler.data=data;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){if(typeof jQuery!="undefined"&&!jQuery.event.triggered)return jQuery.event.handle.apply(arguments.callee.elem,arguments);});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else -for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event){data.unshift({type:type,target:elem,preventDefault:function(){},stopPropagation:function(){},timeStamp:now()});data[0][expando]=true;}data[0].type=type;if(exclusive)data[0].exclusive=true;var handle=jQuery.data(elem,"handle");if(handle)val=handle.apply(elem,data);if((!fn||(jQuery.nodeName(elem,'a')&&type=="click"))&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val,ret,namespace,all,handlers;event=arguments[0]=jQuery.event.fix(event||window.event);namespace=event.type.split(".");event.type=namespace[0];namespace=namespace[1];all=!namespace&&!event.exclusive;handlers=(jQuery.data(this,"events")||{})[event.type];for(var j in handlers){var handler=handlers[j];if(all||handler.type==namespace){event.handler=handler;event.data=handler.data;ret=handler.apply(this,arguments);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}return val;},fix:function(event){if(event[expando]==true)return event;var originalEvent=event;event={originalEvent:originalEvent};var props="altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target timeStamp toElement type view wheelDelta which".split(" ");for(var i=props.length;i;i--)event[props[i]]=originalEvent[props[i]];event[expando]=true;event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};event.timeStamp=event.timeStamp||now();if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=event.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},proxy:function(fn,proxy){proxy.guid=fn.guid=fn.guid||proxy.guid||this.guid++;return proxy;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;event.type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;event.type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){var one=jQuery.event.proxy(fn||data,function(event){jQuery(this).unbind(event,one);return(fn||data).apply(this,arguments);});return this.each(function(){jQuery.event.add(this,type,one,fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){return this[0]&&jQuery.event.trigger(type,data,this[0],false,fn);},toggle:function(fn){var args=arguments,i=1;while(i=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("
").append(res.responseText.replace(//g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=now();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{url:location.href,global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));var jsonp,jsre=/=\?(&|$)/g,status,data,type=s.type.toUpperCase();if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(type=="GET"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&type=="GET"){var ts=now();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&type=="GET"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");var remote=/^(?:\w+:)?\/\/([^\/?#]+)/;if(s.dataType=="script"&&type=="GET"&&remote.test(s.url)&&remote.exec(s.url)[1]!=location.host){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xhr=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();if(s.username)xhr.open(type,s.url,s.async,s.username,s.password);else -xhr.open(type,s.url,s.async);try{if(s.data)xhr.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xhr.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");xhr.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend&&s.beforeSend(xhr,s)===false){s.global&&jQuery.active--;xhr.abort();return false;}if(s.global)jQuery.event.trigger("ajaxSend",[xhr,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xhr&&(xhr.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xhr)&&"error"||s.ifModified&&jQuery.httpNotModified(xhr,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xhr,s.dataType,s.dataFilter);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xhr.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else -jQuery.handleError(s,xhr,status);complete();if(s.async)xhr=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xhr){xhr.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xhr.send(s.data);}catch(e){jQuery.handleError(s,xhr,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xhr,s]);}function complete(){if(s.complete)s.complete(xhr,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xhr,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xhr;},handleError:function(s,xhr,status,e){if(s.error)s.error(xhr,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xhr,s,e]);},active:0,httpSuccess:function(xhr){try{return!xhr.status&&location.protocol=="file:"||(xhr.status>=200&&xhr.status<300)||xhr.status==304||xhr.status==1223||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpNotModified:function(xhr,url){try{var xhrRes=xhr.getResponseHeader("Last-Modified");return xhr.status==304||xhrRes==jQuery.lastModified[url]||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpData:function(xhr,type,filter){var ct=xhr.getResponseHeader("content-type"),xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0,data=xml?xhr.responseXML:xhr.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(filter)data=filter(data,type);if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else -for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else -s.push(encodeURIComponent(j)+"="+encodeURIComponent(jQuery.isFunction(a[j])?a[j]():a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle.apply(this,arguments):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall),p,hidden=jQuery(this).is(":hidden"),self=this;for(p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return opt.complete.call(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else -e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.call(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(elem){type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",jQuery.makeArray(array));}return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].call(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:jQuery.fx.speeds[opt.duration])||jQuery.fx.speeds.def;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.call(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.call(this.elem,this.now,this);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=now();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;ithis.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done)this.options.complete.call(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.extend(jQuery.fx,{speeds:{slow:600,fast:200,def:400},step:{scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}}});jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),css=jQuery.curCSS,fixed=css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||css(offsetChild,"position")=="absolute"))||(mozilla&&css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l,10)||0;top+=parseInt(t,10)||0;}return results;};jQuery.fn.extend({position:function(){var left=0,top=0,results;if(this[0]){var offsetParent=this.offsetParent(),offset=this.offset(),parentOffset=/^body|html$/i.test(offsetParent[0].tagName)?{top:0,left:0}:offsetParent.offset();offset.top-=num(this,'marginTop');offset.left-=num(this,'marginLeft');parentOffset.top+=num(offsetParent,'borderTopWidth');parentOffset.left+=num(offsetParent,'borderLeftWidth');results={top:offset.top-parentOffset.top,left:offset.left-parentOffset.left};}return results;},offsetParent:function(){var offsetParent=this[0].offsetParent;while(offsetParent&&(!/^body|html$/i.test(offsetParent.tagName)&&jQuery.css(offsetParent,'position')=='static'))offsetParent=offsetParent.offsetParent;return jQuery(offsetParent);}});jQuery.each(['Left','Top'],function(i,name){var method='scroll'+name;jQuery.fn[method]=function(val){if(!this[0])return;return val!=undefined?this.each(function(){this==window||this==document?window.scrollTo(!i?val:jQuery(window).scrollLeft(),i?val:jQuery(window).scrollTop()):this[method]=val;}):this[0]==window||this[0]==document?self[i?'pageYOffset':'pageXOffset']||jQuery.boxModel&&document.documentElement[method]||document.body[method]:this[0][method];};});jQuery.each(["Height","Width"],function(i,name){var tl=i?"Left":"Top",br=i?"Right":"Bottom";jQuery.fn["inner"+name]=function(){return this[name.toLowerCase()]()+num(this,"padding"+tl)+num(this,"padding"+br);};jQuery.fn["outer"+name]=function(margin){return this["inner"+name]()+num(this,"border"+tl+"Width")+num(this,"border"+br+"Width")+(margin?num(this,"margin"+tl)+num(this,"margin"+br):0);};});})(); \ No newline at end of file diff --git a/doc/_themes/pysidedocs/static/pysidedocs.css b/doc/_themes/pysidedocs/static/pysidedocs.css index 5ae39236..708ddf77 100644 --- a/doc/_themes/pysidedocs/static/pysidedocs.css +++ b/doc/_themes/pysidedocs/static/pysidedocs.css @@ -10,7 +10,6 @@ html { body { margin: 0; padding: 0; - text-align: center; background-color: #EBEBEB; height: 100%; color: #333; @@ -20,7 +19,7 @@ strong { font-weight:bold; } -#body { +.document { padding-bottom: 90px; } @@ -32,8 +31,8 @@ strong { background-color: white; } -#footer { - position:absolute; +.footer { + position: absolute; bottom: 0px; margin-top: 50px; text-align:center; @@ -44,40 +43,40 @@ strong { width: 100%; } -#footer img { +.footer img { margin-left: 8px; margin-right: 8px; } -#sidebar { +.sphinxsidebar { float: left; width: 250px; padding: 0px 10px 0px 10px; text-align: left; } -#sidebar ul { +.sphinxsidebar ul { padding: 0px; margin: 0px; list-style-position: inside; } -#sidebar > ul { +.sphinxsidebar > ul { padding: 0px; margin: 0px; } -#sidebar ul li { +.sphinxsidebar ul li { margin-left: 10px; padding: 0px; } -#sidebar h3, #sidebar h3 a { +.sphinxsidebar h3, .sphinxsidebar h3 a { font-weight: bold; color: #333; } -#body > div.section { +.documentwrapper { margin-left: 270px; text-align: left; background-color: #ffffff; @@ -93,7 +92,6 @@ h1 { padding-bottom: 15px; padding-top: 15px; border-bottom: 1px solid #c2c2c2; - text-transform:uppercase; margin-right: -100px; position: relative; left: -50px; @@ -137,8 +135,23 @@ pre * { font: 100% monospace; } +.pre { + font: 100% monospace; +} + .headerlink { - display: none; + font-size: 100%; + color: inherit; + float: right; + visibility: Hidden +} + +h1 .headerlink { + padding-right: 50px; +} + +h1:hover .headerlink, h2:hover .headerlink, h3:hover .headerlink { + visibility: Visible; } a, a:visited { @@ -181,6 +194,11 @@ div.warning { border: 1px solid #f66; } +div.seealso { + background-color: #ffffcc; + border: 1px solid #ffff66; +} + div.note { border: 1px solid #e3e3e3; } @@ -246,26 +264,24 @@ hr { } /******************* TOPO *****************************/ -#header { +.header { background-image: url(bg_topo.jpg); background-repeat: repeat-x; height: 147px; } -#header_container { +.header_container { background-image: url(bg_header.png); background-repeat: no-repeat; background-position: 100px 0px; } -#logo { - background-image: url(pysidelogo.png); - background-repeat: no-repeat; -/* background-position: 0px 4px; */ - height: 112px; +.logo { + text-align: left; + margin-bottom: 10px; } -#search_box { +#searchbox { border-top: 1px solid #989898; padding-top: 10px; margin-left: -10px; @@ -333,31 +349,39 @@ em { /******** REL bar *********/ -#relbar { - padding: 0px 10px 0px 10px; +.related { + display: inline; +} + +.related ul { + padding: 0px 0px 0px 10px; margin: 0px; text-align: left; background-image: url(relbar_bg.png); } -#relbar li { +.related li { display: inline; color: white; font-weight: bold; } -#relbar li a { +.related li a { color: inherit; line-height: 35px; font-weight: bold; vertical-align: middle; } -#relbar li.right { +.related li.right { float: right; margin-right: 5px; } +.related h3 { + display: none; +} + .align-center { text-align: center; } @@ -390,3 +414,62 @@ img { table.footnote { margin: 0px; } + +#synopsis table, table.field-list { + margin: 0px; +} + +tt.descname { + font-size: 120%; + font-weight: bold; +} + +#functions ul, #virtual-functions ul, #slots ul, #signals ul, #static-functions ul { + list-style: none; + margin: 0px; + padding: 10px; + border: 1px solid #ddd; + background-color: #f4f4f4; + -moz-border-radius:10px; + -webkit-border-radius:10px; + -khtml-border-radius:10px; +} + +#synopsis span.pre { + color: #009491; + font-weight: bolder; +} + +#detailed-description .class dt, #detailed-description .method dt, #detailed-description .attribute dt, #detailed-description .function dt { + margin: 0px; + padding: 10px; + border: 1px solid #ddd; + background-color: #f4f4f4; + -moz-border-radius:10px; + -webkit-border-radius:10px; + -khtml-border-radius:10px; +} + +.pysidetoc ul { + list-style: none; + padding: 0px; + margin: 0px; +} + +.pysidetoc em { + font-style: normal; +} + +.pysidetoc strong { + display: block; + padding: 5px; + border: 1px solid #ddd; + background-color: #f4f4f4; + -moz-border-radius:6px; + -webkit-border-radius:6px; + -khtml-border-radius:6px; +} + +.hide { + display: none; +} diff --git a/doc/_themes/pysidedocs/static/searchtools.js b/doc/_themes/pysidedocs/static/searchtools.js deleted file mode 100644 index e0226258..00000000 --- a/doc/_themes/pysidedocs/static/searchtools.js +++ /dev/null @@ -1,467 +0,0 @@ -/** - * helper function to return a node containing the - * search summary for a given text. keywords is a list - * of stemmed words, hlwords is the list of normal, unstemmed - * words. the first one is used to find the occurance, the - * latter for highlighting it. - */ - -jQuery.makeSearchSummary = function(text, keywords, hlwords) { - var textLower = text.toLowerCase(); - var start = 0; - $.each(keywords, function() { - var i = textLower.indexOf(this.toLowerCase()); - if (i > -1) - start = i; - }); - start = Math.max(start - 120, 0); - var excerpt = ((start > 0) ? '...' : '') + - $.trim(text.substr(start, 240)) + - ((start + 240 - text.length) ? '...' : ''); - var rv = $('
').text(excerpt); - $.each(hlwords, function() { - rv = rv.highlightText(this, 'highlight'); - }); - return rv; -} - -/** - * Porter Stemmer - */ -var PorterStemmer = function() { - - var step2list = { - ational: 'ate', - tional: 'tion', - enci: 'ence', - anci: 'ance', - izer: 'ize', - bli: 'ble', - alli: 'al', - entli: 'ent', - eli: 'e', - ousli: 'ous', - ization: 'ize', - ation: 'ate', - ator: 'ate', - alism: 'al', - iveness: 'ive', - fulness: 'ful', - ousness: 'ous', - aliti: 'al', - iviti: 'ive', - biliti: 'ble', - logi: 'log' - }; - - var step3list = { - icate: 'ic', - ative: '', - alize: 'al', - iciti: 'ic', - ical: 'ic', - ful: '', - ness: '' - }; - - var c = "[^aeiou]"; // consonant - var v = "[aeiouy]"; // vowel - var C = c + "[^aeiouy]*"; // consonant sequence - var V = v + "[aeiou]*"; // vowel sequence - - var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 - var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 - var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 - var s_v = "^(" + C + ")?" + v; // vowel in stem - - this.stemWord = function (w) { - var stem; - var suffix; - var firstch; - var origword = w; - - if (w.length < 3) - return w; - - var re; - var re2; - var re3; - var re4; - - firstch = w.substr(0,1); - if (firstch == "y") - w = firstch.toUpperCase() + w.substr(1); - - // Step 1a - re = /^(.+?)(ss|i)es$/; - re2 = /^(.+?)([^s])s$/; - - if (re.test(w)) - w = w.replace(re,"$1$2"); - else if (re2.test(w)) - w = w.replace(re2,"$1$2"); - - // Step 1b - re = /^(.+?)eed$/; - re2 = /^(.+?)(ed|ing)$/; - if (re.test(w)) { - var fp = re.exec(w); - re = new RegExp(mgr0); - if (re.test(fp[1])) { - re = /.$/; - w = w.replace(re,""); - } - } - else if (re2.test(w)) { - var fp = re2.exec(w); - stem = fp[1]; - re2 = new RegExp(s_v); - if (re2.test(stem)) { - w = stem; - re2 = /(at|bl|iz)$/; - re3 = new RegExp("([^aeiouylsz])\\1$"); - re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); - if (re2.test(w)) - w = w + "e"; - else if (re3.test(w)) { - re = /.$/; - w = w.replace(re,""); - } - else if (re4.test(w)) - w = w + "e"; - } - } - - // Step 1c - re = /^(.+?)y$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(s_v); - if (re.test(stem)) - w = stem + "i"; - } - - // Step 2 - re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - suffix = fp[2]; - re = new RegExp(mgr0); - if (re.test(stem)) - w = stem + step2list[suffix]; - } - - // Step 3 - re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - suffix = fp[2]; - re = new RegExp(mgr0); - if (re.test(stem)) - w = stem + step3list[suffix]; - } - - // Step 4 - re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; - re2 = /^(.+?)(s|t)(ion)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(mgr1); - if (re.test(stem)) - w = stem; - } - else if (re2.test(w)) { - var fp = re2.exec(w); - stem = fp[1] + fp[2]; - re2 = new RegExp(mgr1); - if (re2.test(stem)) - w = stem; - } - - // Step 5 - re = /^(.+?)e$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(mgr1); - re2 = new RegExp(meq1); - re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); - if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) - w = stem; - } - re = /ll$/; - re2 = new RegExp(mgr1); - if (re.test(w) && re2.test(w)) { - re = /.$/; - w = w.replace(re,""); - } - - // and turn initial Y back to y - if (firstch == "y") - w = firstch.toLowerCase() + w.substr(1); - return w; - } -} - - -/** - * Search Module - */ -var Search = { - - _index : null, - _queued_query : null, - _pulse_status : -1, - - init : function() { - var params = $.getQueryParameters(); - if (params.q) { - var query = params.q[0]; - $('input[name="q"]')[0].value = query; - this.performSearch(query); - } - }, - - /** - * Sets the index - */ - setIndex : function(index) { - var q; - this._index = index; - if ((q = this._queued_query) !== null) { - this._queued_query = null; - Search.query(q); - } - }, - - hasIndex : function() { - return this._index !== null; - }, - - deferQuery : function(query) { - this._queued_query = query; - }, - - stopPulse : function() { - this._pulse_status = 0; - }, - - startPulse : function() { - if (this._pulse_status >= 0) - return; - function pulse() { - Search._pulse_status = (Search._pulse_status + 1) % 4; - var dotString = ''; - for (var i = 0; i < Search._pulse_status; i++) - dotString += '.'; - Search.dots.text(dotString); - if (Search._pulse_status > -1) - window.setTimeout(pulse, 500); - }; - pulse(); - }, - - /** - * perform a search for something - */ - performSearch : function(query) { - // create the required interface elements - this.out = $('#search-results'); - this.title = $('

' + _('Searching') + '

').appendTo(this.out); - this.dots = $('').appendTo(this.title); - this.status = $('

').appendTo(this.out); - this.output = $('