From 3ba895f573d54b68e4fa6f0ff388d071d1d69d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Pereira?= Date: Tue, 24 Apr 2018 11:42:10 +0100 Subject: [PATCH] Refactor and fixes Python binding Python binding was broke since commit b1f37a8. This is a fix and to some degree a refactor. The binding build is now integrated. Controlled by the CMake QTERMWIDGET_BUILD_PYTHON_BINDING option. CMake components taken from https://cgit.kde.org/pykde5.git/. No need to reinvent the wheel. Closes https://github.com/lxqt/qtermwidget/issues/135. --- CMakeLists.txt | 7 ++ pyqt/CMakeLists.txt | 61 ++++++++++++++ pyqt/README.md | 36 --------- pyqt/{config.py.in => __init__.py} | 0 pyqt/cmake/COPYING-CMAKE-SCRIPTS | 22 +++++ pyqt/cmake/FindPyQt5.cmake | 53 ++++++++++++ pyqt/cmake/FindPyQt5.py | 28 +++++++ pyqt/cmake/FindPythonLibrary.cmake | 73 +++++++++++++++++ pyqt/cmake/FindSIP.cmake | 64 +++++++++++++++ pyqt/cmake/FindSIP.py | 15 ++++ pyqt/cmake/PythonCompile.py | 4 + pyqt/cmake/PythonMacros.cmake | 82 +++++++++++++++++++ pyqt/cmake/SIPMacros.cmake | 124 +++++++++++++++++++++++++++++ pyqt/config-old.py | 85 -------------------- pyqt/config.py | 104 ------------------------ pyqt/qtermwidgetconfig.py | 0 pyqt/{ => sip}/qtermwidget.sip | 5 +- 17 files changed, 537 insertions(+), 226 deletions(-) create mode 100644 pyqt/CMakeLists.txt delete mode 100644 pyqt/README.md rename pyqt/{config.py.in => __init__.py} (100%) create mode 100644 pyqt/cmake/COPYING-CMAKE-SCRIPTS create mode 100644 pyqt/cmake/FindPyQt5.cmake create mode 100644 pyqt/cmake/FindPyQt5.py create mode 100644 pyqt/cmake/FindPythonLibrary.cmake create mode 100644 pyqt/cmake/FindSIP.cmake create mode 100644 pyqt/cmake/FindSIP.py create mode 100644 pyqt/cmake/PythonCompile.py create mode 100644 pyqt/cmake/PythonMacros.cmake create mode 100644 pyqt/cmake/SIPMacros.cmake delete mode 100755 pyqt/config-old.py delete mode 100755 pyqt/config.py delete mode 100644 pyqt/qtermwidgetconfig.py rename pyqt/{ => sip}/qtermwidget.sip (97%) diff --git a/CMakeLists.txt b/CMakeLists.txt index b077d6cb..b99e1a41 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ set(LXQTBT_MINIMUM_VERSION "0.4.1") option(UPDATE_TRANSLATIONS "Update source translation translations/*.ts files" OFF) option(BUILD_EXAMPLE "Build example application. Default OFF." OFF) option(QTERMWIDGET_USE_UTEMPTER "Uses the libutempter library. Mainly for FreeBSD" OFF) +option(QTERMWIDGET_BUILD_PYTHON_BINDING "Build python binding" OFF) # just change version for releases set(QTERMWIDGET_VERSION_MAJOR "0") @@ -304,6 +305,12 @@ if(BUILD_EXAMPLE) endif() # end of example application +# python binding +if (QTERMWIDGET_BUILD_PYTHON_BINDING) + add_subdirectory(pyqt) +endif() +# end of python binding + CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" diff --git a/pyqt/CMakeLists.txt b/pyqt/CMakeLists.txt new file mode 100644 index 00000000..3ebaf5eb --- /dev/null +++ b/pyqt/CMakeLists.txt @@ -0,0 +1,61 @@ +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) + +# Match what's used in the main macros +cmake_policy(SET CMP0002 OLD) +find_package(PythonLibrary) + +include(PythonMacros) + +find_package(SIP) +include(SIPMacros) + +if(SIP_VERSION STRLESS "040f03") # These version numbers also appear in ../CMakeLists.txt + message(FATAL_ERROR "The version of SIP found is too old. 4.15.3 or later is needed.") +endif() + +find_package(PyQt5) +if(PYQT5_VERSION STRLESS "050101") # These version numbers also appear in ../CMakeLists.txt + message(FATAL_ERROR "The version of PyQt found is too old. 5.1.1 or later is required.") +endif() + +set(SIP_INCLUDES ${PYQT5_SIP_DIR} sip) +set(SIP_CONCAT_PARTS 8) +set(SIP_TAGS ALL WS_X11 ${PYQT5_VERSION_TAG}) +set(SIP_DISABLE_FEATURES VendorID PyQt_NoPrintRangeBug) + +# Use an extra option when compiling on Python 3. +if (PYTHON_VERSION_MAJOR GREATER 2) + if(PYQT5_VERSION STRGREATER "040904") + # Disable for newer PyQt + set(SIP_EXTRA_OPTIONS -P -g) + else () + set(SIP_EXTRA_OPTIONS -g) + endif() +else (PYTHON_VERSION_MAJOR GREATER 2) + if(PYQT5_VERSION STRGREATER "040904") + # Disable for newer PyQt + set(SIP_EXTRA_OPTIONS -P -g -x Py_v3) + else () + set(SIP_EXTRA_OPTIONS -g -x Py_v3) + endif() +endif () + +include_directories( + "${SIP_INCLUDE_DIR}" +) + +add_definitions(-D_REENTRANT -DSIP_PROTECTED_IS_PUBLIC -Dprotected=public) + +file(GLOB qtermwidget_files_sip sip/*.sip) +set(SIP_EXTRA_FILES_DEPEND "${qtermwidget_files_sip}") +add_sip_python_module(QTermWidget sip/qtermwidget.sip qtermwidget5) + +python_install(__init__.py "${PYTHON_SITE_PACKAGES_INSTALL_DIR}/PyQt5/qtermwidget") + +set (SIP_FILES_INSTALL_DIR "${CMAKE_INSTALL_DATAROOTDIR}/sip") + +install(DIRECTORY sip/ DESTINATION "${SIP_FILES_INSTALL_DIR}/PyQt5/qtermwidget" + PATTERN "*~" EXCLUDE # This sucks, why can't I just whitelist what I _do_ want? + PATTERN ".svn" EXCLUDE + PATTERN "*.in" EXCLUDE +) diff --git a/pyqt/README.md b/pyqt/README.md deleted file mode 100644 index 8117d4bf..00000000 --- a/pyqt/README.md +++ /dev/null @@ -1,36 +0,0 @@ -PyQt5 Bindings for QTermWidget -============================== - - -INSTALL: ------------- - -####1. Download, compile and install QTermWidget: - $ git clone https://github.com/lxqt/qtermwidget.git - $ cd qtermwidget && mkdir build && cd build - $ cmake .. - $ make - $ sudo make install -If `make install` command will not work just copy the `qtermwidget.so*` files to /usr/lib directory. -####2. Install PyQt5 and PyQt5-devel if not yet installed. -####3. Configure, compile and install Python bindings. Execute in terminal in the qtermwidget bindings folder: - $ cd pyqt/ - $ QT_SELECT=5 python config.py - $ make - $ sudo make install - -####4. You can run ./test.py to test the installed module. - - -ABOUT: ---------- -Curently maintained by: -- Pawel Koston - -Based on previous PyQt4 bindings by: -- Piotr "Riklaunim" Maliński , -- Alexander Slesarev - -PyQt5 QTermWidget Bindings -License: GPL3 - diff --git a/pyqt/config.py.in b/pyqt/__init__.py similarity index 100% rename from pyqt/config.py.in rename to pyqt/__init__.py diff --git a/pyqt/cmake/COPYING-CMAKE-SCRIPTS b/pyqt/cmake/COPYING-CMAKE-SCRIPTS new file mode 100644 index 00000000..6fc1e7e8 --- /dev/null +++ b/pyqt/cmake/COPYING-CMAKE-SCRIPTS @@ -0,0 +1,22 @@ + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pyqt/cmake/FindPyQt5.cmake b/pyqt/cmake/FindPyQt5.cmake new file mode 100644 index 00000000..b4a52e15 --- /dev/null +++ b/pyqt/cmake/FindPyQt5.cmake @@ -0,0 +1,53 @@ +# Find PyQt5 +# ~~~~~~~~~~ +# Copyright (c) 2014, Simon Edwards +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# +# PyQt5 website: http://www.riverbankcomputing.co.uk/pyqt/index.php +# +# Find the installed version of PyQt5. FindPyQt5 should only be called after +# Python has been found. +# +# This file defines the following variables: +# +# PYQT5_VERSION - The version of PyQt5 found expressed as a 6 digit hex number +# suitable for comparison as a string +# +# PYQT5_VERSION_STR - The version of PyQt5 as a human readable string. +# +# PYQT5_VERSION_TAG - The PyQt version tag using by PyQt's sip files. +# +# PYQT5_SIP_DIR - The directory holding the PyQt5 .sip files. +# +# PYQT5_SIP_FLAGS - The SIP flags used to build PyQt. + +IF(EXISTS PYQT5_VERSION) + # Already in cache, be silent + SET(PYQT5_FOUND TRUE) +ELSE(EXISTS PYQT5_VERSION) + + FIND_FILE(_find_pyqt5_py FindPyQt5.py PATHS ${CMAKE_MODULE_PATH}) + + EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} ${_find_pyqt5_py} OUTPUT_VARIABLE pyqt5_config) + IF(pyqt5_config) + STRING(REGEX REPLACE "^pyqt_version:([^\n]+).*$" "\\1" PYQT5_VERSION ${pyqt5_config}) + STRING(REGEX REPLACE ".*\npyqt_version_str:([^\n]+).*$" "\\1" PYQT5_VERSION_STR ${pyqt5_config}) + STRING(REGEX REPLACE ".*\npyqt_version_tag:([^\n]+).*$" "\\1" PYQT5_VERSION_TAG ${pyqt5_config}) + STRING(REGEX REPLACE ".*\npyqt_sip_dir:([^\n]+).*$" "\\1" PYQT5_SIP_DIR ${pyqt5_config}) + STRING(REGEX REPLACE ".*\npyqt_sip_flags:([^\n]+).*$" "\\1" PYQT5_SIP_FLAGS ${pyqt5_config}) + + SET(PYQT5_FOUND TRUE) + ENDIF(pyqt5_config) + + IF(PYQT5_FOUND) + IF(NOT PYQT5_FIND_QUIETLY) + MESSAGE(STATUS "Found PyQt5 version: ${PYQT5_VERSION_STR}") + ENDIF(NOT PYQT5_FIND_QUIETLY) + ELSE(PYQT5_FOUND) + IF(PYQT5_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find PyQt5.") + ENDIF(PYQT5_FIND_REQUIRED) + ENDIF(PYQT5_FOUND) + +ENDIF(EXISTS PYQT5_VERSION) diff --git a/pyqt/cmake/FindPyQt5.py b/pyqt/cmake/FindPyQt5.py new file mode 100644 index 00000000..318b9a30 --- /dev/null +++ b/pyqt/cmake/FindPyQt5.py @@ -0,0 +1,28 @@ +# Copyright (c) 2014, Simon Edwards +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +import PyQt5.Qt +import sys +import os.path + +print("pyqt_version:%06.0x" % PyQt5.Qt.PYQT_VERSION) +print("pyqt_version_str:%s" % PyQt5.Qt.PYQT_VERSION_STR) + +pyqt_version_tag = "" +in_t = False +for item in PyQt5.Qt.PYQT_CONFIGURATION["sip_flags"].split(' '): + if item=="-t": + in_t = True + elif in_t: + if item.startswith("Qt_5"): + pyqt_version_tag = item + else: + in_t = False +print("pyqt_version_tag:%s" % pyqt_version_tag) + +# FIXME This next line is just a little bit too crude. +pyqt_sip_dir = os.path.join(sys.prefix, "share", "sip", "PyQt5") +print("pyqt_sip_dir:%s" % pyqt_sip_dir) + +print("pyqt_sip_flags:%s" % PyQt5.Qt.PYQT_CONFIGURATION["sip_flags"]) diff --git a/pyqt/cmake/FindPythonLibrary.cmake b/pyqt/cmake/FindPythonLibrary.cmake new file mode 100644 index 00000000..78309b7d --- /dev/null +++ b/pyqt/cmake/FindPythonLibrary.cmake @@ -0,0 +1,73 @@ +# Find Python +# ~~~~~~~~~~~ +# Find the Python interpreter and related Python directories. +# +# This file defines the following variables: +# +# PYTHON_EXECUTABLE - The path and filename of the Python interpreter. +# +# PYTHON_SHORT_VERSION - The version of the Python interpreter found, +# excluding the patch version number. (e.g. 2.5 and not 2.5.1)) +# +# PYTHON_LONG_VERSION - The version of the Python interpreter found as a human +# readable string. +# +# PYTHON_SITE_PACKAGES_INSTALL_DIR - this cache variable can be used for installing +# own python modules. You may want to adjust this to be the +# same as ${PYTHON_SITE_PACKAGES_DIR}, but then admin +# privileges may be required for installation. +# +# PYTHON_SITE_PACKAGES_DIR - Location of the Python site-packages directory. +# +# PYTHON_INCLUDE_PATH - Directory holding the python.h include file. +# +# PYTHON_LIBRARY, PYTHON_LIBRARIES- Location of the Python library. + +# Copyright (c) 2007, Simon Edwards +# Copyright (c) 2012, Luca Beltrame +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +include(FindPackageHandleStandardArgs) + +find_package(PythonInterp) + +if (PYTHONINTERP_FOUND) + + option(INSTALL_PYTHON_FILES_IN_PYTHON_PREFIX "Install the Python files in the Python packages dir" FALSE) + + # Set the Python libraries to what we actually found for interpreters + set(Python_ADDITIONAL_VERSIONS "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}") + # These are kept for compatibility + set(PYTHON_SHORT_VERSION "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}") + set(PYTHON_LONG_VERSION ${PYTHON_VERSION_STRING}) + + find_package(PythonLibs QUIET) + + if(PYTHONLIBS_FOUND) + set(PYTHON_LIBRARY ${PYTHON_LIBRARIES}) + endif(PYTHONLIBS_FOUND) + + # Auto detect Python site-packages directory + execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(True))" + OUTPUT_VARIABLE PYTHON_SITE_PACKAGES_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + message(STATUS "Python system site-packages directory: ${PYTHON_SITE_PACKAGES_DIR}") + if(INSTALL_PYTHON_FILES_IN_PYTHON_PREFIX) + set(PYTHON_SITE_PACKAGES_INSTALL_DIR ${PYTHON_SITE_PACKAGES_DIR}) + else() + execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(True, prefix='${CMAKE_INSTALL_PREFIX}'))" + OUTPUT_VARIABLE PYTHON_SITE_PACKAGES_INSTALL_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + endif() + + if(NOT PYTHON_SITE_PACKAGES_INSTALL_DIR STREQUAL PYTHON_SITE_PACKAGES_DIR) + message(STATUS "The Python files will be installed to ${PYTHON_SITE_PACKAGES_INSTALL_DIR}. Make sure to add them to the Python search path (e.g. by setting PYTHONPATH)") + endif() + +endif(PYTHONINTERP_FOUND) + +find_package_handle_standard_args(PythonLibrary DEFAULT_MSG PYTHON_LIBRARY) diff --git a/pyqt/cmake/FindSIP.cmake b/pyqt/cmake/FindSIP.cmake new file mode 100644 index 00000000..954e50d2 --- /dev/null +++ b/pyqt/cmake/FindSIP.cmake @@ -0,0 +1,64 @@ +# Find SIP +# ~~~~~~~~ +# +# SIP website: http://www.riverbankcomputing.co.uk/sip/index.php +# +# Find the installed version of SIP. FindSIP should be called after Python +# has been found. +# +# This file defines the following variables: +# +# SIP_VERSION - The version of SIP found expressed as a 6 digit hex number +# suitable for comparison as a string. +# +# SIP_VERSION_STR - The version of SIP found as a human readable string. +# +# SIP_EXECUTABLE - Path and filename of the SIP command line executable. +# +# SIP_INCLUDE_DIR - Directory holding the SIP C++ header file. +# +# SIP_DEFAULT_SIP_DIR - Default directory where .sip files should be installed +# into. + +# Copyright (c) 2007, Simon Edwards +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + + + +IF(SIP_VERSION) + # Already in cache, be silent + SET(SIP_FOUND TRUE) +ELSE(SIP_VERSION) + + FIND_FILE(_find_sip_py FindSIP.py PATHS ${CMAKE_MODULE_PATH}) + + EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} ${_find_sip_py} OUTPUT_VARIABLE sip_config) + IF(sip_config) + STRING(REGEX REPLACE "^sip_version:([^\n]+).*$" "\\1" SIP_VERSION ${sip_config}) + STRING(REGEX REPLACE ".*\nsip_version_str:([^\n]+).*$" "\\1" SIP_VERSION_STR ${sip_config}) + STRING(REGEX REPLACE ".*\nsip_bin:([^\n]+).*$" "\\1" SIP_EXECUTABLE ${sip_config}) + IF(NOT SIP_DEFAULT_SIP_DIR) + STRING(REGEX REPLACE ".*\ndefault_sip_dir:([^\n]+).*$" "\\1" SIP_DEFAULT_SIP_DIR ${sip_config}) + ENDIF(NOT SIP_DEFAULT_SIP_DIR) + STRING(REGEX REPLACE ".*\nsip_inc_dir:([^\n]+).*$" "\\1" SIP_INCLUDE_DIR ${sip_config}) + FILE(TO_CMAKE_PATH ${SIP_DEFAULT_SIP_DIR} SIP_DEFAULT_SIP_DIR) + FILE(TO_CMAKE_PATH ${SIP_INCLUDE_DIR} SIP_INCLUDE_DIR) + IF(EXISTS ${SIP_EXECUTABLE}) + SET(SIP_FOUND TRUE) + ELSE() + MESSAGE(STATUS "Found SIP configuration but the sip executable could not be found.") + ENDIF() + ENDIF(sip_config) + + IF(SIP_FOUND) + IF(NOT SIP_FIND_QUIETLY) + MESSAGE(STATUS "Found SIP version: ${SIP_VERSION_STR}") + ENDIF(NOT SIP_FIND_QUIETLY) + ELSE(SIP_FOUND) + IF(SIP_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find SIP") + ENDIF(SIP_FIND_REQUIRED) + ENDIF(SIP_FOUND) + +ENDIF(SIP_VERSION) diff --git a/pyqt/cmake/FindSIP.py b/pyqt/cmake/FindSIP.py new file mode 100644 index 00000000..ecb734f2 --- /dev/null +++ b/pyqt/cmake/FindSIP.py @@ -0,0 +1,15 @@ +# FindSIP.py +# +# Copyright (c) 2007, Simon Edwards +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +import sys +import sipconfig + +sipcfg = sipconfig.Configuration() +print("sip_version:%06.0x" % sipcfg.sip_version) +print("sip_version_str:%s" % sipcfg.sip_version_str) +print("sip_bin:%s" % sipcfg.sip_bin) +print("default_sip_dir:%s" % sipcfg.default_sip_dir) +print("sip_inc_dir:%s" % sipcfg.sip_inc_dir) diff --git a/pyqt/cmake/PythonCompile.py b/pyqt/cmake/PythonCompile.py new file mode 100644 index 00000000..156fea28 --- /dev/null +++ b/pyqt/cmake/PythonCompile.py @@ -0,0 +1,4 @@ +# By Simon Edwards +# This file is in the public domain. +import py_compile, sys +sys.exit(py_compile.main()) diff --git a/pyqt/cmake/PythonMacros.cmake b/pyqt/cmake/PythonMacros.cmake new file mode 100644 index 00000000..6a82d883 --- /dev/null +++ b/pyqt/cmake/PythonMacros.cmake @@ -0,0 +1,82 @@ +# Python macros +# ~~~~~~~~~~~~~ +# Copyright (c) 2007, Simon Edwards +# Copyright (c) 2012, Luca Beltrame +# Copyright (c) 2012, Rolf Eike Beer +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# +# This file defines the following macros: +# +# PYTHON_INSTALL (SOURCE_FILE DESTINATION_DIR) +# Install the SOURCE_FILE, which is a Python .py file, into the +# destination directory during install. The file will be byte compiled +# and both the .py file and .pyc file will be installed. + +set(PYTHON_MACROS_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +macro(PYTHON_INSTALL SOURCE_FILE DESTINATION_DIR) + + find_file(_python_compile_py PythonCompile.py PATHS ${CMAKE_MODULE_PATH}) + + # Install the source file. + install(FILES ${SOURCE_FILE} DESTINATION ${DESTINATION_DIR}) + + # Byte compile and install the .pyc file, unless explicitly prevented by env.. + if("$ENV{PYTHONDONTWRITEBYTECODE}" STREQUAL "") + get_filename_component(_absfilename ${SOURCE_FILE} ABSOLUTE) + get_filename_component(_filename ${SOURCE_FILE} NAME) + get_filename_component(_filenamebase ${SOURCE_FILE} NAME_WE) + get_filename_component(_basepath ${SOURCE_FILE} PATH) + + if(WIN32) + # remove drive letter + string(REGEX REPLACE "^[a-zA-Z]:/" "/" _basepath "${_basepath}") + endif(WIN32) + + set(_bin_py ${CMAKE_CURRENT_BINARY_DIR}/${_basepath}/${_filename}) + + # Python 3.2 changed the pyc file location + if(PYTHON_VERSION_STRING VERSION_GREATER 3.1) + # To get the right version for suffix + set(_bin_pyc "${CMAKE_CURRENT_BINARY_DIR}/${_basepath}/__pycache__/${_filenamebase}.cpython-${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR}.pyc") + set(_py_install_dir "${DESTINATION_DIR}/__pycache__/") + else() + set(_bin_pyc "${CMAKE_CURRENT_BINARY_DIR}/${_basepath}/${_filenamebase}.pyc") + set(_py_install_dir "${DESTINATION_DIR}") + endif() + + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${_basepath}) + + # Setting because it will be displayed later, in compile_python_files + set(_message "Byte-compiling ${_bin_py} to ${_bin_pyc}") + + string(REPLACE "/" "_" _rule_name "${_basepath}/${_bin_pyc}") + add_custom_target("${_rule_name}" ALL) + + get_filename_component(_abs_bin_py ${_bin_py} ABSOLUTE) + if(_abs_bin_py STREQUAL _absfilename) # Don't copy the file onto itself. + add_custom_command( + TARGET "${_rule_name}" + COMMAND "${CMAKE_COMMAND}" -E echo "${_message}" + COMMAND "${PYTHON_EXECUTABLE}" "${_python_compile_py}" "${_bin_py}" + DEPENDS "${_absfilename}" + ) + else() + add_custom_command( + TARGET "${_rule_name}" + COMMAND "${CMAKE_COMMAND}" -E echo "${_message}" + COMMAND "${CMAKE_COMMAND}" -E copy "${_absfilename}" "${_bin_py}" + COMMAND "${PYTHON_EXECUTABLE}" "${_python_compile_py}" "${_bin_py}" + DEPENDS "${_absfilename}" + ) + endif() + + install(FILES ${_bin_pyc} DESTINATION "${_py_install_dir}") + unset(_py_install_dir) + unset(_message) + + endif("$ENV{PYTHONDONTWRITEBYTECODE}" STREQUAL "") + +endmacro(PYTHON_INSTALL) diff --git a/pyqt/cmake/SIPMacros.cmake b/pyqt/cmake/SIPMacros.cmake new file mode 100644 index 00000000..86c26077 --- /dev/null +++ b/pyqt/cmake/SIPMacros.cmake @@ -0,0 +1,124 @@ +# Macros for SIP +# ~~~~~~~~~~~~~~ +# Copyright (c) 2007, Simon Edwards +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# +# SIP website: http://www.riverbankcomputing.co.uk/sip/index.php +# +# This file defines the following macros: +# +# ADD_SIP_PYTHON_MODULE (MODULE_NAME MODULE_SIP [library1, libaray2, ...]) +# Specifies a SIP file to be built into a Python module and installed. +# MODULE_NAME is the name of Python module including any path name. (e.g. +# os.sys, Foo.bar etc). MODULE_SIP the path and filename of the .sip file +# to process and compile. libraryN are libraries that the Python module, +# which is typically a shared library, should be linked to. The built +# module will also be install into Python's site-packages directory. +# +# The behaviour of the ADD_SIP_PYTHON_MODULE macro can be controlled by a +# number of variables: +# +# SIP_INCLUDES - List of directories which SIP will scan through when looking +# for included .sip files. (Corresponds to the -I option for SIP.) +# +# SIP_TAGS - List of tags to define when running SIP. (Corresponds to the -t +# option for SIP.) +# +# SIP_CONCAT_PARTS - An integer which defines the number of parts the C++ code +# of each module should be split into. Defaults to 8. (Corresponds to the +# -j option for SIP.) +# +# SIP_DISABLE_FEATURES - List of feature names which should be disabled +# running SIP. (Corresponds to the -x option for SIP.) +# +# SIP_EXTRA_OPTIONS - Extra command line options which should be passed on to +# SIP. + +SET(SIP_INCLUDES) +SET(SIP_TAGS) +SET(SIP_CONCAT_PARTS 8) +SET(SIP_DISABLE_FEATURES) +SET(SIP_EXTRA_OPTIONS) + +MACRO(ADD_SIP_PYTHON_MODULE MODULE_NAME MODULE_SIP) + + SET(EXTRA_LINK_LIBRARIES ${ARGN}) + + STRING(REPLACE "." "/" _x ${MODULE_NAME}) + GET_FILENAME_COMPONENT(_parent_module_path ${_x} PATH) + GET_FILENAME_COMPONENT(_child_module_name ${_x} NAME) + + GET_FILENAME_COMPONENT(_module_path ${MODULE_SIP} PATH) + + if(_module_path STREQUAL "") + set(CMAKE_CURRENT_SIP_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") + else(_module_path STREQUAL "") + set(CMAKE_CURRENT_SIP_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/${_module_path}") + endif(_module_path STREQUAL "") + + GET_FILENAME_COMPONENT(_abs_module_sip ${MODULE_SIP} ABSOLUTE) + + # We give this target a long logical target name. + # (This is to avoid having the library name clash with any already + # install library names. If that happens then cmake dependancy + # tracking get confused.) + STRING(REPLACE "." "_" _logical_name ${MODULE_NAME}) + SET(_logical_name "python_module_${_logical_name}") + + FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_SIP_OUTPUT_DIR}) # Output goes in this dir. + + SET(_sip_includes) + FOREACH (_inc ${SIP_INCLUDES}) + GET_FILENAME_COMPONENT(_abs_inc ${_inc} ABSOLUTE) + LIST(APPEND _sip_includes -I ${_abs_inc}) + ENDFOREACH (_inc ) + + SET(_sip_tags) + FOREACH (_tag ${SIP_TAGS}) + LIST(APPEND _sip_tags -t ${_tag}) + ENDFOREACH (_tag) + + SET(_sip_x) + FOREACH (_x ${SIP_DISABLE_FEATURES}) + LIST(APPEND _sip_x -x ${_x}) + ENDFOREACH (_x ${SIP_DISABLE_FEATURES}) + + SET(_message "-DMESSAGE=Generating CPP code for module ${MODULE_NAME}") + SET(_sip_output_files) + FOREACH(CONCAT_NUM RANGE 0 ${SIP_CONCAT_PARTS} ) + IF( ${CONCAT_NUM} LESS ${SIP_CONCAT_PARTS} ) + SET(_sip_output_files ${_sip_output_files} ${CMAKE_CURRENT_SIP_OUTPUT_DIR}/sip${_child_module_name}part${CONCAT_NUM}.cpp ) + ENDIF( ${CONCAT_NUM} LESS ${SIP_CONCAT_PARTS} ) + ENDFOREACH(CONCAT_NUM RANGE 0 ${SIP_CONCAT_PARTS} ) + + IF(NOT WIN32) + SET(TOUCH_COMMAND touch) + ELSE(NOT WIN32) + SET(TOUCH_COMMAND echo) + # instead of a touch command, give out the name and append to the files + # this is basically what the touch command does. + FOREACH(filename ${_sip_output_files}) + FILE(APPEND filename "") + ENDFOREACH(filename ${_sip_output_files}) + ENDIF(NOT WIN32) + ADD_CUSTOM_COMMAND( + OUTPUT ${_sip_output_files} + COMMAND ${CMAKE_COMMAND} -E echo ${message} + COMMAND ${TOUCH_COMMAND} ${_sip_output_files} + COMMAND ${SIP_EXECUTABLE} ${_sip_tags} ${_sip_x} ${SIP_EXTRA_OPTIONS} -j ${SIP_CONCAT_PARTS} -c ${CMAKE_CURRENT_SIP_OUTPUT_DIR} ${_sip_includes} ${_abs_module_sip} + DEPENDS ${_abs_module_sip} ${SIP_EXTRA_FILES_DEPEND} + ) + # not sure if type MODULE could be uses anywhere, limit to cygwin for now + IF (CYGWIN) + ADD_LIBRARY(${_logical_name} MODULE ${_sip_output_files} ) + ELSE (CYGWIN) + ADD_LIBRARY(${_logical_name} SHARED ${_sip_output_files} ) + ENDIF (CYGWIN) + TARGET_LINK_LIBRARIES(${_logical_name} ${PYTHON_LIBRARY}) + TARGET_LINK_LIBRARIES(${_logical_name} ${EXTRA_LINK_LIBRARIES}) + SET_TARGET_PROPERTIES(${_logical_name} PROPERTIES PREFIX "" OUTPUT_NAME ${_child_module_name}) + + INSTALL(TARGETS ${_logical_name} DESTINATION "${PYTHON_SITE_PACKAGES_INSTALL_DIR}/${_parent_module_path}") + +ENDMACRO(ADD_SIP_PYTHON_MODULE) diff --git a/pyqt/config-old.py b/pyqt/config-old.py deleted file mode 100755 index b5eb76e0..00000000 --- a/pyqt/config-old.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# PyQt4 bindings for th QTermWidget project. -# -# Copyright (C) 2009 Piotr "Riklaunim" Maliński , -# Alexander Slesarev -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -import os -import sipconfig -from PyQt4 import pyqtconfig - -# The name of the SIP build file generated by SIP and used by the build -# system. -build_file = "qtermwidget.sbf" - -# Get the PyQt configuration information. -config = pyqtconfig.Configuration() - -# Get the extra SIP flags needed by the imported qt module. Note that -# this normally only includes those flags (-x and -t) that relate to SIP's -# versioning system. -qt_sip_flags = config.pyqt_sip_flags - -# Run SIP to generate the code. Note that we tell SIP where to find the qt -# module's specification files using the -I flag. -os.system(" ".join([config.sip_bin, "-c", ".", "-b", build_file, "-I", - config.pyqt_sip_dir, qt_sip_flags, "qtermwidget.sip"])) - -# We are going to install the SIP specification file for this module and -# its configuration module. -installs = [] - -installs.append(["qtermwidget.sip", os.path.join(config.default_sip_dir, - "qtermwidget")]) - -installs.append(["qtermwidgetconfig.py", config.default_mod_dir]) - -# Create the Makefile. The QtModuleMakefile class provided by the -# pyqtconfig module takes care of all the extra preprocessor, compiler and -# linker flags needed by the Qt library. -makefile = pyqtconfig.QtGuiModuleMakefile( - configuration = config, - build_file = build_file, - installs = installs) - -# Add the library we are wrapping. The name doesn't include any platform -# specific prefixes or extensions (e.g. the "lib" prefix on UNIX, or the -# ".dll" extension on Windows). -makefile.extra_lib_dirs.append("..") -makefile.extra_libs = ["qtermwidget4"] - -# Generate the Makefile itself. -makefile.generate() - -# Now we create the configuration module. This is done by merging a Python -# dictionary (whose values are normally determined dynamically) with a -# (static) template. -content = { - # Publish where the SIP specifications for this module will be - # installed. - "qtermwidget_sip_dir": config.default_sip_dir, - - # Publish the set of SIP flags needed by this module. As these are the - # same flags needed by the qt module we could leave it out, but this - # allows us to change the flags at a later date without breaking - # scripts that import the configuration module. - "qtermwidget_sip_flags": qt_sip_flags} - -# This creates the qtermwidgetconfig.py module from the qtermwidgetconfig.py.in -# template and the dictionary. -sipconfig.create_config_module("qtermwidgetconfig.py", "config.py.in", content) diff --git a/pyqt/config.py b/pyqt/config.py deleted file mode 100755 index 59252139..00000000 --- a/pyqt/config.py +++ /dev/null @@ -1,104 +0,0 @@ -import os -import sipconfig -import subprocess -import os -import site -import pprint -from distutils import sysconfig -from PyQt5 import QtCore -import PyQt5 - - -class Configuration(sipconfig.Configuration): - """The class that represents PyQt configuration values. - """ - - def getEnv(self, name, default): - return os.environ.get(name) or default - - def __init__(self): - qmake_bin = subprocess.check_output( - ["which", "qmake"], universal_newlines=True).strip(' \t\n\r') - qtconfig = subprocess.check_output( - [qmake_bin, "-query"], universal_newlines=True) - qtconfig = dict(x.split(":", 1) for x in qtconfig.splitlines()) - - self.pyQtIncludePath = self.getEnv( - 'PYQT_INCLUDE_PATH', '/usr/share/sip/PyQt5') - - pyqtconfig = { - "pyqt_config_args": "--confirm-license -v " + str(self.pyQtIncludePath) + " --qsci-api -q " + qmake_bin, - "pyqt_version": QtCore.PYQT_VERSION, - "pyqt_version_str": QtCore.PYQT_VERSION_STR, - "pyqt_bin_dir": PyQt5.__path__[0], - "pyqt_mod_dir": PyQt5.__path__[0], - "pyqt_sip_dir": str(self.pyQtIncludePath), - "pyqt_modules": "QtCore QtGui QtWidgets", # ... and many more - "pyqt_sip_flags": QtCore.PYQT_CONFIGURATION['sip_flags'], - "qt_version": QtCore.QT_VERSION, - "qt_edition": "free", - "qt_winconfig": "shared", - "qt_framework": 0, - "qt_threaded": 1, - "qt_dir": qtconfig['QT_INSTALL_PREFIX'], - "qt_data_dir": qtconfig['QT_INSTALL_DATA'], - "qt_archdata_dir": qtconfig['QT_INSTALL_DATA'], - "qt_inc_dir": qtconfig['QT_INSTALL_HEADERS'], - "qt_lib_dir": qtconfig['QT_INSTALL_LIBS'] - } - - macros = sipconfig._default_macros.copy() - macros['INCDIR_QT'] = qtconfig['QT_INSTALL_HEADERS'] - macros['LIBDIR_QT'] = qtconfig['QT_INSTALL_LIBS'] - macros['MOC'] = os.path.join(qtconfig['QT_INSTALL_BINS'], 'moc') - - sipconfig.Configuration.__init__(self, [pyqtconfig]) - self.set_build_macros(macros) - - -# The name of the SIP build file generated by SIP and used by the build system. -build_file = "qtermwidget.sbf" - -# Get the SIP configuration information. -config = Configuration() - -# Run SIP to generate the build_file -os.system(" ".join([config.sip_bin, '-I', str(config.pyQtIncludePath), str( - config.pyqt_sip_flags), "-b", build_file, "-o", "-c", ". " " qtermwidget.sip"])) - -installs = [] -installs.append(["qtermwidget.sip", os.path.join( - config.pyqt_sip_dir, "qtermwidget")]) -installs.append(["qtermwidgetconfig.py", config.pyqt_mod_dir]) - -makefile = sipconfig.SIPModuleMakefile( - configuration=config, build_file=build_file, installs=installs, qt=["QtCore", "QtGui", "QtWidgets"]) - -# Add the library we are wrapping. The name doesn't include any platform -# specific prefixes or extensions (e.g. the "lib" prefix on UNIX, or the -# ".dll" extension on Windows). -makefile.extra_lib_dirs.append("../lib/") -makefile.extra_lib_dirs.append("..") -makefile.extra_libs = ["qtermwidget5"] - -# Support for C++11 -makefile.extra_cxxflags.append('-std=c++11') - -# Generate the Makefile itself. -makefile.generate() - -content = { - # Publish where the SIP specifications for this module will be - # installed. - "qtermwidget_sip_dir": config.pyqt_sip_dir, - - # Publish the set of SIP flags needed by this module. As these are the - # same flags needed by the qt module we could leave it out, but this - # allows us to change the flags at a later date without breaking - # scripts that import the configuration module. - "qtermwidget_sip_flags": config.pyqt_sip_flags -} - -# This creates the qtermwidgetconfig.py module from the qtermwidgetconfig.py.in -# template and the dictionary. -sipconfig.create_config_module("qtermwidgetconfig.py", "config.py.in", content) diff --git a/pyqt/qtermwidgetconfig.py b/pyqt/qtermwidgetconfig.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pyqt/qtermwidget.sip b/pyqt/sip/qtermwidget.sip similarity index 97% rename from pyqt/qtermwidget.sip rename to pyqt/sip/qtermwidget.sip index d40f7fbb..dccf0765 100644 --- a/pyqt/qtermwidget.sip +++ b/pyqt/sip/qtermwidget.sip @@ -1,5 +1,8 @@ %Module QTermWidget +%ModuleHeaderCode +#pragma GCC visibility push(default) +%End %Import QtGui/QtGuimod.sip %Import QtCore/QtCoremod.sip @@ -19,7 +22,7 @@ public: ScrollBarRight=2 }; - enum KeyboardCursorShape + enum class KeyboardCursorShape { BlockCursor=0, UnderlineCursor=1,